Every error is JSON with a stable code, a message for people, and a requestId to quote.
The error envelope
{
"requestId": "…",
"error": {
"code": "INVALID_PRESENTATION_ID",
"message": "presentationId query parameter is required.",
"hint": "…"
}
}
error.codeis upper snake case and stable; match on it.error.messageis for people and can change.error.hint, when there is one, says where to look next.requestIdis what to quote in a bug report.
Only error, with its code and message, is on every error; requestId
and hint are present when the endpoint has them. The OAuth endpoints answer
with RFC 6749 bodies instead, {"error": "…", "error_description": "…"}.
Common codes
| Status | Code | Meaning |
|---|---|---|
401 | UNAUTHORIZED, INVALID_ACCESS_TOKEN | The credential is missing, expired, or revoked. See Authentication. |
404 | NOT_FOUND | No endpoint at that /api path. The body's hint names the OpenAPI document and the MCP server, and docs names the API overview. |
404 | PRESENTATION_NOT_FOUND | No presentation at that address, or one you cannot read. |
405 | METHOD_NOT_ALLOWED | The endpoint exists, but not for that HTTP method. |
422 | IDEMPOTENCY_KEY_REUSED | The same Idempotency-Key with a different body. |
429 | CONTEXT_RATE_LIMITED | The per-IP window on /api/presentations/context. Wait Retry-After seconds. |
The live creation endpoints under /v1/presentations add their own. In every
case nothing was written.
| Status | Code | Meaning |
|---|---|---|
400 | LIVE_APPEND_ONLY | An append removed, reordered, or inserted a slide before one already sent. The message names the first slide that moved. |
404 | NO_OPEN_CREATION | Nothing is open under that id. A finalized presentation answers this. |
409 | LIVE_TARGET_CHANGED | An append sent a slug, handle, org, or visibility different from the one the creation started with. Leave them out and the originals are used. |
409 | LIVE_REVISION_CONFLICT | The baseRevision you sent is behind the current live.revision. Read the presentation, then append after what is there. |
409 | LIVE_APPEND_IN_PROGRESS | Another append or narration upload was still being written after 20 seconds. Try again. |
409 | CREATION_SUPERSEDED | Another publish of the same presentation replaced the open creation. |
Rate limits
GET and POST /api/presentations/context are limited per IP: 60 requests
per 10 minutes without a credential, 300 with one. Every response from the
endpoint carries RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset
(seconds) and RateLimit-Policy (60;w=600 without a credential,
300;w=600 with one). A 429 adds Retry-After. In the batch form each item
costs one slot, and items past the window come back as CONTEXT_RATE_LIMITED
rows rather than failing the request.
The documentation MCP server, POST /docs/mcp, allows 120 requests per 10
minutes per IP.
Publishing endpoints have no request window.
Back to the API overview. For the tool-level view of the same API, see the MCP servers.