Errors
All API errors (except authentication — see below) share a single envelope: an error object with a stable code, a human-readable message, and machine-readable details. Branch on code, not on the message text.
error envelope
{
"error": {
"code": "ERR_INVALID_REQUEST",
"message": "Invalid request body",
"details": { "errors": [ /* field-level validation problems */ ] }
}
}Error codes
| Code | HTTP | Notes |
|---|---|---|
| ERR_INVALID_REQUEST | 400 | Malformed body or parameters. details.errors lists the field-level validation problems. |
| ERR_CONTENT_POLICY | 400 | The request was rejected by content policy. |
| ERR_API_KEY_INVALID | 401 | Reserved. Live authentication failures use the {"detail"} shape below instead of the envelope. |
| ERR_INSUFFICIENT_BALANCE | 402 | Wallet can't cover the request (details include required — the required USD amount — and a top-up URL), or a per-key monthly budget was exceeded (details.reason = monthly_budget_exceeded with the cap). |
| ERR_MODEL_NOT_FOUND | 404 | The requested model is not available to your account. |
| ERR_NOT_FOUND | 404 | The creation id doesn't exist or doesn't belong to your account — both cases return the same error. |
| ERR_RATE_LIMIT | 429 | Per-key request rate or the polling minimum interval was exceeded. Honor Retry-After. |
| ERR_QUOTA_EXCEEDED | 429 | A concurrency or capacity limit was hit — details.scope / details.reason identifies which. Honor Retry-After. |
| ERR_INTERNAL | 500 | Unexpected server error. |
| ERR_GENERATION_FAILED | 502 | Generation failed after acceptance. The charge has already been refunded in full — safe to retry. |
Authentication errors (401 / 403)
Authentication failures are the one exception to the envelope: they return a plain {"detail": "..."} body. See Authentication.
401 / 403 responses
HTTP/1.1 401 Unauthorized
{"detail": "authentication_required"}
HTTP/1.1 401 Unauthorized
{"detail": "api_key_invalid"}
HTTP/1.1 403 Forbidden
{"detail": "account_disabled"}Retry-After
Every 429 response includes a Retry-After header (in seconds). Back off for at least that long before retrying — see Rate limits.
Retryability & refunds
A 502 ERR_GENERATION_FAILED means the up-front charge has already been refunded — you can safely submit the request again. Use an idempotency key on retries so a request that actually succeeded is never charged twice.