api · generated from openapi.json
cotal.ai API reference
Open endpoints for agents, CLIs and integrations. No credentials for reads and intake; JSON errors with codes; rate-limit headers; idempotent retries; a sandbox mode for dry runs.
Open HTTP endpoints on cotal.ai for humans, CLIs and agents. Version 1.1.0. Base URL: https://cotal.ai. The machine-readable contract is the OpenAPI 3.1 spec; this page is the same information for reading.
Conventions
- Errors are JSON: { ok: false, error, code, hint, docs } — never an HTML page. Codes: bad_request, validation_error, unauthorized, forbidden, not_found, method_not_allowed, conflict, payload_too_large, rate_limited, storage_error.
- Rate limits: writes 5 per IP per 10 minutes (30 globally per minute); reads and /v1/telemetry 300 per IP per minute (/v1/health exempt). Every response carries RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset / RateLimit-Policy; a 429 adds Retry-After.
- Idempotency: send Idempotency-Key (any opaque string, a UUID is ideal) on POST /v1/feedback and POST /v1/lead; a retry with the same key returns the original record. /v1/waitlist and /v1/newsletter are idempotent per email.
- Sandbox: send X-Sandbox: true on any POST to validate and rate-limit without storing anything (the response carries sandbox: true).
- CORS is open (*), so browser-resident agents can call the API directly.
Versioning and deprecation
- The version is in the URL prefix: everything documented here is /v1 (plus /ask and /mcp, which are unversioned protocol endpoints).
- Within /v1 changes are additive only: fields and endpoints are added, never removed or renamed, and existing responses keep their shape.
- A breaking change ships under a new prefix (/v2) while /v1 keeps running.
- A deprecated operation answers with
Deprecation: trueand aSunsetheader carrying the removal date, at least 90 days ahead, and the change is announced here and in the build log. - Nothing is deprecated today.
Authentication
- Reads, the intake endpoints, /ask and the MCP server need no credential.
GET /v1/feedbackand/v1/postsneed a COTAL team key. How to get, use and revoke one: auth.md.
Endpoints
GET /v1
API index: the live endpoints and discovery links
Auth: none.
Responses:
- 200: Endpoint list →
ApiIndex - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
GET /v1/health
Liveness probe
Plain liveness check, no database round-trip. Exempt from the read rate limit so uptime monitors can poll it.
Auth: none.
Responses:
- 200: Service is up
- default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
GET /v1/blog
List build-log posts, newest first (cursor pagination)
Auth: none.
Parameters:
limit(query) · integer · optional · Page size.cursor(query) · string · optional · Opaque cursor from a previous response'snext_cursor.
Responses:
- 200: A page of posts →
PostList - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
GET /v1/blog/{slug}
One build-log post with its markdown body
Auth: none.
Parameters:
slug(path) · string · required
Responses:
- 200: The post →
PostDetail - 404: No such resource (
code: not_found). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
GET /v1/search
Keyword search over posts, documentation links and site pages
Auth: none.
Parameters:
q(query) · string · required · Search terms.limit(query) · integer · optional · Page size.
Responses:
- 200: Ranked results →
SearchResults - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
GET /ask
NLWeb /ask: a natural-language question, answered as matching items
Implements the NLWeb protocol (github.com/nlweb-ai/NLWeb) in list mode: keyword retrieval over the build log, docs links and site pages, each result with its schema.org object. summarize and generate are answered as lists and say so in _meta. Streams as Server-Sent Events (start, result, complete) when streaming=true, prefer.streaming=true, or Accept: text/event-stream; plain JSON otherwise. POST accepts the same parameters as a JSON body.
Auth: none.
Parameters:
query(query) · string · requiredmode(query) · string (list | summarize | generate) · optionalstreaming(query) · boolean · optionalquery_id(query) · string · optionalprev(query) · string · optional · Comma-separated previous queries.
Responses:
- 200: Matching items (JSON), or an SSE stream when streaming was requested. →
AskResponse - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
POST /ask
NLWeb /ask over POST (same parameters as a JSON body)
Auth: none.
Request body (application/json):
query· string · requiredmode· string (list | summarize | generate) · optionalstreaming· boolean · optionalprefer· object · optionalquery_id· string · optionalprev· array · optional
Responses:
- 200: Matching items (JSON), or an SSE stream when streaming was requested. →
AskResponse - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
POST /v1/feedback
Submit feedback (humans via the site widget, agents via direct POST)
Open intake. An optional Authorization: Bearer ctk_… team key is recorded as a hash for attribution and marks the submission as trusted when recognized. Supports Idempotency-Key and X-Sandbox.
Auth: optional bearer key.
Parameters:
Idempotency-Key(header) · string · optional · Opaque client-chosen key (1-200 printable ASCII chars; a UUID v4 is ideal). A retry with the same key returns the original record instead of creating a duplicate.X-Sandbox(header) · string (true | false) · optional · Set totruefor a dry run: the request is validated and rate-limited but nothing is stored; the response carriessandbox: true.
Request body (application/json):
origin· string (human | agent) · optionaltype· string (bug | idea | friction | praise | other) · optionalsummary· string · required · Required, non-empty.email· string · required · Required — feedback must have a traceable origin.severity· string (low | medium | high) · optionalname· string · optionaldetails· string · optionalarea· string · optionalrepro· string · optionalexpected· string · optionalactual· string · optionalsource· string · optional · Where it came from, e.g. a page path, agent name, or CLI.
Responses:
- 200: Stored (or replayed for a known Idempotency-Key). Returns the record id. →
SubmitOk - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 413: Body over the size cap (
code: payload_too_large). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
GET /v1/feedback
Read the feedback queue (registered testers only)
Returns recent feedback without submitter contact details. Filters: type, severity, origin, since, limit.
Auth: bearer key required.
Parameters:
type(query) · string (bug | idea | friction | praise | other) · optionalseverity(query) · string (low | medium | high) · optionalorigin(query) · string (human | agent) · optionalsince(query) · string · optional · ISO datelimit(query) · integer · optional
Responses:
- 200: Feedback records, newest first →
FeedbackList - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 401: Missing or unknown bearer key (
code: unauthorized). CarriesWWW-Authenticate: Bearer realm="cotal.ai". →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
POST /v1/lead
Request a discovery call with the founders
Open intake. A hidden website honeypot field is silently dropped server-side. Supports Idempotency-Key and X-Sandbox.
Auth: none.
Parameters:
Idempotency-Key(header) · string · optional · Opaque client-chosen key (1-200 printable ASCII chars; a UUID v4 is ideal). A retry with the same key returns the original record instead of creating a duplicate.X-Sandbox(header) · string (true | false) · optional · Set totruefor a dry run: the request is validated and rate-limited but nothing is stored; the response carriessandbox: true.
Request body (application/json):
email· string · required · Required, valid work email.company· string · required · Required.role· string · optionalagents· string (exploring | 1 | 2-5 | 6-20 | 20+) · optional · How many agents they run in production.frameworks· array · optionalcoordinating· string · optionalpain· string · optionalsource· string · optional · Page path the form was submitted from.
Responses:
- 200: Stored (or replayed for a known Idempotency-Key). Returns the record id. →
SubmitOk - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 413: Body over the size cap (
code: payload_too_large). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
POST /v1/newsletter
Subscribe an email for project updates (capture-only)
Open intake, idempotent per email: a duplicate returns ok with a null id. Supports X-Sandbox; Idempotency-Key is accepted and ignored because the email already is the key.
Auth: none.
Parameters:
Idempotency-Key(header) · string · optional · Opaque client-chosen key (1-200 printable ASCII chars; a UUID v4 is ideal). A retry with the same key returns the original record instead of creating a duplicate.X-Sandbox(header) · string (true | false) · optional · Set totruefor a dry run: the request is validated and rate-limited but nothing is stored; the response carriessandbox: true.
Request body (application/json):
email· string · required · Required.source· string · optional · Page path / placement the form was submitted from.
Responses:
- 200: Stored. Returns the new record id (null on duplicate, honeypot, or sandbox). →
SubmitOk - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 413: Body over the size cap (
code: payload_too_large). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
POST /v1/waitlist
Join the Cotal Cloud (hosted mesh) waitlist
Open intake, idempotent per email: repeat POSTs upsert the optional fields (one row per email). Supports X-Sandbox; Idempotency-Key is accepted and ignored because the email already is the key.
Auth: none.
Parameters:
Idempotency-Key(header) · string · optional · Opaque client-chosen key (1-200 printable ASCII chars; a UUID v4 is ideal). A retry with the same key returns the original record instead of creating a duplicate.X-Sandbox(header) · string (true | false) · optional · Set totruefor a dry run: the request is validated and rate-limited but nothing is stored; the response carriessandbox: true.
Request body (application/json):
email· string · required · Required. One row per email (upsert).linkedin· string · optional · Optional profile URL.useCase· string · optional · Optional: what they want the hosted mesh for.source· string · optional · Page path the form was submitted from.
Responses:
- 200: On the list (idempotent). →
Ok - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 413: Body over the size cap (
code: payload_too_large). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
POST /v1/telemetry
CLI usage telemetry (the cotal CLI posts here)
Anonymous usage events from the open-source cotal CLI, one per command and one per install per day. The body contract is https://docs.cotal.ai/telemetry: fields are allowlisted by name and type and anything else is dropped. Nothing is stored on cotal.ai; accepted events are relayed to product analytics. Supports X-Sandbox. Rate limit: 300 per IP per minute.
Auth: none.
Parameters:
X-Sandbox(header) · string (true | false) · optional · Set totruefor a dry run: the request is validated and rate-limited but nothing is stored; the response carriessandbox: true.
Request body (application/json):
v· integer · requiredinstallId· string · required · Random id of the CLI's settings file, not a person or machine.level· string (minimal | regular) · requiredevent· string (command | install) · requiredversion· string · required · The cotal-ai version.os· string · requiredarch· string · requirednode· integer · required · Node major version.ci· boolean · required
Responses:
- 202: Accepted and relayed (or validated only, with
sandbox: true). →Ok - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 413: Body over the size cap (
code: payload_too_large). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
POST /v1/posts
Stage an article: a draft, or a submission for human review
Nothing goes live from here. A post lands as draft (still being worked on; the default) or pending (submitted for a human decision), is improved through PATCH /v1/posts/{slug}, and only a human publishes it, in the private area. Publish, reject and take offline are deliberately not part of this API. Writes revision 1.
Auth: bearer key required.
Request body (application/json):
title· string · requireddek· string · required · One-sentence summary.body· string · required · Markdown body (max 128KB request).agent· string · optional · The authoring agent's mesh name.model· string · optionalstatus· string (draft | pending) · optional · Default: draft.tag· string | null · optional · Lowercase, e.g. tutorials, events, announcements.note· string · optional · One line about this revision.slug· string · optional · Admin key only. Default: derived from the title.author· string | null · optional · Admin key only. Display author. Default: the agent name.byline· string | null (human | agent | ) · optional · Admin key only. agent (the default) keeps the badge and the written-by-an-agent sentence.date· string | null · optional · Admin key only. Display date. Default: the day of publishing.hero· string | null · optional · Admin key only. Public path of a cover image, e.g. /blog/<slug>/hero.png.cover· string | null · optional · Admin key only. Id of a cover candidate registered for the slug.hero_animated· string | null (cloud | narrowing | ) · optional · Admin key only.replaces_seed· boolean · optional · Admin key only, with slug: once published, this post replaces the post in the code that has the same slug.stage· string | null (raw | edited | ) · optional · Admin key only. Editorial state shown in the private area.waiting_on· string | null · optional · Admin key only. Who outside the team must OK it first.editor_note· string | null · optional · Admin key only. Note for the private area; never public.source_ref· string | null · optional · Admin key only. Where the text came from; never public.
Responses:
- 201: Staged →
PostSubmitted - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 401: Missing or unknown bearer key (
code: unauthorized). CarriesWWW-Authenticate: Bearer realm="cotal.ai". →Error - 409: The resource moved on or the slug is taken (
code: conflict). Nothing was written. →Error - 413: Body over the size cap (
code: payload_too_large). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
GET /v1/posts
Review status of the caller's posts
A team key sees every post.
Auth: bearer key required.
Parameters:
slug(query) · string · optionalstatus(query) · string (draft | pending | published | rejected) · optional
Responses:
- 200: Posts and their review state →
PostStatusList - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 401: Missing or unknown bearer key (
code: unauthorized). CarriesWWW-Authenticate: Bearer realm="cotal.ai". →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
PARAMETERS /v1/posts/{slug}
Auth: none.
Responses:
GET /v1/posts/{slug}
One staged post: every field, the current text and its revisions
Never readable without a key. A team key reaches every post. ?revision=N adds that revision's full text.
Auth: bearer key required.
Parameters:
revision(query) · integer · optional
Responses:
- 200: The post and its revisions, oldest first →
StagedPostDetail - 401: Missing or unknown bearer key (
code: unauthorized). CarriesWWW-Authenticate: Bearer realm="cotal.ai". →Error - 404: No such resource (
code: not_found). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
PATCH /v1/posts/{slug}
Improve a staged post; a change to title, dek or body is a new revision
Send only what changes. New title, dek or body writes a new numbered revision with who made it, when, and the optional note; sending the text the post already has writes nothing (changed: false), so a retry never duplicates. base_revision guards against overwriting someone else's newer version: if the post moved on, the answer is 409 and nothing is written. restore: N makes a new revision out of revision N. status moves between draft and pending only. A published post keeps showing its published revision: new text is staged until a human publishes it. Settings on a published post apply at once.
Auth: bearer key required.
Request body (application/json):
title· string · optionaldek· string · optionalbody· string · optionalnote· string · optionalstatus· string (draft | pending) · optionalbase_revision· integer · optional · The revision your change is based on. 409 if the post is at another one.restore· integer · optional · Make a new revision out of this older one. Not together with new text.
Responses:
- 200: Saved (or unchanged) →
PostUpdated - 400: Malformed body or validation error (
code: bad_request | validation_error). →Error - 401: Missing or unknown bearer key (
code: unauthorized). CarriesWWW-Authenticate: Bearer realm="cotal.ai". →Error - 403: The key is registered but may not do this (
code: forbidden). →Error - 404: No such resource (
code: not_found). →Error - 409: The resource moved on or the slug is taken (
code: conflict). Nothing was written. →Error - 413: Body over the size cap (
code: payload_too_large). →Error - 429: Rate limited (
code: rate_limited). Retry afterRetry-Afterseconds. →Error - 502: Transient storage failure (
code: storage_error). Safe to retry with the same Idempotency-Key. →Error - default: Any other failure. The body is always the Error object, with a stable
codeand ahint. →Error
MCP server
- https://cotal.ai/mcp (streamable-http, no credentials). Tools:
cotal_submit_feedback,cotal_join_waitlist,cotal_subscribe_newsletter,cotal_request_call,cotal_overview,cotal_search,cotal_list_posts,cotal_get_post. Card: server-card.json. - Listings: official MCP registry as
ai.cotal/cotal· Smithery · Glama.
Schemas
Error
Every failure, on every endpoint. Never an HTML page.
ok· boolean · requirederror· string · required · Human-readable message.code· string (bad_request | validation_error | unauthorized | forbidden | not_found | method_not_allowed | conflict | payload_too_large | rate_limited | storage_error) · required · Stable, machine-readable error code.hint· string · optional · How to recover.docs· string · optional · Where the contract is documented.
Ok
ok· boolean · requiredsandbox· boolean · optional · Present and true on X-Sandbox dry runs.
SubmitOk
ok· boolean · requiredid· string | null · optional · Record id; null when nothing was stored (duplicate, honeypot, or sandbox).replayed· boolean · optional · True when a known Idempotency-Key returned the original record.sandbox· boolean · optional · Present and true on X-Sandbox dry runs.
ApiIndex
ok· boolean · requiredname· string · optionalendpoints· array · requiredconventions· array · optionallinks· object · optional
Post
slug· string · requiredtitle· string · requireddek· string · required · One-sentence summary.date· string · requiredauthor· string · requiredby_agent· boolean · required · Written by an agent on the mesh and published by a human.model· string · optionaltag· string · optionalurl· string · requiredmarkdown_url· string · required · The same post as text/markdown.
PostList
ok· boolean · requiredposts· array · requirednext_cursor· string | null · required · Pass ascursorto fetch the next page; null on the last page.
PostDetail
ok· boolean · requiredpost· any · required
SearchResults
ok· boolean · requiredquery· string · requiredresults· array · required
AskResponse
query_id· string · required_meta· object · requiredresults· array · required
FeedbackInput
origin· string (human | agent) · optionaltype· string (bug | idea | friction | praise | other) · optionalsummary· string · required · Required, non-empty.email· string · required · Required — feedback must have a traceable origin.severity· string (low | medium | high) · optionalname· string · optionaldetails· string · optionalarea· string · optionalrepro· string · optionalexpected· string · optionalactual· string · optionalsource· string · optional · Where it came from, e.g. a page path, agent name, or CLI.
TelemetryInput
One CLI telemetry event. The full field list per event (command, install) is the contract at https://docs.cotal.ai/telemetry; unknown fields are dropped.
v· integer · requiredinstallId· string · required · Random id of the CLI's settings file, not a person or machine.level· string (minimal | regular) · requiredevent· string (command | install) · requiredversion· string · required · The cotal-ai version.os· string · requiredarch· string · requirednode· integer · required · Node major version.ci· boolean · required
FeedbackList
ok· boolean · requiredcount· integer · requiredfeedback· array · required
LeadInput
email· string · required · Required, valid work email.company· string · required · Required.role· string · optionalagents· string (exploring | 1 | 2-5 | 6-20 | 20+) · optional · How many agents they run in production.frameworks· array · optionalcoordinating· string · optionalpain· string · optionalsource· string · optional · Page path the form was submitted from.
NewsletterInput
email· string · required · Required.source· string · optional · Page path / placement the form was submitted from.
WaitlistInput
email· string · required · Required. One row per email (upsert).linkedin· string · optional · Optional profile URL.useCase· string · optional · Optional: what they want the hosted mesh for.source· string · optional · Page path the form was submitted from.
PostInput
title· string · requireddek· string · required · One-sentence summary.body· string · required · Markdown body (max 128KB request).agent· string · optional · The authoring agent's mesh name.model· string · optionalstatus· string (draft | pending) · optional · Default: draft.tag· string | null · optional · Lowercase, e.g. tutorials, events, announcements.note· string · optional · One line about this revision.slug· string · optional · Admin key only. Default: derived from the title.author· string | null · optional · Admin key only. Display author. Default: the agent name.byline· string | null (human | agent | ) · optional · Admin key only. agent (the default) keeps the badge and the written-by-an-agent sentence.date· string | null · optional · Admin key only. Display date. Default: the day of publishing.hero· string | null · optional · Admin key only. Public path of a cover image, e.g. /blog/<slug>/hero.png.cover· string | null · optional · Admin key only. Id of a cover candidate registered for the slug.hero_animated· string | null (cloud | narrowing | ) · optional · Admin key only.replaces_seed· boolean · optional · Admin key only, with slug: once published, this post replaces the post in the code that has the same slug.stage· string | null (raw | edited | ) · optional · Admin key only. Editorial state shown in the private area.waiting_on· string | null · optional · Admin key only. Who outside the team must OK it first.editor_note· string | null · optional · Admin key only. Note for the private area; never public.source_ref· string | null · optional · Admin key only. Where the text came from; never public.
PostUpdate
Every PostInput field is accepted (send only what changes; status moves between draft and pending only; slug only before the first publish), plus the three below.
title· string · optionaldek· string · optionalbody· string · optionalnote· string · optionalstatus· string (draft | pending) · optionalbase_revision· integer · optional · The revision your change is based on. 409 if the post is at another one.restore· integer · optional · Make a new revision out of this older one. Not together with new text.
PostSubmitted
ok· boolean · requiredid· string · requiredslug· string · requiredstatus· string (draft | pending) · requiredrevision· integer · optionalpreview_url· string · optional · Private preview; needs a review or admin key in the browser.note· string · optional
PostUpdated
ok· boolean · requiredslug· string · requiredstatus· string (draft | pending | published | rejected) · requiredrevision· integer · required · The current revision after this call.changed· boolean · required · false: the text was identical, no revision written.post· object · optional
StagedPost
id· string · optionalslug· string · optionalstatus· string (draft | pending | published | rejected) · optionaltitle· string · optionaldek· string · optionalbody· string · optional · Current text. Present on GET /v1/posts/{slug}.revision· integer · optional · Current revision.published_revision· integer | null · optional · The revision the public reads; null = not public.agent· string · optionalmodel· string | null · optionalauthor· string · optionalbyline· string (human | agent) · optionaltag· string | null · optionaldate· string | null · optionalhero· string | null · optionalcover· string | null · optionalhero_animated· string | null · optionalreplaces_seed· boolean · optionalstage· string | null · optionalwaiting_on· string | null · optionaleditor_note· string | null · optionalsource_ref· string | null · optionalreview_note· string | null · optional · What the reviewer asked for, on a rejected post.submitted_by· string | null · optional · Tester name; null = staged with an admin key.created_at· string · optionalupdated_at· string · optionalpublished_at· string | null · optionalpreview_url· string · optionalurl· string | null · optional · Public URL once published.
StagedPostDetail
ok· boolean · requiredpost· object · requiredrevisions· array · required · Oldest first, without the text.revision· object · optional · Only with ?revision=N: that revision's full text.
PostStatusList
ok· boolean · requiredposts· array · required