Errors
What the API answers when a request fails, what each status and code means, and what to do next. Every other page links here.
Error Formats
The endpoints that follow the OpenAI API (/v1/chat/completions, /v1/responses, /v1/embeddings, /v1/audio/transcriptions, /v1/conversations) answer in the OpenAI error envelope, so an SDK surfaces error.message and error.code as usual:
{
"error": {
"message": "Invalid API key",
"type": "authentication_error",
"param": null,
"code": "invalid_api_key"
}
}
The other endpoints (agents, schemas, extractions, prompts, providers, knowledge bases and so on) answer with a problem document. Branch on errorCode, which is stable; detail is prose that can be reworded:
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "…",
"timestamp": "2026-10-22T09:41:07.113Z",
"errorCode": "SCHEMA_NOT_FOUND"
}
Two answers come from the security layer in front of every /v1 endpoint and have neither shape: a request with no Authorization header gets a bare 401 with no body, and a rejected surface assertion gets a flat {"error": "<code>", "message": "…"}.
Statuses
| Status | Means | What to do |
|---|---|---|
400 | The request is malformed or names something that does not exist or is not allowed: a bad body, an unknown model, an invalid policy or continuation | Read message or detail; the request will not succeed unchanged |
401 | No key, or the key is rejected | See Authentication |
402 | Usage is used up with no extra usage available, or the plan does not include the feature | See Usage and plan |
403 | The key's role or your role does not allow this action | Use a key with a higher role, or ask an admin; see API Keys |
404 | The resource does not exist, or you may not address it | Check the id or name, and that the key belongs to the organization that owns it |
406 | The Accept header rules out JSON | Send Accept: application/json or none |
409 | The request conflicts with the current state, for example a name that is taken or an agent with no published version | Change the name, or publish a version, then retry |
410 | A file you attached has expired | Upload the file again |
413 | A JSON body over 64 MB | Send less per request; file uploads have their own limits on Files |
429 | A limit was reached. There are three different limits | See 429: which limit |
502 | The model provider failed | Retry with a short back-off |
Authentication
A rejected key gets 401 with a code:
code | Meaning |
|---|---|
invalid_api_key | The key is malformed or does not exist, for example because it was deleted |
key_disabled | The key was disabled on the API keys page |
key_expired | The key is past its expiration date |
no_organization | The key is not linked to an organization; create a new key |
forbidden (403) | A valid key whose role does not allow this action |
Create a new key, or enable the disabled one, on the API keys page. A request with no Authorization header at all gets a bare 401.
429: Which Limit
429 is three different limits. Read error.code and the headers to tell them apart.
| Limit | code | What to do |
|---|---|---|
| The key's rate limit: 50,000 requests per key | code rate_limited | The key stays rejected until it has gone 24 hours without an accepted request, and there is no Retry-After. Do not retry in a loop; spread the load over more keys and alert on repeats |
| The key's usage limit | code usage_exceeded | Raise the limit, or use another key |
| Too many concurrent calls | type rate_limit_error, with a Retry-After header | Wait for the seconds in Retry-After, then retry |
| Too many turns from one end user of an embedded agent | status only, on POST /v1/responses | Slow the turns down and retry |
Usage and Plan
402 is a refusal before any work started, so nothing was spent or queued.
| Case | Answer |
|---|---|
| Usage is used up and extra usage is off | 402, type billing_error. An admin can turn on extra usage |
| An extraction batch needs more usage than is left | 402; nothing was queued |
| A knowledge base search on the built-in embedding models when usage is used up | 402 |
A provider/model call or a new provider on a plan without BYOK | 402; creating a provider answers with errorCode LIMIT_EXCEEDED_BYOK |
A call that runs on your own provider can also fail because your account with that provider has no credits left or has reached its spend limit. The gateway answers 400 with type billing_error and code provider_quota_exhausted; the message says which of the two it is. Retrying does not help until you add credits or raise the limit with the provider. A stream that has started ends with an error event carrying the same type and code, and a stored or background response is failed with the same code.
Agents
| Status and code | When | What to do |
|---|---|---|
400 | A malformed model reference, a #{model} override the version does not list, a bad file reference or a malformed Backbone-Turn-Id header | Fix the request |
400 invalid_hitl_policy | The stored approval policy fails validation, so every run of that version is refused | Save a valid policy as a new version |
400 invalid_approval_decision, unknown_approval_id, approval_hmac_mismatch, incomplete_tool_outputs | A bad approval decision or an unanswered tool call | Answer every pending call, echo the hmac unchanged |
400 invalid_conversation_mode | A backbone:mode item with a mode that does not exist | Send plan, ask or auto |
400 conversation_in_plan_mode | An approve that Plan mode refuses | Leave Plan mode or reject the call |
400 conversation_mode_not_offered | A request runs under a mode the agent does not offer | Pick an offered mode or send "mode": null |
404 | An unknown agent, or one the caller may not address | Check the name, label and key |
409 agent_not_published | The agent has no published version | Publish one with POST /v1/agents/{agentId}/versions |
409 approval_already_decided | The same decision sent again after the paused response was continued | Fetch the continuation the message names; do not send the decision again |
410 file_expired | An attached file's lifetime ran out | Upload it again |
Gateway
| Status and code | When |
|---|---|
400 model_not_supported | The provider prefix serves no embeddings |
400 too_many_inputs, empty_input, input_too_large | An embeddings request with more than 2,048 inputs, an empty input, or more than 1 MiB |
400 upstream_error | The provider refused the request, for example an over-long input or a bad dimensions |
404 | No provider configured for the prefix |
413 request_too_large | A JSON body over 64 MB |
502 upstream_error | The provider failed |
400 audio_duration_unknown | The built-in whisper-1 could not read the audio's duration; see Audio Transcription |