Skip to main content

Error Codes

All API errors return a JSON response with a detail field:

Status codes

Common errors and fixes

Authentication errors (401)

Fix: Use Authorization: Bearer sk_YOUR_KEY (include the Bearer prefix).
Fix: Check that your key is correct and hasn’t been revoked. Generate a new key from Settings > API Keys.

Validation errors (400)

Fix: Include a non-empty message in your request body.

Unsupported file type (415)

A legacy binary .doc upload returns the same 415:
Fix: Upload one of the supported formats — .pdf, .docx, .txt, .rtf, .md, .html, .htm. Convert legacy .doc files to .docx first. RTF is supported as an upload input only; it is not an export target. Catch 415 (Unsupported Media Type) separately from 400 when handling upload-validation failures.

Rate limit (429)

Fix: Upgrade your plan at Settings > Billing, or wait for your monthly reset. Honor the Retry-After header (seconds until the request can succeed) and branch on the 429 status and the X-Usage-Limit / X-Usage-Used / X-Usage-Remaining headers rather than the detail string (the wording may change). Check the usage object in chat responses to monitor remaining operations. A plain-text 429 with no Retry-After is an infrastructure surge response, not an application error; back off with jitter and retry (see Rate Limits).

Timeout (504)

Both the synchronous /v1/chat and the async /v1/chat/async endpoints apply a 30-minute wall-clock cap, but they surface the timeout differently: Synchronous /v1/chat returns an HTTP 504 with a plain detail string:
Async /v1/chat/async does not return a 504 on the poll — the job completes and the friendly summary below is persisted as the job’s AI response (read it from the job result):
Fix: Use the async endpoint (/v1/chat/async) for long operations — it streams intermediate progress events as the work runs and supports human-in-the-loop approval. Split large requests into smaller turns (one section per turn).

Request too large (413)

The 413 response covers two distinct cases — caller-too-large and document-too-large for the chosen export format — with a structured JSON detail body so clients can react appropriately. Caller payload exceeds the transport limit:
A much smaller ~32 MiB platform limit sits in front of the application. A body over that ceiling is rejected at the gateway with a generic error page (HTML), not this structured JSON body — so don’t try to parse it as JSON. Keep request bodies well under that limit; for large exports, switch to the upload-then-export pattern below.
Fix: For exports, switch to the upload-then-export pattern — see Large documents. For other endpoints, split the work into smaller requests. Export payload exceeds the format-specific cap:
Fix: Call POST /v1/documents/export/email-request instead — the file will be rendered in the background and emailed as a 7-day signed download link. See Email fallback for very large documents.

Validation errors (422)

Fix: format is now a strict enum on /v1/documents/export. Use one of "docx", "pdf", "html", "markdown", "txt". The value "doc" is accepted as a legacy alias and will be removed in a future release.
Fix: session_id may contain only letters, digits, and the characters _, -, and ., up to a maximum of 256 characters. Drop spaces, slashes, and other punctuation from the id you choose.

Not found (404)

Fix: Jobs are cleaned up 1 hour after completion. Check the job ID and timing. Use /v1/jobs to list active jobs.

Revert conflicts (409)

Fix: Wait for the in-flight job to finish (poll /v1/jobs/{job_id} or watch the SSE stream until you see final), or cancel it via POST /v1/jobs/{job_id}/cancel before retrying revert.

Revert target too old (422)

Fix: Per-message revert only works for chats started after the feature shipped. Older sessions remain readable but their messages don’t carry the marker the rewind needs. Start a new session for full revert support.