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

CodeHTTPNotes
ERR_INVALID_REQUEST400Malformed body or parameters. details.errors lists the field-level validation problems.
ERR_CONTENT_POLICY400Reserved. 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_INVALID401Reserved. Live authentication failures use the {"detail"} shape below instead of the envelope.
ERR_INSUFFICIENT_BALANCE402Wallet 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_FOUND404The requested model is not available to your account.
ERR_NOT_FOUND404The creation id doesn't exist or doesn't belong to your account — both cases return the same error.
ERR_RATE_LIMIT429Per-key request rate or the polling minimum interval was exceeded. Honor Retry-After.
ERR_QUOTA_EXCEEDED429A concurrency or capacity limit was hit — details.scope / details.reason identifies which. Honor Retry-After.
ERR_INTERNAL500Unexpected server error.
ERR_GENERATION_FAILED502Generation failed after acceptance. The charge has already been refunded in full — safe to retry.
ERR_PROVIDER_UNAVAILABLE503The 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.

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 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:

error values on a failed creation
"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.