{"openapi":"3.1.0","info":{"title":"Summify API","version":"2.2.0","description":"Access your Summify pods, content, agent briefs, and semantic search, and ingest content into Summify from your own systems. Use your API key from the Summify dashboard (Pro/Max plans). Works with ChatGPT custom GPTs, Claude MCP, and any OpenAPI-compatible agent."},"servers":[{"url":"https://summify.io/api","description":"Production API"},{"url":"https://api.summify.io","description":"Subdomain alias (same backend, clean URL — coming soon)"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"Your Summify API key from Dashboard → Account → API Access"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable error message."},"code":{"type":"string","description":"Stable machine-readable error code (see Errors → error-codes)."}}},"Pod":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"icon":{"type":"string","nullable":true},"is_default":{"type":"boolean"},"content_count":{"type":"integer"}}},"ContentItem":{"type":"object","properties":{"type":{"type":"string","enum":["video","voice","text"]},"data":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"summary":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}}}},"SearchResult":{"type":"object","properties":{"chunk_id":{"type":"integer"},"snippet":{"type":"string","description":"The matching text passage"},"similarity":{"type":"number","description":"Cosine similarity score 0-1"},"source":{"type":"object","properties":{"document_id":{"type":"string"},"title":{"type":"string"},"type":{"type":"string","enum":["video","voice","text"]},"content_id":{"type":"integer"},"video_id":{"type":"string","nullable":true},"channel":{"type":"string","nullable":true},"thumbnail":{"type":"string","nullable":true}}},"pods":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"}}}}}},"ChatMessage":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string","minLength":1,"maxLength":8000}}},"ChatRequest":{"type":"object","required":["pod_id","message"],"properties":{"pod_id":{"type":"integer","minimum":1},"message":{"type":"string","minLength":1,"maxLength":16000,"description":"The user message to send."},"conversation_id":{"type":"string","format":"uuid","nullable":true,"description":"Resume an existing conversation. Omit to start a new one."},"system_prompt":{"type":"string","nullable":true,"maxLength":4000,"description":"Optional system prompt. Overrides the default grounded-assistant prompt."},"max_output_tokens":{"type":"integer","minimum":1,"maximum":4096,"description":"Cap on completion length. Values above 4096 are clamped."}}},"ChatCitation":{"type":"object","required":["index","source"],"properties":{"index":{"type":"integer","minimum":1,"description":"1-based marker matching [1][2] in content."},"source":{"type":"object","required":["type","content_id","title","href"],"properties":{"type":{"type":"string","description":"video | voice | text"},"content_id":{"type":"string"},"title":{"type":"string"},"href":{"type":"string","description":"Dashboard URL for the source content."},"timestamp_seconds":{"type":"number","description":"Deprecated. Equivalent to `timestamps[0]`. Retained for backcompat."},"timestamps":{"type":"array","items":{"type":"number"},"description":"All chunk offsets (seconds) this source contributed to, sorted ascending. Render each as a deep-link chip. Empty for non-transcript sources."}}}}},"ChatResponse":{"type":"object","required":["conversation_id","message","citations","usage"],"properties":{"conversation_id":{"type":"string","format":"uuid","description":"Conversation id — pass back on the next turn to continue the thread."},"message":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","enum":["assistant"]},"content":{"type":"string"}}},"citations":{"type":"array","items":{"$ref":"#/components/schemas/ChatCitation"}},"usage":{"type":"object","required":["tokens_in","tokens_out"],"properties":{"tokens_in":{"type":"integer"},"tokens_out":{"type":"integer"}}}}},"Job":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["ingest_youtube","ingest_text","ingest_upload","generate_quiz","generate_brief","embed_retry"]},"status":{"type":"string","enum":["pending","processing","completed","failed"]},"attempts":{"type":"integer"},"max_attempts":{"type":"integer"},"tenant_user_id":{"type":"string","format":"uuid","nullable":true},"request_id":{"type":"string","nullable":true},"result":{"type":"object","nullable":true,"description":"Populated when status=completed."},"last_error":{"type":"string","nullable":true},"webhook_status":{"type":"string","nullable":true,"description":"Delivery state of the terminal webhook event."},"webhook_attempts":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"JobAccepted":{"type":"object","properties":{"job_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending"]},"status_url":{"type":"string","description":"Relative URL to poll: GET /v1/jobs/{id}."},"video_id":{"type":"string","nullable":true,"description":"YouTube video id; present only on /v1/ingest/youtube responses."}}},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string","format":"uri"},"description":{"type":"string","nullable":true},"event_types":{"type":"array","items":{"type":"string"},"nullable":true,"description":"Null = subscribed to all supported types."},"disabled":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"message_id":{"type":"string"},"status":{"type":"string","enum":["success","pending","failed","sending"]},"status_text":{"type":"string"},"response_status_code":{"type":"integer","nullable":true},"response_duration_ms":{"type":"integer","nullable":true},"timestamp":{"type":"string","format":"date-time"},"trigger_type":{"type":"string"},"url":{"type":"string","format":"uri"}}},"Entity":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"wikidata_id":{"type":"string","nullable":true},"mention_count":{"type":"integer"},"aliases":{"type":"array","items":{"type":"string"},"nullable":true}}},"Style":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"contentTypes":{"type":"array","items":{"type":"string","enum":["youtube","article","pdf","text","voice"]}}}},"UsageSummary":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"days":{"type":"integer"}}},"totals":{"type":"object","properties":{"requests":{"type":"integer"},"charge_units":{"type":"integer"},"errors":{"type":"integer"}}},"by_status_code":{"type":"object","additionalProperties":{"type":"integer"},"description":"Map of HTTP status code → request count."}}},"MeResponse":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"org_id":{"type":"string","format":"uuid","nullable":true},"api_key_id":{"type":"string","nullable":true},"scopes":{"type":"array","items":{"type":"string"},"nullable":true},"tier":{"type":"string","nullable":true},"auth_method":{"type":"string","enum":["api_key","session"]}}}}},"paths":{"/v1/me":{"get":{"operationId":"getMe","summary":"Identify the caller","description":"Returns the user, org, API key, scope, and tier associated with the credentials used. Useful for SDK diagnostics and onboarding flows.","responses":{"200":{"description":"Caller identity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/usage":{"get":{"operationId":"getUsageSummary","summary":"API usage summary for the caller org","description":"Aggregate request + error counts and Stripe charge units over a rolling window. Scope: `read`.","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":90,"default":30},"description":"Window size in days (1-90). Defaults to 30."}],"responses":{"200":{"description":"Usage summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/jobs/{id}":{"get":{"operationId":"getJob","summary":"Poll an async job","description":"Returns the current state of a job enqueued by POST /v1/ingest/*. Partners typically consume completion via webhooks and use this endpoint only for polling fallback. Scope: `read`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Job state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Job not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/session":{"get":{"operationId":"getAuthSession","summary":"Resolve session for the current credentials","description":"Lightweight probe for hybrid clients: reports whether the caller is authenticated via API key, session cookie, or Supabase JWT. Safe to call anonymously — returns { authenticated: false }.","responses":{"200":{"description":"Authentication status.","content":{"application/json":{"schema":{"type":"object","properties":{"authenticated":{"type":"boolean"},"method":{"type":"string","enum":["api_key","session","jwt"],"nullable":true},"user":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"email":{"type":"string","nullable":true},"plan":{"type":"string","nullable":true},"credit":{"type":"integer","nullable":true}}}}}}}}}}},"/v1/ingest/youtube":{"post":{"operationId":"ingestYoutube","summary":"Ingest a YouTube video","description":"Enqueues an async job that downloads, transcribes, summarises, embeds, and optionally assigns the result to pods. Returns 202 immediately with a job_id to poll (or subscribe via webhooks). Idempotent — retries with the same Idempotency-Key return the existing job. Scope: `write`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","description":"YouTube video URL or 11-char video id."},"pod_ids":{"type":"array","items":{"type":"integer"},"maxItems":50},"style":{"type":"string","maxLength":40,"description":"Summary style key; see GET /v1/styles."},"title":{"type":"string","maxLength":500},"transcript":{"type":"string","maxLength":1000000,"description":"Optional caller-supplied transcript. Skips download + transcription when provided."},"tenant_user_id":{"type":"string","format":"uuid"}}}}}},"responses":{"202":{"description":"Job accepted for asynchronous processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Billing required (org trial expired or blocked)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/ingest/text":{"post":{"operationId":"ingestText","summary":"Ingest raw text content","description":"Enqueues an async summarise + embed job over the supplied text. Useful for article bodies, PDFs pre-extracted to text, or partner-authored notes. Scope: `write`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["content"],"properties":{"content":{"type":"string","minLength":1,"maxLength":1000000},"title":{"type":"string","maxLength":500},"style":{"type":"string","maxLength":40},"language":{"type":"string","maxLength":20},"pod_ids":{"type":"array","items":{"type":"integer"},"maxItems":50},"content_type":{"type":"string","enum":["text","article","pdf"]},"tenant_user_id":{"type":"string","format":"uuid"}}}}}},"responses":{"202":{"description":"Job accepted for asynchronous processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Billing required (org trial expired or blocked)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/ingest/upload":{"post":{"operationId":"ingestUpload","summary":"Ingest audio/video from a partner-hosted URL","description":"Downloads media from `source_url`, transcribes, summarises, embeds, and assigns to pods. The source URL must be publicly reachable and resolves to a non-private IP (SSRF guard enforced). Scope: `write`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["source_url"],"properties":{"source_url":{"type":"string","format":"uri"},"title":{"type":"string","maxLength":500},"style":{"type":"string","maxLength":40},"language":{"type":"string","maxLength":20},"pod_ids":{"type":"array","items":{"type":"integer"},"maxItems":50},"tenant_user_id":{"type":"string","format":"uuid"}}}}}},"responses":{"202":{"description":"Job accepted for asynchronous processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Billing required (org trial expired or blocked)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks":{"get":{"operationId":"listWebhooks","summary":"List webhook endpoints","description":"Returns all webhook endpoints owned by the caller org. Scope: `webhook_admin`.","responses":{"200":{"description":"Endpoint list.","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createWebhook","summary":"Create a webhook endpoint","description":"Registers a new endpoint with Svix. A signing secret is returned inline — store it securely; it is NOT retrievable later. Scope: `webhook_admin`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","maxLength":2000},"description":{"type":"string","maxLength":200},"event_types":{"type":"array","items":{"type":"string"},"description":"Supported: content.ingested, content.ingested_partial, content.ingest_failed, learn.quiz_generated, learn.quiz_failed, brief.updated, brief.generation_failed, webhook.test."}}}}}},"responses":{"201":{"description":"Created endpoint.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEndpoint"},{"type":"object","properties":{"signing_secret":{"type":"string","description":"HMAC secret for verifying incoming payloads. Shown ONCE."}}}]}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}":{"delete":{"operationId":"deleteWebhook","summary":"Delete a webhook endpoint","description":"Removes the endpoint from Svix. Pending retries are cancelled. Scope: `webhook_admin`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"id":{"type":"string"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Endpoint not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/deliveries":{"get":{"operationId":"listWebhookDeliveries","summary":"List recent deliveries for a webhook","description":"Paginated via opaque `iterator` cursor. Scope: `webhook_admin`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"iterator","in":"query","schema":{"type":"string"},"description":"Opaque cursor from previous response."}],"responses":{"200":{"description":"Delivery page.","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"iterator":{"type":"string","nullable":true},"done":{"type":"boolean"},"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Endpoint not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/test":{"post":{"operationId":"sendWebhookTest","summary":"Send a test event to a webhook","description":"Triggers a `webhook.test` event through the full Svix pipeline — useful for verifying endpoint reachability + signature validation. Scope: `webhook_admin`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Test delivered.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"message_id":{"type":"string"},"event_type":{"type":"string","enum":["webhook.test"]}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Endpoint not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/entities/search":{"post":{"operationId":"searchEntities","summary":"Search the knowledge graph for entities","description":"Free-text entity search across the caller-accessible knowledge graph. Scope: `read`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["q"],"properties":{"q":{"type":"string","minLength":1,"maxLength":200},"limit":{"type":"integer","minimum":1,"maximum":50,"default":20}}}}}},"responses":{"200":{"description":"Matching entities.","content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string"},"count":{"type":"integer"},"results":{"type":"array","items":{"$ref":"#/components/schemas/Entity"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/entities/{id}":{"get":{"operationId":"getEntity","summary":"Fetch a single entity","description":"Accepts either the numeric entity id or the URL slug. Scope: `read`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Entity detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Entity not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/entities/{id}/relations":{"get":{"operationId":"getEntityRelations","summary":"Fetch an entity's related entities","description":"Returns the top co-occurring / semantically related entities. Scope: `read`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Related entities.","content":{"application/json":{"schema":{"type":"object","properties":{"entity":{"$ref":"#/components/schemas/Entity"},"relations":{"type":"array","items":{"$ref":"#/components/schemas/Entity"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Entity not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pods/{podId}/overview":{"get":{"operationId":"getPodOverview","summary":"Lightweight pod summary","description":"Returns counts and the most recent items — a cheaper alternative to listPods + getPodContent when building a landing surface. Scope: `read`.","parameters":[{"name":"podId","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Pod overview.","content":{"application/json":{"schema":{"type":"object","description":"Pod counts, recent item titles, and truncated preview snippets."}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Pod not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pods/{podId}/entities":{"get":{"operationId":"getPodEntities","summary":"Top entities within a pod","description":"Returns the entities mentioned across pod content, ranked by mention frequency. Scope: `read`.","parameters":[{"name":"podId","in":"path","required":true,"schema":{"type":"integer"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Top entities.","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"entities":{"type":"array","items":{"$ref":"#/components/schemas/Entity"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Pod not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/styles":{"get":{"operationId":"listStyles","summary":"List supported summary styles","description":"Public endpoint — returns the set of valid `style` values accepted by /v1/ingest/*, along with which content types each supports.","security":[],"responses":{"200":{"description":"Styles.","content":{"application/json":{"schema":{"type":"object","properties":{"styles":{"type":"array","items":{"$ref":"#/components/schemas/Style"}}}}}}}}}},"/v1/pods":{"get":{"operationId":"listPods","summary":"List all pods","description":"Returns all pods belonging to the authenticated user with content counts. Use this first to discover available pods before searching or loading briefs.","responses":{"200":{"description":"List of pods","content":{"application/json":{"schema":{"type":"object","properties":{"pods":{"type":"array","items":{"$ref":"#/components/schemas/Pod"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pods/{podId}/brief":{"get":{"operationId":"getPodBrief","summary":"Get the agent brief for a pod","description":"Returns a structured knowledge synthesis for a pod — domain worldview, named frameworks with attribution, step-by-step playbooks, key statistics, expert disagreements, anti-patterns, and boundaries. Load this into your context to become a domain specialist. Use the search endpoint with the provided search_hints to get full source passages for any framework or technique.","parameters":[{"name":"podId","in":"path","required":true,"schema":{"type":"integer"},"description":"The pod ID"}],"responses":{"200":{"description":"Pod brief","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ready","legacy","pending"],"description":"ready = full brief available, legacy = older overview format, pending = not yet generated"},"manifest":{"type":"object","description":"The structured brief. Contains: domain, worldview, evidence_base, frameworks[], playbooks[], key_stats[], anti_patterns[], non_obvious_insights[], expert_disagreements[], boundaries"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Pod not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pods/{podId}/search":{"post":{"operationId":"searchPodContent","summary":"Semantic search within a pod","description":"Search across a pod's content using AI semantic search (RAG). Returns the most relevant passages with source attribution. Supports single query or batch queries (up to 10). Use search_hints from the pod brief to find specific frameworks or techniques.","parameters":[{"name":"podId","in":"path","required":true,"schema":{"type":"integer"},"description":"The pod ID to search within"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"Single search query"},"queries":{"type":"array","items":{"type":"string"},"maxItems":10,"description":"Multiple queries for batch search (max 10). More efficient than multiple single calls. Results are deduplicated."}}}}}},"responses":{"200":{"description":"Search results with source attribution","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Pod not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pods/{podId}/content":{"get":{"operationId":"getPodContent","summary":"Get content in a pod","description":"Returns all content items in a specific pod, optionally filtered by type.","parameters":[{"name":"podId","in":"path","required":true,"schema":{"type":"integer"}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["video","voice","text"]},"description":"Filter by content type"}],"responses":{"200":{"description":"List of content items","content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"array","items":{"$ref":"#/components/schemas/ContentItem"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Pod not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/content/{contentType}/{contentId}":{"get":{"operationId":"getContentDetail","summary":"Get content detail","description":"Returns the full detail of a specific content item including summary and transcript. For asking questions about content, prefer searchPodContent — it uses semantic search to find relevant passages without loading entire transcripts.","parameters":[{"name":"contentType","in":"path","required":true,"schema":{"type":"string","enum":["video","voice"]}},{"name":"contentId","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Content detail with summary and transcript","content":{"application/json":{"schema":{"type":"object","properties":{"item":{"type":"object"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Content not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/chat":{"post":{"operationId":"chat","summary":"Grounded chat completion over a pod","description":"Runs retrieval over the specified pod, then generates an answer grounded in the retrieved chunks. Returns the assistant message, numbered citations, and token usage. Pass `Accept: text/event-stream` to receive a streamed SSE response instead. Requires the `chat` scope.","x-required-scopes":["chat"],"parameters":[{"name":"X-Tenant-User-Id","in":"header","required":true,"schema":{"type":"string"},"description":"Identifies the end-user on behalf of whom the chat is running."},{"name":"Accept","in":"header","required":false,"schema":{"type":"string","enum":["application/json","text/event-stream"]},"description":"Use `text/event-stream` to receive SSE streaming. Defaults to `application/json`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"200":{"description":"Chat response with citations and token usage. When Accept is text/event-stream, events are: `start` (conversation_id), `delta` (content chunk), `done` (citations + usage), `error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatResponse"}},"text/event-stream":{"schema":{"type":"string","description":"SSE stream. Events: start { conversation_id }, delta { content }, done { citations, usage }, error { message }."}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Pod not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/tenants/{external_user_id}":{"delete":{"operationId":"deleteTenant","summary":"Delete all data for a tenant user","description":"Purges all conversations and associated data for the given tenant user. Idempotent — already-deleted users return `{ deleted: true, already_deleted: true }`. Requires the `conversations` scope.","x-required-scopes":["conversations"],"parameters":[{"name":"external_user_id","in":"path","required":true,"schema":{"type":"string"},"description":"The partner-side user identifier (X-Tenant-User-Id)."}],"responses":{"200":{"description":"Deletion result.","content":{"application/json":{"schema":{"type":"object","required":["deleted"],"properties":{"deleted":{"type":"boolean"},"already_deleted":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/conversations":{"get":{"operationId":"listConversations","summary":"List conversations for a tenant user","description":"Returns a cursor-paginated list of conversations belonging to the specified tenant user. Requires the `conversations` scope.","x-required-scopes":["conversations"],"parameters":[{"name":"tenant_user_id","in":"query","required":true,"schema":{"type":"string"},"description":"The partner-side user identifier."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque pagination cursor from a previous response."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Page size (max 100, default 20)."}],"responses":{"200":{"description":"Paginated conversation list.","content":{"application/json":{"schema":{"type":"object","required":["conversations","next_cursor"],"properties":{"conversations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"pod_id":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"message_count":{"type":"integer"}}}},"next_cursor":{"type":"string","nullable":true}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/conversations/{conversation_id}":{"get":{"operationId":"getConversation","summary":"Get a conversation with optional messages","description":"Returns conversation metadata and, if `with_messages=true`, the message history. Requires the `conversations` scope.","x-required-scopes":["conversations"],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Conversation UUID."},{"name":"with_messages","in":"query","required":false,"schema":{"type":"boolean"},"description":"Include message history in the response."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Max messages to return when with_messages=true."}],"responses":{"200":{"description":"Conversation detail.","content":{"application/json":{"schema":{"type":"object","properties":{"conversation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"pod_id":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"messages":{"type":"array","items":{"$ref":"#/components/schemas/ChatMessage"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Conversation not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteConversation","summary":"Delete a conversation","description":"Permanently deletes a conversation and all its messages. Requires the `conversations` scope.","x-required-scopes":["conversations"],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Conversation UUID."}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["deleted"],"properties":{"deleted":{"type":"boolean","enum":[true]}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Conversation not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/search":{"post":{"operationId":"searchAllContent","summary":"Search across all content","description":"Search across all of the user's content or a specific pod using AI semantic search. For pod-specific search with structured results, prefer /v1/pods/{podId}/search.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"pod_id":{"type":"integer","description":"Optional pod ID to scope the search. Omit to search all content."},"query":{"type":"string","description":"The search query"}}}}}},"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (missing scope or plan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Pod not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}