API reference
Errors and error codes
The error envelope, every error code the chat, widget, workflow and ingest endpoints return, its HTTP status and what to do about it.
Reference3 min readUpdated 23 October 2026
Errors come in one of two ways. Before the stream starts, the API answers with an HTTP error status and a JSON envelope. After the stream has started (the status is already 200), a failure arrives as a final error event with the same fields. Handle both.
HTTP/1.1 402 Payment RequiredX-Request-Id: 284662c8227a417d9f66755385919e0e{ "error": { "code": "OUT_OF_CREDITS", "message": "You're out of credits. Buy credits to continue.", "request_id": "284662c8227a417d9f66755385919e0e", "balance": 0, "buy_url": "/settings?tab=billing" }}code is stable and meant for your code; message is for people and may change. Some errors add fields: OUT_OF_CREDITS adds balance and buy_url, VALIDATION_ERROR adds details. Always log request_id: it finds the request in our logs and your trace.
Chat: before the stream (HTTP status)
| Status | Code | What to do |
|---|---|---|
| 400 | MISSING_AGENT_ID | Send X-Agent-Id or agent_id in the body |
| 400 | MISSING_MESSAGE | Send a non-empty message |
| 401 | MISSING_API_KEY | Send your secret key in X-Api-Key |
| 401 | INVALID_API_KEY | Check the key is your sk-so- key, complete, with no spaces |
| 402 | OUT_OF_CREDITS | Buy credits, or turn on auto top-up. See Running out of credits |
| 403 | AGENT_INACTIVE | The agent is paused. Set it to Active on its Settings tab |
| 404 | AGENT_NOT_FOUND | The agent id is wrong or belongs to another account |
| 422 | VALIDATION_ERROR | The body doesn't match the schema (for example a message over 32,000 characters); see details |
| 429 | RATE_LIMIT_EXCEEDED | Wait X-RateLimit-Reset seconds, then retry. See Rate limits |
| 500 | INTERNAL_ERROR | Retry once; if it persists, send support the request_id |
Chat: inside the stream (error event)
| Code | Meaning | What to do |
|---|---|---|
CONVERSATION_NOT_FOUND | The conversation id is unknown or belongs to another agent | Start a new conversation |
TIMEOUT | The reply took longer than 120 seconds | Retry; shorten tool chains or lower max tokens |
LLM_AUTH_ERROR | The model provider rejected the agent's key | Fix the key on the agent or LLM keys page |
LLM_RATE_LIMITED | Your model provider rate-limited the key | Back off; raise your limits with the provider |
LLM_UNAVAILABLE | The provider was down or overloaded (503/529) or unreachable | Retry after a short wait |
LLM_ERROR | Any other provider error | Check the trace for the provider's message |
INTERNAL_ERROR | Anything else, including an agent with no provider key | Check the agent has a key; send support the request_id |
Provider errors only ever arrive as error events inside a 200 response, never as an HTTP status. A reply that fails after its credit was spent is refunded.
Widget
| Status | Code | Meaning |
|---|---|---|
| 401 | SECRET_KEY_NOT_ALLOWED | A secret key was used on the widget. Use the agent's pk-so- key |
| 401 | MISSING_WIDGET_KEY | No data-widget-key on the script |
| 401 | INVALID_WIDGET_KEY | The key is malformed, unknown or was rotated |
| 403 | WIDGET_KEY_SCOPE | The key belongs to a different agent than data-agent-id |
| 403 | ORIGIN_NOT_ALLOWED | The website isn't in the key's Allowed websites |
| 403 | AGENT_INACTIVE | The agent is paused |
| 404 | AGENT_NOT_FOUND, CONVERSATION_NOT_FOUND | Unknown agent or conversation |
| 429 | RATE_LIMIT_EXCEEDED | 120 a minute per key or 12 per visitor exceeded |
Workflows
| Status | Code | Meaning |
|---|---|---|
| 400 | MISSING_RUN, RUN_MODE_MISMATCH, INVALID_INPUT | The body is incomplete, or the input doesn't match the Start step's fields |
| 402 | OUT_OF_CREDITS | Not enough credits to start the run |
| 403 | TEST_RUN_NOT_ALLOWED | Test runs can only be started from the designer |
| 404 | WORKFLOW_NOT_FOUND, RUN_NOT_FOUND | Wrong id, or not yours |
| 409 | WORKFLOW_NOT_PUBLISHED, RUN_ALREADY_STARTED | Publish the workflow first; a run can only start once |
| 429 | RATE_LIMIT_EXCEEDED | More than 30 runs a minute. Sends Retry-After |
| 429 | TOO_MANY_RUNNING | 5 runs already in progress. Sends Retry-After: 10 |
Knowledge ingestion
| Status | Code | Meaning |
|---|---|---|
| 413 | FILE_TOO_LARGE | The file is over 50 MB |
| 415 | UNSUPPORTED_MEDIA_TYPE | Not a PDF or plain-text file |
| 422 | EXTRACTION_FAILED, VALIDATION_ERROR | No readable text (for example a scanned PDF), or a bad field |
| 502 | EMBEDDING_FAILED, CRAWL_FAILED | The embedding or crawling service failed; credits for failed pages are refunded |
| 503 | CRAWLER_DISABLED | Website crawling is unavailable right now |
| 500 | INGEST_FAILED | Anything else |
Traces and analytics
TRACE_NOT_FOUND (404), INVALID_RANGE (400) and TRACE_BACKEND_UNAVAILABLE (503).
Codes that don't exist
You may see INSUFFICIENT_CREDITS or RATE_LIMITED in older examples elsewhere. The API doesn't send them: use OUT_OF_CREDITS and RATE_LIMIT_EXCEEDED.
Still stuck?
Email us with what you tried and any request id. A person replies.