Errors
Use the HTTP status first to classify a failure and, when present, the code field to choose the specific action. Do not program against the error text: it is written in English, can change and, for some internal failures, may contain technical details.
Canonical format
Section titled “Canonical format”The Agents, Knowledge Bases, Conversations, Lists and Tags endpoints use this envelope:
{ "error": "Invalid or missing API token", "code": "unauthorized"}| Field | Type | How to use it |
|---|---|---|
error | string | English diagnostic message. Do not use it as an identifier or show it directly to the end customer. |
code | string | Machine-readable identifier. Handle known codes and keep a fallback for new or missing values. |
Current canonical codes
Section titled “Current canonical codes”code | Typical status | What it means | Recommended action |
|---|---|---|---|
invalid_request | 400 | Invalid JSON, parameter, field or UUID. | Fix the request; retrying the same content does not help. |
unauthorized | 401 | Missing, invalid or revoked token. | Stop the call and replace the token. See Authentication. |
forbidden | 403 | The target is outside the organization or is not a compatible API inbox. | Review the resource and configuration; do not retry automatically. |
not_found | 404 | Resource or route not found, including a resource from another organization. | Confirm the ID and path. An unsupported method also falls through to 404, not 405. |
conflict | 409 | Current state blocks the operation, such as preserved unsubscribe consent, a duplicate tag or a non-editable knowledge-base item. | Read the current state and reconcile before trying another action. |
internal_error | 500 | Unexpected application, database or configuration failure. | Treat the outcome as unknown; reconcile and only then retry with backoff. |
service_unavailable | 503 | A knowledge-base search dependency is unavailable. | Retry with exponential backoff and jitter; do not interpret the response as an empty knowledge base. |
HTTP statuses emitted today
Section titled “HTTP statuses emitted today”| Status | Current use |
|---|---|
200 OK | Read, update, completed action or synchronous Chat. |
201 Created | Created knowledge-base item or created/confirmed list membership. |
202 Accepted | Chat accepted for asynchronous processing or placed in the debounce queue. The response does not prove the run finished. |
204 No Content | Deleted knowledge-base item; do not try to decode JSON. |
400 Bad Request | Invalid input. |
401 Unauthorized | Missing or invalid token. |
403 Forbidden | Forbidden, incompatible or inactive Chat target. |
404 Not Found | Resource, route, or method-and-route combination not found. |
409 Conflict | Current state is incompatible with the operation. |
500 Internal Server Error | Unexpected failure or synchronous Chat pipeline failure. |
503 Service Unavailable | Temporarily unavailable dependency or persistence failure classified by the pipeline. |
The API does not currently implement public 408 Request Timeout or 429 Too Many Requests responses. Synchronous Chat has no fixed product HTTP deadline: a model timeout or another pipeline failure currently arrives as 500, while a proxy or client may close the connection without receiving JSON. See the full contract in Chat.
Current Chat exceptions
Section titled “Current Chat exceptions”Chat shares part of the runtime used by other channels and does not yet follow a closed code catalog. Depending on the phase, you may receive:
- specific lowercase codes such as
agent_not_foundandtrigger_inactive; - legacy uppercase codes such as
AGENT_NOT_FOUND,AGENT_ARCHIVEDandAGENT_INACTIVE; - the technical failure class, such as
TimeoutError, in a500; - on one rare defensive path, a
500witherrorbut nocode.
This divergence is tracked as BUG-API-038; the promised 408 and incomplete Swagger catalog also extend BUG-API-022. Until the product unifies the contract, use the status as a fallback and record unknown codes for observability without failing to decode them.
Handling strategy
Section titled “Handling strategy”- Read the body as text and then try to decode JSON; proxies may also return HTML or an empty body.
- For a
2xxresponse, handle the endpoint-specific status — especially202and204. - For
400,401,403,404or409, fix the input, credential, target or state before retrying. - For
500or503, assume a write may have happened partially. Query the resource or history before retrying. - When retrying is safe, use exponential backoff with jitter and a maximum attempt count. There is no guaranteed
Retry-Afterheader today.
const response = await fetch(url, options);const raw = await response.text();
let body = null;try { body = raw ? JSON.parse(raw) : null;} catch { // Non-JSON body returned by a proxy or the platform.}
if (!response.ok) { const code = typeof body?.code === "string" ? body.code : null;
if (code === "unauthorized") rotateOrReplaceToken(); else if (response.status >= 500) scheduleReconciliationAndRetry(); else handlePermanentFailure(response.status, code);}