{"openapi":"3.1.0","info":{"title":"ContextRepo REST API","version":"2.3.0","summary":"Public REST API for prompts, documents, collections, search, progressive disclosure, and document coordination.","description":"ContextRepo is the AI Context Repo for agents. The REST API exposes 35 authenticated `/v1/*` operations for managing prompts, documents, collections, semantic and literal search, web scraping, source refresh, revision-safe document coordination and leases, hierarchical chunk navigation, and synthesized cited answers. Authentication is via Clerk-issued bearer tokens (session JWT or OAuth `oat_*`) or first-party `gm_*` API keys. Requests must include a descriptive `User-Agent`. All timestamp fields (including createdAt, updatedAt, lastActivityAt, expiresAt, lastViewedAt, lastCheckedAt, lastChangedAt, and lastRefreshError.at) are epoch milliseconds (integers), not ISO date-time strings. Response schemas in this revision reflect the live Convex handler contract. Versioning and deprecation policy: within the `/v1` prefix changes are additive only; new majors ship side-by-side with a six-month deprecation runway signaled via `Deprecation` and `Sunset` response headers (RFC 8594, RFC 9745). Full policy: https://contextrepo.com/docs/api/versioning","termsOfService":"https://contextrepo.com/policies","contact":{"name":"Context Repo Support","url":"https://contextrepo.com","email":"support@contextrepo.com"},"license":{"name":"Proprietary - ContextRepo","url":"https://contextrepo.com/policies"},"x-detailedDescription":"Hosted on the Convex deployment fronted by `api.contextrepo.com`. MCP transport, Clerk webhooks, CORS preflight, and legacy `/v1/mcp/capabilities` are out of scope for this spec; see `/.well-known/mcp/server-card.json`. The `api.contextrepo.com` edge layer rejects requests with library-default User-Agent strings (e.g., raw `Python-urllib/3.x`) with `403` and body `error code: 1010` (plain text, not the JSON envelope). All `/v1/*` responses use HTTP/1.1 chunked transfer encoding; the MCP companion at `/mcp` additionally supports SSE-framed JSON-RPC."},"servers":[{"url":"https://api.contextrepo.com","description":"Production"}],"tags":[{"name":"prompts","description":"Prompt CRUD, versions, restore, and search"},{"name":"documents","description":"Document CRUD, versions, restore, scrape, and source refresh"},{"name":"collections","description":"Collection CRUD and item membership"},{"name":"search","description":"Cross-resource semantic and literal search"},{"name":"progressive-disclosure","description":"Hierarchical chunk navigation for large documents"},{"name":"user","description":"Authenticated user identity and metadata"}],"externalDocs":{"description":"Full developer documentation and integration guides","url":"https://contextrepo.com/docs"},"security":[{"bearerAuth":[]},{"apiKeyAuth":[]}],"paths":{"/v1/collections":{"get":{"tags":["collections"],"operationId":"listCollections","summary":"List collections owned by the authenticated user","description":"Returns a paginated list of collections the caller can read. Supports `limit`, `cursor` (base64-encoded offset), `search` (substring on name/description), and `tags` (AND-semantics filter; items must have all supplied tags). Requires `documents.read` for API keys; session JWTs and OAuth tokens bypass scope gating.","x-context-repo-required-scope":"documents.read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Search"},{"$ref":"#/components/parameters/Tags"}],"responses":{"200":{"description":"Collections listed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CollectionListItem"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["data","pagination"]},"example":{"data":[{"id":"k57a8b9c0d1e2f3g4h5i6j7k8l","name":"Marketing Prompts","description":"Reusable prompts for content drafts and ad copy","itemCount":12}],"pagination":{"cursor":"","hasMore":false}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"post":{"tags":["collections"],"operationId":"createCollection","summary":"Create a new collection","description":"Creates a collection owned by the authenticated user. Returns 201 with a `Location` header pointing at `/v1/collections/{id}`. Requires `documents.write` for machine tokens and API keys.","x-context-repo-required-scope":"documents.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionCreateRequest"}}}},"responses":{"201":{"description":"Collection created","headers":{"Location":{"schema":{"type":"string"},"description":"Relative URL of the created resource"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Collection"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/documents/scrape":{"post":{"tags":["documents"],"operationId":"scrapeUrl","summary":"Scrape a URL into a new document","description":"Submits a URL to be scraped, parsed, and stored as a new document. Returns 202 Accepted with the freshly-created `documentId` while chunking and embedding finish in the background. Requires `documents.write` for machine tokens and API keys (the legacy scope `documents.scrape` is also accepted for forward-compat). Bound by the `scrape` Redis rate-limit tier (much stricter than the `api` tier).","x-context-repo-required-scope":"documents.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeRequest"}}}},"responses":{"202":{"description":"Scrape accepted - chunking and embedding will finish in the background","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"documentId":{"type":"string"}},"required":["documentId"]}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/documents":{"post":{"tags":["documents"],"operationId":"createDocument","summary":"Create a new document","description":"Creates a document with `title` + `content`. Optional `tags` and `collectionIds`. Returns 201 with a `Location` header. Idempotency-Key may be supplied for atomic replay protection.","x-context-repo-required-scope":"documents.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentCreateRequest"}}}},"responses":{"201":{"description":"Document created","headers":{"Location":{"schema":{"type":"string"},"description":"Relative URL of the created document"},"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DocumentAcknowledgement"}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"422":{"$ref":"#/components/responses/DocumentProtocol422"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}},"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}]},"get":{"tags":["documents"],"operationId":"listDocuments","summary":"List documents owned by the authenticated user","description":"Returns a paginated list of documents. Supports `limit`, `cursor`, `search`, `collectionId` (filter by collection membership), `status`, `includeArchived`, `includeContent` (when true, content is truncated to 2,000 characters per item), and `tags` (AND-semantics filter; items must have all supplied tags).","x-context-repo-required-scope":"documents.read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Substring filter on the document title."},{"name":"collectionId","in":"query","schema":{"type":"string"},"description":"Restrict to documents in this collection"},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","processing","completed","failed"]},"description":"Filter by processing status."},{"name":"includeArchived","in":"query","schema":{"type":"boolean","default":false}},{"$ref":"#/components/parameters/IncludeContent"},{"$ref":"#/components/parameters/Tags"}],"responses":{"200":{"description":"Documents listed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DocumentListItem"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["data","pagination"]},"example":{"data":[{"id":"k1a2b3c4d5e6f7g8h9i0j1k2l3","title":"Onboarding Guide","status":"completed","updatedAt":1715900000000}],"pagination":{"cursor":"eyJvIjoyNX0=","hasMore":true}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/documents/{id}":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"get":{"tags":["documents"],"operationId":"getDocument","summary":"Get a document by id","description":"Returns document metadata and, unless `includeContent=false`, `content`, `contentHtml`, and `rawHtml` up to the REST response limit. Larger text fields are truncated. Use the progressive-disclosure endpoints for targeted retrieval from large documents.","x-context-repo-required-scope":"documents.read","responses":{"200":{"description":"Document found","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Document"}},"required":["data"]}}},"headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}},"parameters":[{"name":"includeContent","in":"query","schema":{"type":"boolean","default":true},"description":"Set to false to omit content, contentHtml, and rawHtml. Defaults to true on this endpoint (unlike list endpoints)."}]},"patch":{"tags":["documents"],"operationId":"updateDocument","summary":"Update a document","description":"Patches one or more canonical fields: `title`, `content`, `contentHtml`, `rawHtml`, `sourceUrl`, `metadata`, or `tags`. Omitted fields are preserved. Any changed canonical field creates one revision; an exact unchanged write is a no-op. For PATCH and restore only, body `expectedRevision` is an alternative to `If-Match`. If both are supplied their revisions must agree and the If-Match content hash remains enforced. Managed PATCH and restore additionally require `Idempotency-Key`, `X-ContextRepo-Lease-Id`, and `X-ContextRepo-Lease-Fence`. Exact retries must preserve their original precondition representation. Refresh and coordination-policy operations retain their existing preconditions.","x-context-repo-required-scope":"documents.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentUpdateRequest"}}}},"responses":{"200":{"description":"Document updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DocumentAcknowledgement"}},"required":["data"],"additionalProperties":false}}},"headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}},"Idempotent-Replayed":{"description":"true when the completed atomic receipt was replayed.","schema":{"type":"boolean"}}}},"400":{"$ref":"#/components/responses/DocumentProtocol400"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentProtocol409"},"412":{"$ref":"#/components/responses/DocumentProtocol412"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"422":{"$ref":"#/components/responses/DocumentProtocol422"},"428":{"$ref":"#/components/responses/DocumentProtocol428"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}},"parameters":[{"$ref":"#/components/parameters/IfMatch"},{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/DocumentLeaseId"},{"$ref":"#/components/parameters/DocumentLeaseFence"}]},"delete":{"tags":["documents"],"operationId":"deleteDocument","summary":"Delete a document","description":"Permanently deletes a document and all of its versions, chunks, and embeddings. Returns 200 with `{success, id}` (NOT 204) - this 200+body envelope is required for MCP-client compatibility (Mission M-048).","x-context-repo-required-scope":"documents.write","responses":{"200":{"description":"Document deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAck"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/documents/{id}/versions":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"get":{"tags":["documents"],"operationId":"getDocumentVersions","summary":"List version history for a document","description":"Returns all stored versions of a document in newest-first order. Each version row includes `versionId`, `version`, `changeLog`, `createdAt`, `createdBy`, and a content preview.","x-context-repo-required-scope":"documents.read","responses":{"200":{"description":"Versions listed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DocumentVersion"}}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/documents/{id}/refresh":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"post":{"tags":["documents"],"operationId":"refreshDocument","summary":"Refresh a document from its source","description":"Re-fetches an eligible scraped document from its stored source URL. The source fetch completes before this operation returns, so `changed` is known; chunking and embedding for changed content may continue asynchronously. Send an empty POST with no request body. Requires `documents.write` for machine tokens and API keys; the legacy `documents.scrape` scope is also accepted for forward-compatibility. Uses the stricter `scrape` rate-limit tier.","x-context-repo-required-scope":"documents.write","security":[{"bearerAuth":[]},{"apiKeyAuth":[]}],"responses":{"202":{"description":"Source refresh accepted; source comparison is complete and any required chunking or embedding continues asynchronously","headers":{"Location":{"schema":{"type":"string"},"description":"Relative URL of the refreshed document"},"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"documentId":{"type":"string"},"changed":{"type":"boolean"}},"required":["documentId","changed"]}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/DocumentProtocol400"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentProtocol409"},"412":{"$ref":"#/components/responses/DocumentProtocol412"},"422":{"$ref":"#/components/responses/DocumentProtocol422"},"428":{"$ref":"#/components/responses/DocumentProtocol428"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}},"parameters":[{"$ref":"#/components/parameters/IfMatch"},{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/DocumentLeaseId"},{"$ref":"#/components/parameters/DocumentLeaseFence"}]}},"/v1/documents/{id}/restore":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"post":{"tags":["documents"],"operationId":"restoreDocumentVersion","summary":"Restore a document to a previous version","description":"Restores the canonical snapshot selected by `versionId` as a new current revision when it differs; an exact unchanged restore is a no-op. Fields absent from a legacy partial snapshot are preserved from the current document, and the acknowledgement includes `LEGACY_PARTIAL_SNAPSHOT`. A changed canonical snapshot resets revision-fenced processing. For PATCH and restore only, body `expectedRevision` is an alternative to `If-Match`. If both are supplied their revisions must agree and the If-Match content hash remains enforced. Managed PATCH and restore additionally require `Idempotency-Key`, `X-ContextRepo-Lease-Id`, and `X-ContextRepo-Lease-Fence`. Exact retries must preserve their original precondition representation. Refresh and coordination-policy operations retain their existing preconditions.","x-context-repo-required-scope":"documents.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"versionId":{"type":"string"},"expectedRevision":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Original expected document revision. For PATCH and restore only, an alternative to If-Match. If both are supplied their revisions must agree; the If-Match content hash remains enforced. Exact retries must preserve their original precondition representation."}},"required":["versionId"]}}}},"responses":{"200":{"description":"Document restored or already matched the selected snapshot","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DocumentAcknowledgement"}},"required":["data"],"additionalProperties":false}}},"headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}},"Idempotent-Replayed":{"description":"true when the completed atomic receipt was replayed.","schema":{"type":"boolean"}}}},"400":{"$ref":"#/components/responses/DocumentProtocol400"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentProtocol409"},"412":{"$ref":"#/components/responses/DocumentProtocol412"},"422":{"$ref":"#/components/responses/DocumentProtocol422"},"428":{"$ref":"#/components/responses/DocumentProtocol428"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}},"parameters":[{"$ref":"#/components/parameters/IfMatch"},{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/DocumentLeaseId"},{"$ref":"#/components/parameters/DocumentLeaseFence"}]}},"/v1/collections/{id}":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"get":{"tags":["collections"],"operationId":"getCollection","summary":"Get a collection by id","description":"Returns the collection metadata plus optional `stats` block (`itemCount`, `documentCount`, `promptCount`).","x-context-repo-required-scope":"documents.read","responses":{"200":{"description":"Collection found","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Collection"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"patch":{"tags":["collections"],"operationId":"updateCollection","summary":"Update a collection","description":"Patches one or more of: `name`, `description`, `color`, `icon`, `tags`, `isPublic`. Omitted fields are left untouched.","x-context-repo-required-scope":"documents.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionUpdateRequest"}}}},"responses":{"200":{"description":"Collection updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Collection"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"delete":{"tags":["collections"],"operationId":"deleteCollection","summary":"Delete a collection","description":"Permanently deletes the collection. The collection MUST be empty; all items must be removed first. Returns 200 with `{success, id}` (Mission M-048). Returns 409 Conflict if the collection still has items.","x-context-repo-required-scope":"documents.write","responses":{"200":{"description":"Collection deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAck"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/collections/{id}/items":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"get":{"tags":["collections"],"operationId":"getCollectionItems","summary":"List the items in a collection","description":"Returns the items (documents and prompts) inside a collection. When `includeContent=true`, full content is returned in a single un-paginated response. When false, only metadata is returned. When includeContent=true the response is a single non-paginated page: pagination is always {\"cursor\": \"\", \"hasMore\": false}.","x-context-repo-required-scope":"documents.read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IncludeContent"}],"responses":{"200":{"description":"Items listed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CollectionItem"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"post":{"tags":["collections"],"operationId":"addItemsToCollection","summary":"Add items to a collection","description":"Add one or more documents or prompts to a collection. Returns counts of newly-added items vs items that were already members.","x-context-repo-required-scope":"documents.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionMembershipMutation"}}}},"responses":{"200":{"description":"Items added","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"added":{"type":"integer"},"alreadyInCollection":{"type":"integer"}},"required":["added","alreadyInCollection"]}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"put":{"tags":["collections"],"operationId":"removeItemsFromCollection","summary":"Remove items from a collection","description":"PUT (NOT DELETE-with-body) is used to remove items from a collection because DELETE-with-request-body is non-standard and rejected by some CDNs. Returns the count of removed items.","x-context-repo-required-scope":"documents.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionMembershipMutation"}}}},"responses":{"200":{"description":"Items removed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"removed":{"type":"integer"}},"required":["removed"]}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/search":{"get":{"tags":["search"],"operationId":"search","summary":"Search prompts, documents, and collections","description":"Cross-resource search with two modes:\n\n- `semantic=true` (default): vector similarity using OpenAI text-embedding-3-small (1536 dims).\n- `semantic=false`: literal substring match on titles, descriptions, and indexed document body text via hierarchical chunks (full-body literal matching, eventually consistent with chunking; title and preview matches are immediate). Literal document hits matched in the body may carry a `highlight` snippet and a `chunkId` usable with the progressive-disclosure endpoints.\n\nResults are grouped by resource type. Both branches honor `tags` (AND-semantics filter applied symmetrically to prompts, documents, and collections). Requires any read scope (`prompts.read`, `documents.read`).","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Free-form search query (alias: query)"},{"name":"semantic","in":"query","schema":{"type":"boolean","default":true}},{"name":"type","in":"query","schema":{"type":"string","enum":["prompts","documents","collections","all"],"default":"all"}},{"name":"limit","in":"query","schema":{"type":"integer","default":10,"minimum":1,"maximum":50},"description":"Maximum results per resource type."},{"$ref":"#/components/parameters/Tags"},{"name":"scoreThreshold","in":"query","schema":{"type":"number","default":0.35},"description":"Semantic mode only - minimum similarity score for results."}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResults"},"examples":{"semantic":{"summary":"Semantic search response (semantic=true)","value":{"data":{"prompts":[{"promptId":"k9z8y7x6w5v4u3t2s1r0q9p8o7","title":"Code review prompt","description":"Reviews a code diff for correctness, style, and security","tags":["engineering","code-review"]}],"documents":[{"documentId":"k1a2b3c4d5e6f7g8h9i0j1k2l3","title":"Engineering Handbook"}],"collections":[]},"meta":{"query":"code review","semantic":true,"latencyMs":142}}},"literal":{"summary":"Literal search response (semantic=false) — document hit matched in body text","value":{"data":{"prompts":[],"documents":[{"documentId":"k1a2b3c4d5e6f7g8h9i0j1k2l3","title":"Engineering Handbook","highlight":"...every endpoint in our API Design standard declares explicit request and response contracts...","chunkId":"hc_chunk789xyz"}],"collections":[]},"meta":{"query":"API Design","semantic":false}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/user/me":{"get":{"tags":["user"],"operationId":"getMe","summary":"Get the authenticated identity","description":"Returns the resolved authentication identity, including `kind` (`session` | `machine` | `apiKey`), `userId`, profile fields, and the active `permissions` array. Useful for verifying which token / API key is in use and which scopes are granted.","responses":{"200":{"description":"Identity resolved","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/User"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v1/prompts":{"get":{"tags":["prompts"],"operationId":"listPrompts","summary":"List prompts owned by the authenticated user","description":"Returns a paginated list of prompts. Supports `limit`, `cursor`, `q` (substring on title/description), and `tags` (AND-semantics filter; items must have all supplied tags).","x-context-repo-required-scope":"prompts.read","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"q","in":"query","schema":{"type":"string"},"description":"Substring filter on title/description (applied after pagination)."},{"$ref":"#/components/parameters/Tags"},{"name":"includePublic","in":"query","schema":{"type":"boolean","default":false},"description":"Also include public prompts owned by other users."}],"responses":{"200":{"description":"Prompts listed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PromptListItem"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["data","pagination"]},"example":{"data":[{"id":"k9z8y7x6w5v4u3t2s1r0q9p8o7","title":"Code review prompt","description":"Reviews a code diff and surfaces correctness, style, and security issues","tags":["engineering","code-review"],"createdAt":1715731200000,"updatedAt":1715817600000}],"pagination":{"cursor":"","hasMore":false}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"post":{"tags":["prompts"],"operationId":"createPrompt","summary":"Create a new prompt","description":"Creates a prompt with required `title`, `description`, and `content`. Optional `tags`, `variables` (typed user-curated metadata: `{name, type: \"string\"|\"number\"|\"boolean\", description?}[]`), `parameters`, and `collectionIds`. Returns 201 + `Location` header.","x-context-repo-required-scope":"prompts.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptCreateRequest"}}}},"responses":{"201":{"description":"Prompt created","headers":{"Location":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Prompt"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/prompts/{id}":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"get":{"tags":["prompts"],"operationId":"getPrompt","summary":"Get a prompt by id","description":"Returns the full prompt including `content`, `variables`, `parameters`, and version metadata.","x-context-repo-required-scope":"prompts.read","responses":{"200":{"description":"Prompt found","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Prompt"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"patch":{"tags":["prompts"],"operationId":"updatePrompt","summary":"Update a prompt","description":"Patches one or more of: `title`, `description`, `content`, `tags`, `variables`, `parameters`. Omitted fields are left untouched.","x-context-repo-required-scope":"prompts.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptUpdateRequest"}}}},"responses":{"200":{"description":"Prompt updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Prompt"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"delete":{"tags":["prompts"],"operationId":"deletePrompt","summary":"Delete a prompt","description":"Permanently deletes a prompt and all of its versions. Returns 200 with `{success, id}` (Mission M-048).","x-context-repo-required-scope":"prompts.write","responses":{"200":{"description":"Prompt deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAck"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/prompts/{id}/versions":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"get":{"tags":["prompts"],"operationId":"getPromptVersions","summary":"List version history for a prompt","description":"Returns all stored versions of a prompt in newest-first order. Each row includes `versionId`, `version`, `changeLog`, `createdAt`, `createdBy`, and a content preview.","x-context-repo-required-scope":"prompts.read","responses":{"200":{"description":"Versions listed","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PromptVersion"}}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/prompts/{id}/restore":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"post":{"tags":["prompts"],"operationId":"restorePromptVersion","summary":"Restore a prompt to a previous version","description":"Creates a new version with content copied from the specified `versionId`.","x-context-repo-required-scope":"prompts.write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"versionId":{"type":"string"}},"required":["versionId"]}}}},"responses":{"200":{"description":"Prompt restored","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Prompt"}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/pd/search":{"post":{"tags":["progressive-disclosure"],"operationId":"pdSearch","summary":"Vector search returning ranked, hierarchical document chunks","description":"Progressive-disclosure search: returns granular content fragments (chunks) with structural metadata (chunkId, level, parentId, sectionPath, etc.) so an agent can navigate up/down the document tree without loading the entire body.","x-context-repo-required-scope":"documents.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdSearchRequest"}}}},"responses":{"200":{"description":"Chunk results","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/PdSearchResult"}},"meta":{"type":"object","properties":{"query":{"type":"string"},"totalResults":{"type":"integer"},"latencyMs":{"type":"integer"}},"required":["query","totalResults","latencyMs"]}},"required":["results","meta"]}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/pd/expand":{"post":{"tags":["progressive-disclosure"],"operationId":"pdExpand","summary":"Navigate hierarchically from a chunk","description":"Walks the document tree starting from `chunkId` in one of five directions: `up` (parent), `down` (children), `next`/`previous` (siblings), `surrounding` (context window of N siblings on each side; falls back to neighbouring sections if the target is the only child).","x-context-repo-required-scope":"documents.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PdExpandRequest"}}}},"responses":{"200":{"description":"Expansion results","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"chunks":{"type":"array","items":{"$ref":"#/components/schemas/PdExpandChunk"},"description":"Empty array when there are no chunks in the requested direction (including unknown chunkIds that have been re-chunked away)."}},"required":["chunks"]}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/pd/read/{chunkId}":{"parameters":[{"name":"chunkId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["progressive-disclosure"],"operationId":"pdRead","summary":"Read a single chunk with full content + hierarchy metadata","description":"Returns one chunk's full text, sectionPath, chunkIndex, navigation IDs (parentChunkId, prevSiblingId, nextSiblingId), and content metadata (wordCount, headingText).","x-context-repo-required-scope":"documents.read","responses":{"200":{"description":"Chunk found","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PdReadResult"}},"required":["data"]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/reason":{"post":{"tags":["progressive-disclosure"],"operationId":"reason","summary":"Synthesized, cited answer composed across your documents","description":"Runs bounded progressive-disclosure retrieval over the caller's document chunks and, when evidence is admitted, at most one server-managed synthesis pass with zero retries. Empty evidence always skips synthesis. Weak unscoped evidence also skips synthesis; nonempty explicit document or collection scope bypasses only Reason's fixed 0.35 relevance gate. The model emits cited statements and limitations. Disagreements appear as ordinary cited statements in the answer. The server validates admitted chunk IDs and quote containment after collapsing whitespace runs and trimming edges, binds provenance, and renders one markdown `answer` with inline `[[chunkId]]` tokens, a `citations` array, and a best-effort `gaps` list of limitations noticed during this run, including facts not established by the retrieved evidence within the requested scope and retrieval limits. Exact citation validation proves source linkage, not semantic entailment. `meta.citationsDropped` counts references withheld by failed mechanical validation; retained duplicate references do not increase it. This diagnostic is not a semantic-correctness score. Gaps are non-exhaustive; an empty array does not prove complete coverage. Operates on document content only (not prompts); read-only; does not persist.","x-context-repo-required-scope":"documents.read","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReasonRequest"}}}},"responses":{"200":{"description":"Bounded, evidence-linked answer with citations, gaps, and retrieval metadata","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":false,"properties":{"answer":{"type":"string"},"citations":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"chunkId":{"type":"string"},"documentId":{"type":"string"},"documentTitle":{"type":"string"}},"required":["chunkId","documentId","documentTitle"]}},"gaps":{"type":"array","description":"Non-exhaustive, best-effort limitations noticed during this run.","items":{"type":"string"}},"meta":{"type":"object","properties":{"chunksGathered":{"type":"integer"},"citationsDropped":{"type":"integer"},"latencyMs":{"type":"integer"}},"required":["chunksGathered","citationsDropped","latencyMs"]}},"required":["answer","citations","gaps","meta"]}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/pd/session":{"post":{"tags":["progressive-disclosure"],"operationId":"pdCreateSession","summary":"Create a progressive-disclosure session for de-duplication","description":"Creates a session token used by `pdSearch` to de-duplicate chunks across iterative queries. Optional `ttl` (seconds, default 3600).","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"ttl":{"type":"integer","default":3600,"description":"Session lifetime in seconds. Defaults to 3600; the value is not clamped server-side."}}}}}},"responses":{"201":{"description":"Session created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"sessionId":{"type":"string"},"createdAt":{"type":"integer","description":"Epoch milliseconds"},"expiresAt":{"type":"integer","description":"Epoch milliseconds"}},"required":["sessionId","createdAt","expiresAt"]}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/documents/{id}/coordination":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"get":{"tags":["documents"],"operationId":"getDocumentCoordination","summary":"Get document coordination policy and lease state","description":"Returns the current standard or lease-required policy, fence, and caller-safe lease summary. Requires documents.read for scoped credentials. leaseId is present only when heldByCaller is true.","x-context-repo-required-scope":"documents.read","responses":{"200":{"description":"Coordination state returned","headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}},"X-ContextRepo-Lease-Expires-At":{"description":"Lease expiry in epoch milliseconds; omitted when no applicable lease expiry exists.","schema":{"type":"integer","description":"Epoch milliseconds."}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DocumentCoordinationState"}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/DocumentProtocol400"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentProtocol409"},"412":{"$ref":"#/components/responses/DocumentProtocol412"},"422":{"$ref":"#/components/responses/DocumentProtocol422"},"428":{"$ref":"#/components/responses/DocumentProtocol428"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"put":{"tags":["documents"],"operationId":"enableDocumentCoordination","summary":"Require fenced leases for document writes","description":"Owner-only operation that enables lease_required policy at the exact If-Match revision. Requires documents.write.","x-context-repo-required-scope":"documents.write","parameters":[{"$ref":"#/components/parameters/IfMatch"}],"responses":{"200":{"description":"Lease-required coordination enabled","headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DocumentCoordinationState"}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/DocumentProtocol400"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentProtocol409"},"412":{"$ref":"#/components/responses/DocumentProtocol412"},"422":{"$ref":"#/components/responses/DocumentProtocol422"},"428":{"$ref":"#/components/responses/DocumentProtocol428"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}},"delete":{"tags":["documents"],"operationId":"disableDocumentCoordination","summary":"Return a document to standard write policy","description":"Owner-only operation that disables managed coordination at the exact If-Match revision. Rejects while any lease is active. Requires documents.write.","x-context-repo-required-scope":"documents.write","parameters":[{"$ref":"#/components/parameters/IfMatch"}],"responses":{"200":{"description":"Standard coordination policy restored","headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DocumentCoordinationDisableResult"}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/DocumentProtocol400"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentProtocol409"},"412":{"$ref":"#/components/responses/DocumentProtocol412"},"422":{"$ref":"#/components/responses/DocumentProtocol422"},"428":{"$ref":"#/components/responses/DocumentProtocol428"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}},"/v1/documents/{id}/coordination/lease":{"parameters":[{"$ref":"#/components/parameters/IdPath"}],"post":{"tags":["documents"],"operationId":"operateDocumentLease","summary":"Acquire, renew, or release a document lease","description":"Requires documents.write and Idempotency-Key. Acquire omits lease headers; renew and release require the exact X-ContextRepo-Lease-Id and X-ContextRepo-Lease-Fence. ttlMs is allowed only for acquire and renew.","x-context-repo-required-scope":"documents.write","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/DocumentLeaseId"},{"$ref":"#/components/parameters/DocumentLeaseFence"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentLeaseOperationRequest"}}}},"responses":{"200":{"description":"Lease operation completed or atomically replayed","headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}},"X-ContextRepo-Lease-Expires-At":{"description":"Lease expiry in epoch milliseconds; omitted when no applicable lease expiry exists.","schema":{"type":"integer","description":"Epoch milliseconds."}},"Idempotent-Replayed":{"description":"true when the completed atomic receipt was replayed.","schema":{"type":"boolean"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DocumentLeaseAcknowledgement"}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/DocumentProtocol400"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentProtocol409"},"412":{"$ref":"#/components/responses/DocumentProtocol412"},"422":{"$ref":"#/components/responses/DocumentProtocol422"},"428":{"$ref":"#/components/responses/DocumentProtocol428"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"$ref":"#/components/responses/EntitlementUnavailable"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Clerk-issued bearer token. Two accepted forms:\n  1) Session JWT - issued to a logged-in dashboard or extension user.\n  2) `oat_*` - Clerk OAuth user-delegation token (used by the ChatGPT MCP connector and other OAuth clients).\n\nBoth forms bypass scope gating. Scope gating applies to first-party `gm_*` API keys, which MUST carry the requested scope in the key's `permissions` array. The OAuth metadata for token acquisition is published at `/.well-known/oauth-authorization-server` (delegated to Clerk) and `/.well-known/oauth-protected-resource/v1` (this REST resource)."},"apiKeyAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"ContextRepo first-party API key. Header value MUST be exactly `API-Key gm_<publicId>_<secret>` (note the leading `API-Key ` prefix and the underscore-delimited two-part secret). Permissions are taken from the key's `permissions` array stored in the `apiKeys` table; bcrypt is used to verify the secret."}},"parameters":{"Limit":{"name":"limit","in":"query","schema":{"type":"integer","default":20,"minimum":1,"maximum":100},"description":"Maximum number of items to return."},"Cursor":{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor returned by the previous list response. Some endpoints encode a base64 offset; others return a Convex paginated cursor. Treat as opaque."},"Search":{"name":"search","in":"query","schema":{"type":"string"},"description":"Substring filter on the collection name or description."},"IncludeContent":{"name":"includeContent","in":"query","schema":{"type":"boolean","default":false},"description":"When true, include resource content in the response (truncated to 2,000 characters per item on list endpoints)."},"IdPath":{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Convex ID of the resource (a 27-character alphanumeric string)."},"Tags":{"name":"tags","in":"query","schema":{"type":"string"},"description":"Comma-separated list of tags. Items must match ALL supplied tags (AND semantics). Whitespace is trimmed; empty entries are ignored. Tag values must not contain commas."},"IfMatch":{"name":"If-Match","in":"header","schema":{"type":"string","pattern":"^(?:W/)?\"doc:[^\":]+:rev:(0|[1-9]\\d*):sha256:[a-f0-9]{64}-gzip\"$|^\"doc:[^\":]+:rev:(0|[1-9]\\d*):sha256:[a-f0-9]{64}\"$"},"description":"Document revision validator returned by a prior read. Treat it as opaque and return it unchanged in `If-Match`; the canonical form, exact hosted `-gzip` form, and exact weak hosted `W/\"...-gzip\"` form are accepted. A weak canonical validator without `-gzip` is invalid. Clients must not synthesize or normalize any form. Required for policy enable/disable and every canonical write while lease coordination is required, except that PATCH and restore may use body `expectedRevision` instead. This alternative applies only to PATCH and restore; refresh and coordination-policy operations retain their existing preconditions. If both are supplied their revisions must agree and the If-Match content hash remains enforced. Exact retries must preserve their original precondition representation."},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","schema":{"type":"string","minLength":1,"maxLength":255},"description":"Atomic operation receipt key. Required for lease operations and coordinated writes; optional for standard-mode short writes."},"DocumentLeaseId":{"name":"X-ContextRepo-Lease-Id","in":"header","schema":{"type":"string","minLength":1,"maxLength":255},"description":"Opaque lease ID. Required with the fence for renew, release, and canonical writes under lease_required policy; omit when acquiring."},"DocumentLeaseFence":{"name":"X-ContextRepo-Lease-Fence","in":"header","schema":{"type":"integer","minimum":0},"description":"Current lease fencing generation. Required with the lease ID for renew, release, and canonical writes under lease_required policy; omit when acquiring."}},"responses":{"BadRequest":{"description":"Bad Request - malformed body or invalid parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error400"}}}},"Unauthorized":{"description":"Unauthorized - missing or invalid Authorization header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error401"}}}},"Forbidden":{"description":"Forbidden - the caller's identity does not include the required scope or does not own the resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error403"}}}},"NotFound":{"description":"Not Found - resource does not exist or is not visible to the caller","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error404"}}}},"Conflict":{"description":"Conflict - the request conflicts with the current state of the resource (e.g., deleting a non-empty collection)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error409"}}}},"PayloadTooLarge":{"description":"Payload Too Large - one of the body fields exceeds its byte cap (e.g., document content > 2 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error413"}}}},"TooManyRequests":{"description":"Rate limit exceeded. Honor the `Retry-After` header.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Limit for the bucket"},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining quota in the bucket"},"X-RateLimit-Reset":{"schema":{"type":"string","format":"date-time"},"description":"ISO 8601 timestamp for when the window resets (emitted via Date.toISOString())."},"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the next retry is allowed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error429"}}}},"InternalServerError":{"description":"Internal Server Error - unhandled exception in a route handler","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error500"}}}},"DocumentProtocol400":{"description":"400 document revision protocol error. Authorized responses include current revision and ETag metadata when available.","headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentProtocolError"}}}},"DocumentProtocol409":{"description":"409 document revision protocol error. Authorized responses include current revision and ETag metadata when available.","headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentProtocolError"}}}},"DocumentProtocol412":{"description":"412 document revision protocol error. Authorized responses include current revision and ETag metadata when available.","headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentProtocolError"}}}},"DocumentProtocol422":{"description":"422 document revision protocol error. Authorized responses include current revision and ETag metadata when available.","headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentProtocolError"}}}},"DocumentProtocol428":{"description":"428 document revision protocol error. Authorized responses include current revision and ETag metadata when available.","headers":{"ETag":{"description":"Document revision ETag; hosted delivery may mark the representation weak.","schema":{"type":"string"}},"X-ContextRepo-Revision":{"description":"Current canonical document revision.","schema":{"type":"integer","minimum":0}},"X-ContextRepo-Content-Hash":{"description":"SHA-256 hash of the current canonical content.","schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentProtocolError"}}}},"PaymentRequired":{"description":"Payment Required - the caller has no active plan, the plan does not include this feature, or a metered allowance is used up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementError"}}}},"EntitlementUnavailable":{"description":"Service Unavailable - the caller's plan could not be confirmed. Retry after the Retry-After interval","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementError"}}}}},"schemas":{"Prompt":{"type":"object","description":"A prompt template owned by the authenticated user. Note: POST /v1/prompts/{id}/restore returns this shape without tags.","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"content":{"type":"string"},"parameters":{"type":"object","additionalProperties":true},"variables":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean"]},"description":{"type":"string"}},"required":["name","type"]}},"isPublic":{"type":"boolean"},"isArchived":{"type":"boolean"},"currentVersion":{"type":"integer"},"tags":{"type":"array","items":{"type":"string"},"description":"Omitted on the restore response"},"stats":{"type":"object","properties":{"views":{"type":"integer"},"copies":{"type":"integer"}},"required":["views","copies"]}},"required":["id","title","content"]},"PromptListItem":{"type":"object","description":"List-shape prompt returned by GET /v1/prompts. Includes full content.","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"content":{"type":"string"},"isPublic":{"type":"boolean"},"currentVersion":{"type":"integer"},"tags":{"type":"array","items":{"type":"string"}},"stats":{"type":"object","properties":{"views":{"type":"integer"},"copies":{"type":"integer"}},"required":["views","copies"]},"createdAt":{"type":"integer","description":"Epoch milliseconds"},"updatedAt":{"type":"integer","description":"Epoch milliseconds"}},"required":["id","title"]},"PromptVersion":{"type":"object","properties":{"id":{"type":"string","description":"Version row id"},"version":{"type":"integer"},"content":{"type":"string","description":"Full content of this version"},"changeLog":{"type":"string"},"userName":{"type":"string","description":"Display name of the user who created the version"}},"required":["id","version","content"]},"PromptCreateRequest":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"content":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"variables":{"type":"array","items":{"$ref":"#/components/schemas/Prompt/properties/variables/items"}},"parameters":{"type":"object","additionalProperties":true}},"required":["title","description","content"]},"PromptUpdateRequest":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"content":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"variables":{"type":"array","items":{"$ref":"#/components/schemas/Prompt/properties/variables/items"}},"parameters":{"type":"object","additionalProperties":true},"changeLog":{"type":"string"}}},"Document":{"type":"object","description":"Public document detail projection. Storage IDs, ownership IDs, principal IDs, and credential IDs are never exposed. Content fields may be omitted when includeContent=false.","properties":{"id":{"type":"string"},"title":{"type":"string"},"content":{"type":"string"},"contentHtml":{"type":"string"},"rawHtml":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","failed"]},"isArchived":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"sourceType":{"type":"string"},"sourceUrl":{"type":"string","format":"uri"},"source":{"type":"object","description":"Public freshness metadata for a refreshable document source. Internal refresh lock fields are never exposed.","properties":{"contentHash":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"SHA-256 hash of the current source markdown."},"lastCheckedAt":{"type":"integer","description":"Epoch milliseconds when the source was last checked."},"lastChangedAt":{"type":"integer","description":"Epoch milliseconds when a refresh last detected changed source content."},"lastRefreshError":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"at":{"type":"integer","description":"Epoch milliseconds when the refresh failed."}},"required":["code","message","at"]}}},"currentVersion":{"type":"integer","minimum":0,"deprecated":true,"description":"Deprecated alias of revision."},"stats":{"type":"object","properties":{"views":{"type":"integer"},"shares":{"type":"integer"},"exports":{"type":"integer"},"lastViewedAt":{"type":"integer","description":"Epoch milliseconds"}},"required":["views"]},"createdAt":{"type":"integer","description":"Epoch milliseconds"},"updatedAt":{"type":"integer","description":"Epoch milliseconds"},"metadata":{"$ref":"#/components/schemas/DocumentMetadata"},"revision":{"type":"integer","minimum":0},"contentHash":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."},"lastChangedAt":{"type":"integer","description":"Epoch milliseconds."},"snapshotCompleteness":{"$ref":"#/components/schemas/DocumentSnapshotCompleteness"},"actor":{"$ref":"#/components/schemas/DocumentActor"},"origin":{"$ref":"#/components/schemas/DocumentOrigin"},"etag":{"type":"string","description":"Canonical strong validator for the current document revision. Hosted delivery can expose a representation-specific `W/\"...-gzip\"` ETag response header; either server-returned value is accepted unchanged in `If-Match`."},"isPublic":{"type":"boolean","description":"Whether an explicitly pinned public snapshot is enabled."},"publicVersion":{"type":"integer","minimum":1,"description":"Pinned revision exposed by the public share route."}},"required":["id","title"]},"DocumentListItem":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","failed"]},"isArchived":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"updatedAt":{"type":"integer","description":"Epoch milliseconds"},"content":{"type":"string","description":"Truncated to 2,000 chars when includeContent=true"}},"required":["id","title"]},"DocumentVersion":{"type":"object","description":"Public immutable document revision projection. Internal storage, owner, principal, and credential IDs are excluded.","properties":{"id":{"type":"string","description":"Version row ID."},"documentId":{"type":"string"},"version":{"type":"integer","minimum":0},"title":{"type":"string"},"content":{"type":"string"},"contentHtml":{"type":"string"},"rawHtml":{"type":"string"},"sourceUrl":{"type":"string","format":"uri"},"metadata":{"$ref":"#/components/schemas/DocumentMetadata"},"tags":{"type":"array","items":{"type":"string"}},"revision":{"type":"integer","minimum":0},"currentVersion":{"type":"integer","minimum":0,"deprecated":true,"description":"Deprecated alias of revision."},"contentHash":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."},"lastChangedAt":{"type":"integer","description":"Epoch milliseconds."},"snapshotCompleteness":{"$ref":"#/components/schemas/DocumentSnapshotCompleteness"},"actor":{"$ref":"#/components/schemas/DocumentActor"},"origin":{"$ref":"#/components/schemas/DocumentOrigin"},"changeLog":{"type":"string"},"operationId":{"type":"string"},"createdAt":{"type":"integer","description":"Epoch milliseconds."}},"required":["id","documentId","version","title"],"additionalProperties":false},"DocumentCreateRequest":{"type":"object","properties":{"title":{"type":"string"},"content":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"collectionIds":{"type":"array","items":{"type":"string"}},"origin":{"type":"string","enum":["mcp","browser_extension"],"description":"Optional capture-origin tag surfaced in the dashboard Source row; any other value is silently dropped."}},"required":["title","content"]},"DocumentUpdateRequest":{"type":"object","description":"Patch a document snapshot. Every property is optional: omission preserves the current value. Empty content is valid, [] clears tags, {} clears metadata, and JSON null explicitly clears contentHtml, rawHtml, or sourceUrl.","properties":{"title":{"type":"string","description":"Omitted means preserve."},"content":{"type":"string","description":"Omitted means preserve; an empty string is valid Markdown."},"contentHtml":{"type":["string","null"],"description":"Omitted means preserve; null means clear."},"rawHtml":{"type":["string","null"],"description":"Omitted means preserve; null means clear."},"sourceUrl":{"type":["string","null"],"format":"uri","description":"Omitted means preserve; null means clear."},"metadata":{"$ref":"#/components/schemas/DocumentMetadata","description":"Omitted means preserve; an empty object clears metadata."},"tags":{"type":"array","items":{"type":"string"},"description":"Omitted means preserve; an empty array clears all tags."},"changeLog":{"type":"string","description":"Optional descriptive change note; never treated as an identity claim."},"expectedRevision":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Original expected document revision. For PATCH and restore only, an alternative to If-Match. If both are supplied their revisions must agree; the If-Match content hash remains enforced. Exact retries must preserve their original precondition representation."}},"additionalProperties":false},"ScrapeRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"collectionIds":{"type":"array","items":{"type":"string"}},"options":{"type":"object","additionalProperties":true,"description":"Optional scraper options forwarded to the Firecrawl provider"}},"required":["url"]},"Collection":{"type":"object","description":"A collection (folder) of documents and prompts.","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string","description":"Single-emoji icon"},"isPublic":{"type":"boolean"},"parentCollectionId":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"itemCount":{"type":"integer"},"lastActivityAt":{"type":"integer","description":"Epoch milliseconds"},"createdAt":{"type":"integer","description":"Epoch milliseconds"},"updatedAt":{"type":"integer","description":"Epoch milliseconds"},"stats":{"type":"object","description":"GET /v1/collections/{id} only. Present for any authenticated caller with read access to the collection (session, API-key, and machine auth alike).","properties":{"totalItems":{"type":"integer"},"documentCount":{"type":"integer"},"promptCount":{"type":"integer"},"lastActivityAt":{"type":"integer","description":"Epoch milliseconds"},"topContributors":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"string"},"itemCount":{"type":"integer"}},"required":["userId","itemCount"]}}}}},"required":["id","name"]},"CollectionListItem":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"itemCount":{"type":"integer"},"lastActivityAt":{"type":"integer","description":"Epoch milliseconds"},"isPublic":{"type":"boolean"},"parentCollectionId":{"type":"string"}},"required":["id","name"]},"CollectionCreateRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"parentCollectionId":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}}},"required":["name"]},"CollectionUpdateRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"},"icon":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"isPublic":{"type":"boolean"}}},"CollectionMembershipMutation":{"type":"object","properties":{"itemIds":{"type":"array","items":{"type":"string"}},"itemType":{"type":"string","enum":["document","prompt"]}},"required":["itemIds","itemType"]},"CollectionItem":{"type":"object","description":"An item row from GET /v1/collections/{id}/items.","properties":{"itemType":{"type":"string","enum":["document","prompt"]},"itemId":{"type":"string"},"title":{"type":"string"},"summary":{"type":["string","null"],"description":"Prompt description, or null (documents have no description column; the key is always present)."},"content":{"type":"string","description":"Documents only, when includeContent=true. Prompts never include content on this endpoint."}},"required":["itemType","itemId","title","summary"]},"User":{"type":"object","description":"Resolved authenticated identity returned by GET /v1/user/me.","properties":{"id":{"type":"string","description":"Convex user id"},"name":{"type":"string"},"externalId":{"type":"string","description":"Clerk user id"},"authMethod":{"type":"string","enum":["api_key","bearer"],"description":"Back-compat binary label: api_key for gm_* first-party keys, bearer for everything else."},"kind":{"type":"string","enum":["session","apiKey"],"description":"Authoritative auth shape: session = Clerk session JWT or oat_* OAuth user-delegation token; apiKey = gm_* first-party API key."},"permissions":{"oneOf":[{"type":"string","const":"user-delegation"},{"type":"array","items":{"type":"string"}}],"description":"The literal string \"user-delegation\" for session auth (full per-user authority); otherwise the granted scope/permission list from the token or apiKeys row."},"plan":{"type":"object","description":"The caller's live plan. slug is null when no plan is in force right now, whatever the subscription row says.","properties":{"slug":{"type":["string","null"],"enum":["pro","pro_max","ultimate",null]},"status":{"type":"string","description":"The subscription item status, or \"none\" when there is no subscription."},"isFreeTrial":{"type":"boolean"},"periodEnd":{"type":["number","null"],"description":"Unix epoch milliseconds."}}},"usage":{"type":"array","description":"One entry per meter, in catalog order. Empty when slug is null. used includes credits reserved by work still in flight.","items":{"type":"object","properties":{"meter":{"type":"string","enum":["reasonCalls","scrapeCredits","parseCredits"]},"used":{"type":"number"},"limit":{"type":"number"},"resetsAt":{"type":"number","description":"Unix epoch milliseconds at which the window rolls over."}}}}},"required":["id","name","externalId","authMethod","kind","permissions"]},"SearchResults":{"type":"object","description":"GET /v1/search response. Result item fields differ between semantic (default) and literal (semantic=false) modes; see per-field descriptions on the item schemas.","properties":{"data":{"type":"object","properties":{"prompts":{"type":"array","items":{"$ref":"#/components/schemas/SearchPromptResult"}},"documents":{"type":"array","items":{"$ref":"#/components/schemas/SearchDocumentResult"}},"collections":{"type":"array","items":{"$ref":"#/components/schemas/SearchCollectionResult"}}}},"meta":{"type":"object","properties":{"query":{"type":"string"},"semantic":{"type":"boolean"},"latencyMs":{"type":"integer","description":"Semantic mode only"}},"required":["query","semantic"]}},"required":["data"]},"PdSearchRequest":{"type":"object","properties":{"query":{"type":"string"},"documentId":{"type":"string","description":"Restrict to chunks of a single document"},"collectionId":{"type":"string","description":"Restrict to chunks of documents in a collection"},"sessionId":{"type":"string","description":"Optional session ID for de-duplication across iterative queries. Must come from POST /v1/pd/session; an unknown or expired sessionId is rejected with 400."},"limit":{"type":"integer","default":10,"minimum":1,"maximum":100},"maxTokens":{"type":"integer","description":"Token budget for the returned result set"},"detailLevel":{"type":"string","enum":["summary","full"],"default":"summary","description":"summary returns condensed chunk content; full returns the complete chunk text."}},"required":["query"]},"ReasonRequest":{"type":"object","properties":{"query":{"type":"string","pattern":"\\S","maxLength":2000,"description":"The natural-language question to answer over the caller's documents. Must contain at least one non-whitespace character and at most 2000; the server trims leading and trailing whitespace."},"limit":{"type":"number","default":50,"description":"Gather breadth — number of chunks retrieved before synthesis. Values outside [1, 50] are clamped to the nearest bound (not rejected); non-integers are truncated."},"maxTokens":{"type":"number","default":8000,"description":"Token budget for gathered evidence passed to synthesis. Finite values are truncated to an integer and negative values are normalized to zero."},"documentId":{"type":"string","description":"Restrict synthesis to a single document"},"collectionId":{"type":"string","description":"Restrict synthesis to documents in a collection"}},"required":["query"]},"PdExpandRequest":{"type":"object","properties":{"chunkId":{"type":"string"},"direction":{"type":"string","enum":["up","down","next","previous","surrounding"]},"count":{"type":"integer","minimum":1,"maximum":25,"default":2,"description":"Neighbours per side (only used by direction=surrounding)"}},"required":["chunkId","direction"]},"PaginationInfo":{"type":"object","properties":{"cursor":{"type":"string","description":"Opaque cursor for the next page (empty string when no more results)"},"hasMore":{"type":"boolean"}},"required":["cursor","hasMore"]},"DeleteAck":{"type":"object","description":"Mission M-048 delete acknowledgment - 200 + body, NOT 204.","properties":{"success":{"type":"boolean","const":true},"id":{"type":"string"}},"required":["success","id"]},"ErrorEnvelope":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"integer"},"message":{"type":"string"},"details":{}},"required":["code","message"]}},"required":["error"]},"Error400":{"$ref":"#/components/schemas/ErrorEnvelope"},"Error401":{"$ref":"#/components/schemas/ErrorEnvelope"},"Error403":{"$ref":"#/components/schemas/ErrorEnvelope"},"Error404":{"$ref":"#/components/schemas/ErrorEnvelope"},"Error409":{"$ref":"#/components/schemas/ErrorEnvelope"},"Error413":{"$ref":"#/components/schemas/ErrorEnvelope"},"Error429":{"$ref":"#/components/schemas/ErrorEnvelope"},"Error500":{"$ref":"#/components/schemas/ErrorEnvelope"},"SearchPromptResult":{"type":"object","properties":{"promptId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"score":{"type":"number","description":"Semantic mode only"},"highlight":{"type":"string","description":"Literal mode only - ~200-char snippet centred on the first content match; omitted when the match is title/description-only."},"tags":{"type":"array","items":{"type":"string"}}},"required":["promptId","title"]},"SearchDocumentResult":{"type":"object","properties":{"documentId":{"type":"string"},"title":{"type":"string"},"score":{"type":"number","description":"Semantic mode only"},"highlight":{"type":"string","description":"Match snippet. Always present in semantic mode; present in literal mode when the match came from content."},"chunkId":{"type":"string","description":"Literal mode only - present when the match was found in a hierarchical chunk (full-body literal search); usable with /v1/pd/read and /v1/pd/expand."},"tags":{"type":"array","items":{"type":"string"}}},"required":["documentId","title"]},"SearchCollectionResult":{"type":"object","properties":{"collectionId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","description":"Literal mode only"},"score":{"type":"number","description":"Semantic mode only"},"matchedItems":{"type":"integer","description":"Semantic mode only - number of member items that matched"},"tags":{"type":"array","items":{"type":"string"}}},"required":["collectionId","name"]},"PdSearchResult":{"type":"object","description":"A ranked chunk returned by POST /v1/pd/search.","properties":{"chunkId":{"type":"string"},"content":{"type":"string","description":"Summarized by default (detailLevel=summary); the full chunk text when detailLevel=full."},"score":{"type":"number","description":"Similarity score (0-1)"},"level":{"type":"string","enum":["document","section","paragraph"]},"parentId":{"type":["string","null"],"description":"Parent chunk id, or null at document level"},"siblingIds":{"type":"object","properties":{"prev":{"type":["string","null"]},"next":{"type":["string","null"]}},"required":["prev","next"]},"documentId":{"type":"string"},"documentTitle":{"type":"string"}},"required":["chunkId","content","score","level","parentId","siblingIds","documentId","documentTitle"]},"PdExpandChunk":{"type":"object","description":"A chunk returned by POST /v1/pd/expand. Note the id field is named _id on this endpoint.","properties":{"_id":{"type":"string","description":"Chunk id (named _id on this endpoint)"},"content":{"type":"string"},"level":{"type":"string","enum":["document","section","paragraph"]},"parentId":{"type":["string","null"],"description":"Parent chunk id, or null at document level"},"chunkIndex":{"type":"integer"},"documentId":{"type":"string"},"documentTitle":{"type":"string"}},"required":["_id","content","level","parentId","chunkIndex","documentId","documentTitle"]},"PdReadResult":{"type":"object","description":"Full chunk read returned by GET /v1/pd/read/{chunkId}.","properties":{"chunkId":{"type":"string"},"content":{"type":"string"},"level":{"type":"string","enum":["document","section","paragraph"]},"hierarchy":{"type":"object","properties":{"documentId":{"type":"string"},"documentTitle":{"type":"string"},"sectionPath":{"type":"string","description":"Human-readable section path string (e.g. \"Intro > Setup\")"},"position":{"type":"object","properties":{"chunkIndex":{"type":"integer"},"parentChunkId":{"type":["string","null"]},"prevSiblingId":{"type":["string","null"]},"nextSiblingId":{"type":["string","null"]}},"required":["chunkIndex","parentChunkId","prevSiblingId","nextSiblingId"]}},"required":["documentId","documentTitle","sectionPath","position"]},"metadata":{"type":"object","properties":{"startIndex":{"type":"integer"},"endIndex":{"type":"integer"},"wordCount":{"type":"integer"},"sectionPath":{"type":"string"},"headingText":{"type":"string"}},"required":["startIndex","endIndex","wordCount","sectionPath"]}},"required":["chunkId","content","level","hierarchy","metadata"]},"DocumentActor":{"type":"object","description":"Safe server-derived actor projection. Principal and credential identifiers are never exposed.","properties":{"kind":{"type":"string","enum":["user","api_key","oauth","machine","system","migration"]},"displayName":{"type":"string"}},"required":["kind"],"additionalProperties":false},"DocumentOrigin":{"type":"string","enum":["dashboard","rest","mcp","manual_create","file_ingest","scrape_ingest","source_refresh","restore","migration"],"description":"Server-derived origin of the canonical revision."},"DocumentSnapshotCompleteness":{"type":"string","enum":["legacy_partial","synthetic_current","complete"],"description":"Whether the revision row represents every canonical snapshot field."},"DocumentMetadata":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"author":{"type":"string"},"publishedDate":{"type":"string"},"extractedData":{"type":"object","additionalProperties":{"type":"string"}}},"additionalProperties":false},"DocumentAcknowledgement":{"type":"object","description":"Compact acknowledgement returned by canonical document writes.","properties":{"id":{"type":"string"},"revision":{"type":"integer","minimum":0},"currentVersion":{"type":"integer","minimum":0,"deprecated":true,"description":"Deprecated alias of revision."},"contentHash":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."},"lastChangedAt":{"type":"integer","description":"Epoch milliseconds."},"noop":{"type":"boolean"},"warnings":{"type":"array","items":{"type":"string","enum":["LEGACY_PARTIAL_SNAPSHOT"]}}},"required":["id","revision","currentVersion","contentHash","lastChangedAt","noop"],"additionalProperties":false},"DocumentProtocolErrorDetails":{"type":"object","description":"Authorized conflict metadata. Current revision and ETag are included when available; content and credential identifiers are never included.","properties":{"documentId":{"type":"string"},"revision":{"type":"integer","minimum":0},"contentHash":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Lowercase SHA-256 digest."},"lastChangedAt":{"type":"integer","description":"Epoch milliseconds."},"etag":{"type":"string"}},"additionalProperties":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"DocumentProtocolError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"integer","enum":[400,409,412,422,428]},"reason":{"type":"string","enum":["INVALID_PRECONDITION","LEASE_CONFLICT","FENCE_MISMATCH","OPERATION_IN_PROGRESS","REVISION_MISMATCH","IDEMPOTENCY_KEY_REUSED","DOCUMENT_NOT_COORDINATABLE","PRECONDITION_REQUIRED"]},"message":{"type":"string"},"details":{"$ref":"#/components/schemas/DocumentProtocolErrorDetails"}},"required":["code","reason","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false},"DocumentCoordinationLease":{"type":"object","description":"Active or most recently observed lease summary. leaseId is returned only when heldByCaller=true.","properties":{"active":{"type":"boolean"},"heldByCaller":{"type":"boolean"},"holderDisplayName":{"type":"string"},"expiresAt":{"type":"integer","description":"Epoch milliseconds."},"leaseId":{"type":"string","description":"Opaque lease ID, present only for the current holder."}},"required":["active","heldByCaller","expiresAt"],"additionalProperties":false},"DocumentCoordinationState":{"type":"object","properties":{"documentId":{"type":"string"},"policy":{"type":"string","enum":["standard","lease_required"]},"fence":{"type":"integer","minimum":0},"lease":{"oneOf":[{"$ref":"#/components/schemas/DocumentCoordinationLease"},{"type":"null"}]},"updatedAt":{"type":["integer","null"],"description":"Epoch milliseconds, or null when no coordination row exists."}},"required":["documentId","policy","fence","lease","updatedAt"],"additionalProperties":false},"DocumentCoordinationDisableResult":{"type":"object","properties":{"documentId":{"type":"string"},"policy":{"type":"string","const":"standard"},"fence":{"type":"integer","minimum":0},"disabledAt":{"type":["integer","null"],"description":"Epoch milliseconds, or null for a never-managed document."}},"required":["documentId","policy","fence","disabledAt"],"additionalProperties":false},"DocumentLeaseOperationRequest":{"type":"object","properties":{"action":{"type":"string","enum":["acquire","renew","release"]},"ttlMs":{"type":"integer","minimum":15000,"maximum":300000,"description":"Allowed only for acquire and renew."}},"required":["action"],"additionalProperties":false},"DocumentLeaseAcknowledgement":{"type":"object","properties":{"documentId":{"type":"string"},"action":{"type":"string","enum":["acquire","renew","release"]},"fence":{"type":"integer","minimum":0},"leaseId":{"type":"string","description":"Present for successful acquire/renew by the caller."},"expiresAt":{"type":"integer","description":"Epoch milliseconds."},"released":{"type":"boolean"},"freshlyAcquired":{"type":"boolean","description":"True only when acquire allocated a new lease and fence."}},"required":["documentId","action","fence","released"],"additionalProperties":false},"EntitlementError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"integer","enum":[402,503]},"reason":{"type":"string","enum":["PLAN_REQUIRED","FEATURE_NOT_IN_PLAN","QUOTA_EXCEEDED","ENTITLEMENT_UNAVAILABLE"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}}},"required":["code","reason","message"]}},"required":["error"]}}}}