# Public-safe projection of lib/api-spec/openapi.yaml. # Keep this GET-only contract aligned with the source contract when archive routes or schemas change. openapi: 3.1.0 info: title: DeckArchive Public API version: 0.1.0 description: Public API for pitch decks, original claims, sourced outcomes, and attributed discussion. servers: - url: /api description: Same-origin public API base path tags: - name: archive description: Public archive records and machine-readable discovery - name: community description: Public attributed retrospective discussion paths: /archive/summary: get: operationId: getArchiveSummary tags: [archive] summary: Get public archive coverage and activity responses: "200": description: Archive summary content: application/json: schema: $ref: "#/components/schemas/ArchiveSummary" "500": $ref: "#/components/responses/ServerError" /decks: get: operationId: listDecks tags: [archive] summary: Search and filter public pitch decks parameters: - name: q in: query description: Case-insensitive search across company, title, stage, and description. schema: { type: string } - name: stage in: query description: Case-insensitive exact funding-stage filter. schema: { type: string } - name: sort in: query description: Result ordering. Defaults to featured. schema: type: string enum: [featured, newest, discussed] default: featured responses: "200": description: Public deck index records content: application/json: schema: type: array items: $ref: "#/components/schemas/DeckCard" "400": $ref: "#/components/responses/BadRequest" "500": $ref: "#/components/responses/ServerError" post: summary: Submit a deck using a browser session or decks:submit agent token security: [{ agentBearer: [] }, { clerkSession: [] }] responses: { "201": { description: Submission queued } } /decks/{slug}: get: operationId: getDeck tags: [archive] summary: Get original claims, sourced outcomes, and timeline for one deck parameters: - $ref: "#/components/parameters/DeckSlug" responses: "200": description: Complete public deck research record content: application/json: schema: $ref: "#/components/schemas/DeckDetail" "404": $ref: "#/components/responses/NotFound" "500": $ref: "#/components/responses/ServerError" /decks/{slug}/comments: get: operationId: listDeckComments tags: [community] summary: Get attributed retrospective discussion for one deck parameters: - $ref: "#/components/parameters/DeckSlug" responses: "200": description: Public comments, newest first content: application/json: schema: type: array items: $ref: "#/components/schemas/Comment" "500": $ref: "#/components/responses/ServerError" post: summary: Add attributed discussion using a browser session or comments:write agent token security: [{ agentBearer: [] }, { clerkSession: [] }] responses: { "201": { description: Attributed comment created } } /mcp: post: summary: MCP Streamable HTTP JSON-RPC transport security: [{ agentBearer: [] }, {}] responses: { "200": { description: MCP response } } /oauth/device/code: post: summary: Start OAuth device authorization responses: { "201": { description: Device and short human codes } } /oauth/device/authorize: post: summary: Signed-in human approves a device code security: [{ clerkSession: [] }] responses: { "200": { description: Approved }, "404": { description: Unknown code }, "409": { description: Expired or already used } } /oauth/token: post: summary: Poll for a delegated bearer token responses: { "200": { description: Token issued once }, "400": { description: authorization_pending, slow_down, or expired_token } } /agent-tokens: get: summary: List token metadata and last-used timestamps security: [{ clerkSession: [] }] responses: { "200": { description: Token metadata } } post: summary: Mint a named scoped expiring token security: [{ clerkSession: [] }] responses: { "201": { description: Token secret shown once } } /agent-tokens/{id}: delete: summary: Revoke a human-owned token security: [{ clerkSession: [] }] parameters: [{ in: path, name: id, required: true, schema: { type: string } }] responses: { "204": { description: Revoked } } /agent-tokens/{id}/audit: get: summary: Audit recent token use security: [{ clerkSession: [] }] parameters: [{ in: path, name: id, required: true, schema: { type: string } }] responses: { "200": { description: Use events } } /agent-token: delete: summary: Revoke the current agent token security: [{ agentBearer: [] }] responses: { "204": { description: Revoked } } /agent-manifest: get: operationId: getAgentManifest tags: [archive] summary: Discover machine-readable DeckArchive resources responses: "200": description: Agent discovery manifest content: application/json: schema: $ref: "#/components/schemas/AgentManifest" "500": $ref: "#/components/responses/ServerError" components: securitySchemes: clerkSession: { type: http, scheme: bearer } agentBearer: { type: http, scheme: bearer, bearerFormat: pw_agent token } parameters: DeckSlug: name: slug in: path required: true description: Stable deck record slug. schema: { type: string } responses: BadRequest: description: Invalid query parameters content: application/json: schema: $ref: "#/components/schemas/ErrorEnvelope" NotFound: description: Deck record not found content: application/json: schema: $ref: "#/components/schemas/ErrorEnvelope" ServerError: description: Server error content: application/json: schema: $ref: "#/components/schemas/ErrorEnvelope" schemas: ArchiveSummary: type: object properties: deckCount: { type: number } claimCount: { type: number } sourcedOutcomeCount: { type: number } verifiedContributorCount: { type: number } coverageNote: { type: string } required: [deckCount, claimCount, sourcedOutcomeCount, verifiedContributorCount, coverageNote] DeckCard: type: object properties: slug: { type: string } company: { type: string } title: { type: string } date: { type: string } stage: { type: string } slideCount: { type: number } description: { type: string } status: { type: string } claimCount: { type: number } outcomeCount: { type: number } commentCount: { type: number } accent: { type: string } required: [slug, company, title, date, stage, slideCount, description, status, claimCount, outcomeCount, commentCount, accent] Source: type: object description: Citation supporting a retrospective outcome. properties: label: { type: string } url: { type: string, format: uri-reference } publisher: { type: string } publishedAt: { type: string } required: [label, url, publisher, publishedAt] ClaimOutcome: type: object description: An original slide claim kept separate from its later sourced outcome. properties: id: { type: string } slide: { type: number } topic: { type: string } claim: { type: string } outcome: { type: string } verdict: type: string enum: [validated, mixed, missed, pending] source: $ref: "#/components/schemas/Source" required: [id, slide, topic, claim, outcome, verdict, source] TimelineEvent: type: object properties: year: { type: string } title: { type: string } description: { type: string } sourceUrl: { type: string, format: uri-reference } required: [year, title, description, sourceUrl] DeckDetail: allOf: - $ref: "#/components/schemas/DeckCard" - type: object properties: thesis: { type: string } deckUrl: { type: string, format: uri-reference } sourceUrl: { type: string, format: uri-reference } redistribution: { type: string } coachPrompt: { type: string } claims: type: array items: $ref: "#/components/schemas/ClaimOutcome" timeline: type: array items: $ref: "#/components/schemas/TimelineEvent" required: [thesis, deckUrl, sourceUrl, redistribution, coachPrompt, claims, timeline] Comment: type: object description: Attributed recollection; verification attests affiliation, not factual truth. properties: id: { type: string } author: { type: string } role: { type: string } affiliation: { type: string } verification: type: string enum: [company, investor, identity, community] body: { type: string } createdAt: { type: string } helpfulCount: { type: number } agentAuthored: { type: boolean } onBehalfOf: { type: string } required: [id, author, role, affiliation, verification, body, createdAt, helpfulCount, agentAuthored] AgentManifest: type: object properties: name: { type: string } description: { type: string } apiBase: { type: string } openApiUrl: { type: string } llmsTxtUrl: { type: string } datasetUrl: { type: string } mcpStatus: { type: string } instructions: type: array items: { type: string } required: [name, description, apiBase, openApiUrl, llmsTxtUrl, datasetUrl, mcpStatus, instructions] ErrorEnvelope: type: object properties: error: { type: string } required: [error]