Docs·API reference
Errors
Every error has the same JSON shape. The status tells you whether to retry; the code tells you why.
The shape #
JSON
{
"error": {
"type": "invalid_request_error",
"code": "document_too_long",
"message": "document is 1,204,551 characters; the limit is 1,000,000",
"param": "document"
}
}| Field | Description |
|---|---|
type |
The class of error. One per HTTP status, listed below. |
code |
The exact reason. Use it in your code. |
message |
A sentence for people. It may change; do not parse it. |
param |
The request field at fault, when there is one. |
Every response, errors included, has an x-request-id header. Log it: it identifies the request.
All errors #
| Status | type |
code |
What to do | Retry? |
|---|---|---|---|---|
| 400 | invalid_request_error |
invalid_json, missing_document, missing_question, document_too_long, question_too_long, too_many_fields, invalid_fields, invalid_min_confidence, unsupported_file_type, file_too_large, invalid_file, invalid_date |
Fix the request. param names the field. |
No |
| 401 | authentication_error |
missing_api_key, invalid_api_key, revoked_api_key |
Send Authorization: Bearer <key> with an active key from the API keys page. |
No |
| 403 | permission_error |
account_disabled, access_not_active |
access_not_active: your access is not active yet. Request access, or open the activation link from the approval email. account_disabled: the account is disabled. |
No |
| 404 | not_found_error |
model_not_found, not_found |
Check the model id or the path. | No |
| 413 | invalid_request_error |
request_too_large |
Send a smaller body. Files are up to 10 MB. | No |
| 429 | rate_limit_error |
requests_per_minute, tokens_per_day |
Wait retry-after seconds. See rate limits. |
Yes, after retry-after |
| 503 | overloaded_error |
queue_full, queue_timeout |
We are busy. Wait retry-after seconds. |
Yes, after retry-after |
| 500 | api_error |
internal_error |
Something broke on our side. Try once more later, and log the x-request-id. |
Once, later |
Account and dashboard errors #
The website's own API, under /dashboard/api, uses the same shape. These codes concern access to the preview:
| Status | code |
Where | What it means |
|---|---|---|---|
| 403 | access_not_active |
/v1/*, creating API keys, the playground |
The account's access is not active yet. Access is by invitation during the preview: request access, then open the activation link we email you. |
| 400 | invalid_company, invalid_email, free_email, invalid_role |
The request access form | A field is not valid; param names it. free_email means a free mailbox such as Gmail: use your work email. |
| 409 | waitlist_closed |
The request access form | The request was already reviewed, so it can no longer be changed. |
| 403 | not_admin |
The admin pages | Only admins can review requests. |
Retries #
Retry only what can succeed on a second try:
- Retry 429, 503 and network errors (connection reset, timeout). Wait for
retry-afterwhen the response has it. - Never retry 400, 401, 403 or 404. The same request fails the same way.
- Back off. Without
retry-after, wait 0.5 s, then 1 s, then 2 s, with some random jitter, and stop after a few tries. - Check the daily budget. A 429
tokens_per_daylasts until 00:00 UTC; itsretry-aftersays how long that is. Retrying sooner will not help.
The Python and JavaScript SDKs do all of this for you: 2 retries by default, with backoff and jitter, honouring retry-after.
If you write your own client:
Python
import random, time, requests
def post_with_retries(url, body, key, tries=3):
for attempt in range(tries + 1):
try:
r = requests.post(url, json=body, headers={"Authorization": f"Bearer {key}"}, timeout=60)
except requests.ConnectionError:
if attempt == tries:
raise
time.sleep(0.5 * 2 ** attempt + random.random() * 0.25)
continue
if r.status_code in (429, 503) and attempt < tries:
wait = float(r.headers.get("retry-after", 0.5 * 2 ** attempt))
time.sleep(wait + random.random() * 0.25)
continue
return rThis example uses the requests package; the XERJ SDK itself needs no packages.
Errors you should design for #
document_too_long: the document has more than 1,000,000 characters. Send the part that can hold the answer. See long documents.tokens_per_day: the request would go over today's input tokens. It is refused before the document is read, so it uses no tokens.- A
noneanswer is not an error. It is a normal200response: the document does not answer the question above your bar.