Errors
One shape for every failure.
On failure the HTTP status is non-2xx and the body contains a single error object:
json
{
"error": {
"message": "Insufficient credits: this request needs 60 credits. Top up and try again.",
"type": "insufficient_quota",
"param": null,
"code": "insufficient_credits"
}
}Fields
| Field | Description |
|---|---|
| message | Human readable English. Do not branch on it — wording changes |
| type | Broad category, see below |
| code | Specific reason. Branch on this |
| param | Offending parameter name, or null when not attributable |
Common codes
| HTTP | code | Meaning |
|---|---|---|
| 401 | missing_api_key | No Authorization header, or not in Bearer sk-xxx form |
| 401 | invalid_api_key | Unknown, disabled or deleted key — deliberately indistinguishable |
| 400 | invalid_request | Bad parameters; read message. Empty prompt, image mode with no image, etc. |
| 402 | insufficient_credits | Out of credits. Top up, and check /v1/credits before retrying |
| 429 | rate_limit_exceeded | Too many calls. Back off and retry |
| 429 | concurrency_limit_reached | Concurrency or daily quota reached. Retry later |
| 404 | not_found | Task does not exist, or does not belong to this account |
| 502 | generation_failed | Every image failed during a synchronous call. Credits already refunded |
| 504 | generation_timeout | Synchronous call timed out. The task keeps running and credits are not refunded — fetch it from /v1/tasks/{id} using the id in the message |
| 500 | internal_error | Server side. Retryable; contact us if it persists |
An asynchronous job that fails after being accepted does not use this shape: the call is 200, the task object carries status failed, and the reason sits in error. Only synchronous image calls surface a failure as 502.

