PineRouterDocs
GuidesModelsAPI referenceApps

Errors

Every status code the API returns, the two body shapes, what to do and when to retry.

Every error has an HTTP status and a JSON body. The message ends with a request id, for example (request id: 202611020537...). Keep it: support can find your request with it.

Body shapes

/v1/chat/completions, /v1/responses, /v1/models, /v1/images/*, /v1/videos/*, /v1/audio/* and /v1/embeddings answer in OpenAI's shape. This is a real answer to a request with a wrong key:

{"error": {"code": "", "message": "Invalid token (request id: 202611020537046636626168268d9d6vfJBhWIJ)", "type": "api_error"}}
FieldMeaning
error.messageWhat went wrong, with the request id
error.typeFor example api_error or invalid_request_error
error.codeA short code such as insufficient_user_quota or model_not_found; often empty
error.paramPresent on some errors; usually empty

Errors from the model on /v1/messages use Anthropic's shape:

{"type": "error", "error": {"type": "api_error", "message": "... (request id: ...)"}}

Errors found before the request reaches the model (wrong key, rate limit, a model the key may not use) come back in the OpenAI shape shown in the first tab. Read both.

POST /v1/jobs and GET /v1/jobs/{id} answer with {code, msg, data}. code repeats the HTTP status:

{"code": 404, "msg": "Task not found", "data": null}

Two cases come back in the OpenAI shape instead, because they are answered before the job is read: a missing or wrong key (401) and the rate limit (429).

A job that started and then failed is not an HTTP error. GET /v1/jobs/{id} answers 200 with data.status set to failed and the reason in data.error. A failed job costs nothing.

Status codes

StatusMeaningWhat to doRetry?
400The request is invalid: a missing field, a wrong value, a field the model does not take, or a refusal by the content rulesFix the request using the model's fields on ModelsNo. A content refusal is final; do not reword around it
401No key, a wrong key, or a key that is turned off or expiredCheck the Authorization: Bearer sk-... header and the key in API keysNo
403Balance too low (insufficient_user_quota), the key may not use this model, or your IP is not on the key's allowlistTop up in Wallet, or change the key's model list or IP allowlistNo, not until you fix the cause
404Wrong path, or no job or video with this id on your accountCheck the URL and the idNo
413The request body is too large (over 128 MB)Send files as https:// links instead of inline dataNo
429Rate limit: 120 requests a minute, 60 of them successful. On jobs it can also mean the model is at capacityWait for the Retry-After header (seconds), then retry. See Rate limitsYes, after the wait
500An error on our side or the model'sRetry with backoffYes, up to 3 times
502The model's server sent a bad or empty answerRetry with backoffYes, up to 3 times
503We are briefly overloaded, or no server can take this model right now (model_not_found)Check the model id on Models; then retry with backoffYes, up to 3 times
504The model's server or a proxy on the way timed outRetry with backoffYes, up to 3 times

The model's own servers can return other statuses; they are passed to you as they come.

Timeouts

  • A text call with "stream": true is closed if no data arrives for 5 minutes.
  • Other calls wait until the model answers. POST /v1/images/generations waits for the image, which can take a minute or more, so give your HTTP client a long timeout (several minutes).
  • For anything long, prefer Jobs: the call returns a job id at once; you poll or get a webhook.

If your client times out on a POST /v1/jobs, the job may still have started. Check Task logs in Usage logs before you send it again. There are no idempotency keys yet, so a second request is a second job, charged again.

Retry rules

  • Retry only 429, 500, 502, 503 and 504.
  • Wait Retry-After seconds when the header is present. Otherwise back off: 2, 4, then 8 seconds, plus a little random jitter. Stop after 3 tries.
  • Never resend a job that is still running: poll GET /v1/jobs/{id}.
  • Do not retry 400, 401, 403 or 413. They fail the same way until you change the request, the key or the balance. Repeated content refusals can disable the account.

Code for backoff: Rate limits.

Errors during a stream

Once a stream has started, the status is already 200. An error then arrives as a last event in the stream. See Streaming.