Platform
Errors
Errors follow the shape of whichever protocol you called, so your existing SDK error handling works unchanged.
Shapes
{
"error": {
"message": "Insufficient wallet balance",
"type": "invalid_request_error",
"code": "insufficient_balance"
}
}Status codes
| Field | Type | Description |
|---|---|---|
400 | invalid_request_error | The body failed validation. The message names the offending field. |
401 | authentication_error | Missing, malformed, or revoked key — or the account is disabled. |
402 | insufficient_balance | The wallet cannot cover the reservation. Top up and retry; no model was called. |
403 | model_not_allowed | The key is scoped to a model list that excludes this model. |
404 | model_not_found | No such model, or it is disabled. Check /v1/models. |
413 | prompt_too_large | The prompt exceeded a size ceiling. See Limits. |
429 | rate_limit_error | A rate limit, the key's monthly budget, or the concurrency ceiling. Back off and retry. |
502 | upstream_error | The upstream provider rejected the request. Usually not retryable as-is. |
503 | no_capacity | No capacity for that model right now. Retryable; honour retry-after. |
504 | upstream_timeout | The upstream did not respond in time. The hold was released; retrying is safe. |
Which errors are worth retrying
429, 503, and 504 are transient — retry with exponential backoff. 400, 401, 403, 404, and 413 will fail identically until you change something, so retrying them only burns rate limit. 402 clears as soon as you top up.
Request ids
Every response carries x-request-id. Quote it when contacting support and we can pull the exact request, including the upstream detail that was not sent to you.