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": {
"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 | Reserved. Prompts are screened by the model's safety filter at generation time; a declined prompt fails the creation (fully refunded) rather than returning this error. |
| 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. |
| ERR_PROVIDER_UNAVAILABLE | 503 | The image provider is temporarily unavailable (an upstream outage while starting the job). The charge is refunded in full and the job never started. Honor Retry-After and retry shortly. |
Authentication errors (401 / 403)
Authentication failures are the one exception to the envelope: they return a plain {"detail": "..."} body. See Authentication.
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 and 503 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 (a job that ran and failed) and a 503 ERR_PROVIDER_UNAVAILABLE (the provider was down before the job started) both mean the up-front charge has already been refunded — you can safely submit the request again. For the 503, honor the Retry-After interval first. Use an idempotency key on retries so a request that actually succeeded is never charged twice.
Failed creations
When a creation fails after the 202 acceptance, polling GET /creations/{id} returns status: "failed" with an error string naming the failure reason, and the charge is refunded automatically. error is always one of:
"Prompt rejected by the safety filter. Make the scene more specific — abstract or generic prompts are declined more often."
"Provider returned no image."
"Generation timed out."
"Generation failed."A safety-filter rejection is not retryable as-is — revise the prompt. The other three are transient: submit the request again.