Concepts
Error codes
HTTP error status codes, error response shape, and retry strategy
All errors return JSON; the error object has type and message, sometimes code/param.
Status codes
| Status | Example type | Meaning | Troubleshoot |
|---|---|---|---|
400 | invalid_request_error | malformed request / bad params | check body, required fields, model |
401 | authentication_error | API key missing or invalid | check Authorization: Bearer header |
402 | insufficient_quota | insufficient balance | top up, see Billing |
403 | permission_denied | no access to that model/action | check key permissions or model availability |
404 | not_found | model/resource doesn't exist | verify ID via GET /v1/models |
408 | request_timeout | request timed out | retry; use async for long jobs |
413 | invalid_request_error | request body too large | reduce tokens |
422 | invalid_request_error | param semantics unprocessable | check tools/response_format etc. |
429 | rate_limit_error | rate limit or quota hit | lower concurrency, see Retry-After, Rate limits |
500 | server_error | gateway/router error | platform auto-failovers; contact support if persistent |
502/503 | server_error | upstream unavailable | platform auto-switches upstream; retry shortly |
504 | server_error | gateway timed out waiting on upstream | retry |
Error response
{
"error": {
"type": "invalid_request_error",
"code": "model_not_found",
"param": "model",
"message": "model not found: foo-1"
}
}| Field | Notes |
|---|---|
error.type | error category (see table) |
error.code | specific code (optional) |
error.param | the offending param (optional) |
error.message | human-readable explanation |
Retry strategy
The platform already auto-failovers on 5xx / upstream timeouts, switching upstreams — no aggressive client retry needed. Clients should only do exponential backoff on 429 (rate limit) and the occasional 503.
import time
def call_with_retry(fn, tries=4):
for i in range(tries):
try:
return fn()
except RateLimitError:
time.sleep(2 ** i) # 1, 2, 4, 8s
raise