Skip to main content

Error envelope

Every endpoint fails in the same shape:

Validation errors

When a request body fails schema validation, the 422 validation_error carries one more field inside error: errors, an array with one entry per failing field. The example is a POST /v1/retrieve with no query and a limit of 500. message still describes only the first failure, formatted field: message, so a form can use errors to mark every bad field in one round trip.
The rejected value itself is never echoed back, so a 422 cannot leak what was submitted. errors is present only on schema-validation failures. Other codes, and the few validation_error responses raised by checks made after the body has parsed, carry code and message alone, so read errors when it is there and fall back to message.

Status and error codes

The codes you will actually see, by status: A handful of framework-level failures fall back to generic codes — bad_request, unauthorized, forbidden, not_found, method_not_allowed, conflict, rate_limited, internal_error, service_unavailable. These come from the web framework rather than from a route, so in practice you see them only for a request that reached no endpoint: a misspelled path is 404 not_found, the wrong verb on a real path is 405 method_not_allowed. No documented endpoint returns unauthorized or forbidden — every authentication and authorization refusal carries one of the specific codes above (missing_auth, invalid_token, invalid_api_key, key_expired, no_api_key, space_access_denied, and so on). Branch on the specific codes and treat the generic ones as “my request did not reach the API I meant”. This table is the canonical list. Where another page in these docs shows an error, it shows a code from here; if you find one that does not, the other page is wrong and we want to hear about it.

Endpoint-specific codes

Some endpoints add further codes. See Documents, Webhooks, Organization, Context Receipts, and Billing.

Common mistakes

Retrying

Retry 429, 500 and 503 with backoff. Never retry a 4xx other than 429: the request will fail identically every time. And never blindly retry a write on a 5xx — a 5xx means the request may well have executed, so a re-sent POST /v1/record stores the memory twice.

What the SDKs already retry

Both SDKs retry on your behalf, but not on every call, and the two draw the line differently. Check this table before adding a loop of your own. Three things explain the whole table:
  • A 429 is always retried, writes included. The limiter refuses the request before the route runs, so nothing executed and a re-send cannot double-write. credits_exhausted is the one exception — it rides a 429 but is a balance, not a window, so no backoff can clear it and neither SDK retries it.
  • A 5xx is only retried where a replay is safe. The Python client decides by HTTP method: GET, HEAD, OPTIONS, PUT and DELETE are retried, and every POST is not. retrieve and reason are POST requests, so Python does not retry them on a 5xx even though they are reads — the TypeScript client marks each create explicitly instead and so does retry retrieve. If you need a 5xx retried on retrieve in Python, wrap that one call.
  • A multipart upload is never retried. The body is built from your own file objects and they are not rewound between attempts, so a replay would upload a truncated file. Uploads surface the error instead.

A loop that is safe to put above them

Only the first table row leaves a gap worth closing. Retry AnonaError on the statuses the SDK skipped, honour the wait the server named, and let everything else through untouched.
Note what both versions do not do: they never catch a bare Exception, and they never retry a 4xx. A loop that catches everything retries validation_error and space_not_found three times before reporting the same failure three times more slowly. Tuning the SDK’s own retrying is usually enough, and it is one constructor argument: max_retries / maxRetries (default 2, 0 turns retrying off), and in Python retry_max_wait (default 60.0 seconds) caps how long a single hinted wait may park the call. See the Python SDK and TypeScript SDK pages.

Handling errors in the SDKs

The TypeScript class carries the same information under camelCase names (statusCode, requestId), plus retryAfter on a 429. The TypeScript client raises the same error with statusCode, code, requestId, detail and retryAfter. Both SDKs already retry 429 on every call and a 5xx on the calls where a replay is safe — see What the SDKs already retry before adding a second loop, because for most calls there is nothing left to add.

Next steps

API overview

Every endpoint in one table.

Support

Contact us with a request_id.