{"openapi":"3.1.0","info":{"title":"ChatPRD API","version":"1.0.0","summary":"Read, search, create and update ChatPRD documents from agents and automations.","description":"The ChatPRD API gives agents (Meta Muse, custom scripts, automations) scoped access to a user's\nChatPRD workspace: documents, projects, templates, organizations and chats.\n\nAuthenticate every request with an API key created in ChatPRD under **Settings → API Keys**:\n`Authorization: Bearer <CHATPRD_API_KEY>`. Keys are read-only unless created with write access.\n\nGuides: https://www.chatprd.ai/docs/api","contact":{"name":"ChatPRD Support","url":"https://www.chatprd.ai/support","email":"support@chatprd.ai"},"termsOfService":"https://www.chatprd.ai/terms"},"servers":[{"url":"https://app.chatprd.ai/api/connectors/v1","description":"Production"}],"tags":[{"name":"Account","description":"Who the API key belongs to."},{"name":"Documents","description":"List, search, read, create and update documents."},{"name":"Workspace","description":"Projects, templates, organizations and chats."}],"security":[{"apiKey":["connector:read"]}],"paths":{"/me":{"get":{"tags":["Account"],"operationId":"getMe","summary":"Get the current user","description":"Returns the profile, plan, API key scopes and organizations of the user who owns the API key. Call this first to discover the user's workspaces.","responses":{"200":{"description":"The current user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanRequired"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/documents":{"get":{"tags":["Documents"],"operationId":"listDocuments","summary":"List or search documents","description":"Lists the most recently updated documents the user can access, or searches by title and content when `q` is provided. Without `organizationId` the personal workspace is used; with it, the team workspace. Responses contain summaries only — use `GET /documents/{id}` to read the Markdown content.","parameters":[{"name":"q","in":"query","required":false,"description":"Full-text search over document titles and content (1–200 characters).","schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"organizationId","in":"query","required":false,"description":"Clerk organization ID (`org_…`). Scopes the request to that team workspace instead of the personal workspace.","schema":{"type":"string"}},{"name":"projectId","in":"query","required":false,"description":"Project ID, as returned by `GET /projects`.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return (1–100). Defaults to 20.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Matching documents, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentList"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanRequired"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"tags":["Documents"],"operationId":"createDocument","summary":"Create a document","description":"Creates a document from complete Markdown content. Requires a key with write access (`connector:write`). The document appears in the user's library (and in the given project/organization when specified).","security":[{"apiKey":["connector:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDocumentRequest"},"example":{"title":"Mobile onboarding PRD","contentMarkdown":"# Mobile onboarding PRD\n\n## Problem\n\nNew users drop off before..."}}}},"responses":{"201":{"description":"The created document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentMutationResult"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/UnauthorizedWrite"},"402":{"$ref":"#/components/responses/PlanRequired"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/documents/{id}":{"parameters":[{"name":"id","in":"path","required":true,"description":"Document ID (UUID), as returned by `GET /documents`.","schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Documents"],"operationId":"getDocument","summary":"Read a document","description":"Returns a document with its full Markdown content. Pass `organizationId` for documents that live in a team workspace.","parameters":[{"name":"organizationId","in":"query","required":false,"description":"Clerk organization ID (`org_…`). Scopes the request to that team workspace instead of the personal workspace.","schema":{"type":"string"}}],"responses":{"200":{"description":"The document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanRequired"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Documents"],"operationId":"updateDocument","summary":"Update a document","description":"Replaces the document's content with the supplied Markdown. This is a **full replacement**, not a diff: read the document first, apply your edits to the complete Markdown, then send the whole result with the read response's `updatedAt` value as `expectedUpdatedAt`. A concurrent edit returns `409 conflict`. Requires a key with write access (`connector:write`).","security":[{"apiKey":["connector:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDocumentRequest"},"example":{"contentMarkdown":"# Mobile onboarding PRD\n\n## Problem\n\nUpdated problem statement...","expectedUpdatedAt":"2026-09-25T12:00:00.000Z"}}}},"responses":{"200":{"description":"The updated document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentMutationResult"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/UnauthorizedWrite"},"402":{"$ref":"#/components/responses/PlanRequired"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/projects":{"get":{"tags":["Workspace"],"operationId":"listProjects","summary":"List projects","description":"Lists the user's projects — personal projects by default, or the organization's projects when `organizationId` is given. Use a project's `id` as `projectId` when listing or creating documents.","parameters":[{"name":"organizationId","in":"query","required":false,"description":"Clerk organization ID (`org_…`). Scopes the request to that team workspace instead of the personal workspace.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return (1–100). Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Projects.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectList"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanRequired"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/templates":{"get":{"tags":["Workspace"],"operationId":"listTemplates","summary":"List templates","description":"Lists document templates available to the user, including ChatPRD's built-in templates unless `includeSystem=false`.","parameters":[{"name":"organizationId","in":"query","required":false,"description":"Clerk organization ID (`org_…`). Scopes the request to that team workspace instead of the personal workspace.","schema":{"type":"string"}},{"name":"includeSystem","in":"query","required":false,"description":"Include ChatPRD's built-in templates. Defaults to `true`.","schema":{"type":"string","enum":["true","false"],"default":"true"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return (1–100). Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Templates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateList"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanRequired"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/organizations":{"get":{"tags":["Workspace"],"operationId":"listOrganizations","summary":"List organizations","description":"Lists the organizations (teams) the user belongs to. Use an organization's `id` as `organizationId` on other endpoints.","responses":{"200":{"description":"Organizations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationList"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanRequired"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/chats":{"get":{"tags":["Workspace"],"operationId":"listChats","summary":"List or search chats","description":"Lists the user's chat threads, newest first, or searches them by title when `q` is provided.","parameters":[{"name":"q","in":"query","required":false,"description":"Search chat titles (1–200 characters).","schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"organizationId","in":"query","required":false,"description":"Clerk organization ID (`org_…`). Scopes the request to that team workspace instead of the personal workspace.","schema":{"type":"string"}},{"name":"projectId","in":"query","required":false,"description":"Project ID, as returned by `GET /projects`.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return (1–100). Defaults to 20.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Chats.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatList"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PlanRequired"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"ChatPRD API key from Settings → API Keys, sent as `Authorization: Bearer <key>`. Read-only keys carry the `connector:read` scope; read/write keys also carry `connector:write`. Requires a Pro, Team or Enterprise plan."}},"responses":{"InvalidRequest":{"description":"The query string or body failed validation (`invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing, malformed, revoked or unknown API key (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnauthorizedWrite":{"description":"Missing, malformed, revoked or unknown API key, or a read-only key used on a write endpoint (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PlanRequired":{"description":"The user's plan does not include API access (`plan_required`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"The resource does not exist or the user cannot access it (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The document changed after it was read (`conflict`). Fetch it again, reapply the edit, and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests (`rate_limited`). Limits are per API key: 120 requests per minute for read endpoints and 30 per minute for write endpoints. Wait for the number of seconds in `Retry-After`, then retry.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected server error (`internal_error`). Retry once, then contact support.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthorized","plan_required","not_found","invalid_request","conflict","rate_limited","internal_error"]},"message":{"type":"string","description":"Human-readable explanation safe to show to the user."}}}},"example":{"error":{"code":"unauthorized","message":"Invalid or missing API key."}}},"Me":{"type":"object","required":["id","name","email","plan","key","organizations"],"properties":{"id":{"type":"string","description":"Clerk user ID.","example":"user_2abc…"},"name":{"type":["string","null"]},"email":{"type":"string","format":"email"},"plan":{"type":["string","null"],"description":"Price lookup key of the subscription that grants API access (the user's own, or a team's), or `null` when none."},"key":{"type":"object","required":["name","scopes"],"properties":{"name":{"type":["string","null"],"description":"Name given to the key when it was created."},"scopes":{"type":"array","items":{"type":"string","enum":["connector:read","connector:write"]}}}},"organizations":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationRef"}}}},"OrganizationRef":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Clerk organization ID.","example":"org_2abc…"},"name":{"type":"string"}}},"DocumentSummary":{"type":"object","required":["id","title","createdAt","updatedAt","threadId","url"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"threadId":{"type":["string","null"],"description":"Chat thread the document was created in, if any."},"url":{"type":"string","format":"uri","description":"Link to open the document in ChatPRD."}}},"DocumentList":{"type":"object","required":["documents","count"],"properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/DocumentSummary"}},"count":{"type":"integer"}}},"Document":{"type":"object","required":["id","title","contentMarkdown","createdAt","updatedAt","threadId","project","url"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"contentMarkdown":{"type":"string","description":"Full document body as Markdown."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"threadId":{"type":["string","null"]},"project":{"oneOf":[{"$ref":"#/components/schemas/ProjectRef"},{"type":"null"}]},"url":{"type":"string","format":"uri"}}},"ProjectRef":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}},"CreateDocumentRequest":{"type":"object","required":["title","contentMarkdown"],"properties":{"title":{"type":"string","minLength":1,"maxLength":200},"contentMarkdown":{"type":"string","minLength":1,"pattern":"\\S","description":"Complete document body as Markdown. Must contain non-whitespace text."},"projectId":{"type":"string","description":"Project to create the document in."},"organizationId":{"type":"string","description":"Organization workspace to create the document in."}}},"UpdateDocumentRequest":{"type":"object","required":["contentMarkdown","expectedUpdatedAt"],"properties":{"contentMarkdown":{"type":"string","minLength":1,"pattern":"\\S","description":"The complete new Markdown body. Replaces the existing content entirely and must contain non-whitespace text."},"title":{"type":"string","minLength":1,"maxLength":200},"expectedUpdatedAt":{"type":["string","null"],"format":"date-time","description":"The `updatedAt` value from the GET response used to prepare this replacement."},"organizationId":{"type":"string","description":"Required for documents in a team workspace."}}},"DocumentMutationResult":{"type":"object","required":["id","title","threadId","url"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"threadId":{"type":["string","null"]},"url":{"type":"string","format":"uri"}}},"Project":{"type":"object","required":["id","name","description","createdAt","isSharedWithYou"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"isSharedWithYou":{"type":"boolean","description":"True when another member shared this project with the user."}}},"ProjectList":{"type":"object","required":["projects","count"],"properties":{"projects":{"type":"array","items":{"$ref":"#/components/schemas/Project"}},"count":{"type":"integer"}}},"Template":{"type":"object","required":["id","title","description","isSystem","isDefault"],"properties":{"id":{"type":"integer"},"title":{"type":"string"},"description":{"type":["string","null"]},"isSystem":{"type":"boolean","description":"Built-in ChatPRD template."},"isDefault":{"type":"boolean"}}},"TemplateList":{"type":"object","required":["templates","count"],"properties":{"templates":{"type":"array","items":{"$ref":"#/components/schemas/Template"}},"count":{"type":"integer"}}},"Organization":{"type":"object","required":["id","name","createdAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"OrganizationList":{"type":"object","required":["organizations","count"],"properties":{"organizations":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}},"count":{"type":"integer"}}},"Chat":{"type":"object","required":["id","title","createdAt","updatedAt","messageCount","project","url"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"messageCount":{"type":"integer"},"project":{"oneOf":[{"$ref":"#/components/schemas/ProjectRef"},{"type":"null"}]},"url":{"type":"string","format":"uri"}}},"ChatList":{"type":"object","required":["chats","count"],"properties":{"chats":{"type":"array","items":{"$ref":"#/components/schemas/Chat"}},"count":{"type":"integer"}}}}}}