Skip to main content
There are two places to handle failure: the HTTP response when submitting a request, and the status of an asynchronous job after it has been accepted. For an accepted job, failures arrive through GET /v1/jobs/{id}: status becomes failed or policy_blocked, result remains null, and error.code provides a safe classification. Stop polling at either terminal state. The HTTP error shapes below apply when a request itself is rejected.

Parse the HTTP status and body

Some handlers return a simple error:
Others return structured account or validation information with fields such as code, message, user_message, cta, and next_action. Keep the status code and structured fields. For a readable message, prefer user_message or message, then error; do not assume every endpoint uses the same shape. If cta is true, surface the relevant account action in your application. Repeating the same request will not solve a missing plan, permission, or credit balance.

Handle a failed job

Stop polling on failed or policy_blocked. When present, failure_code gives a broad category: Save the job ID and fail_reason for support and for your own logs. These fields can be absent, so fall back to the status and the message shown in Studio.

Retry reads carefully; reconcile writes first

Use bounded retries with backoff for temporary polling failures. Keep job IDs when a client deadline expires. Avoid an endless poll loop and stop on terminal states. Do not blindly retry a generation, edit, upscale, or video POST after a network timeout: the operation may have been created even if its response was lost. Check recent images or the parent’s versions and reuse the existing job when found. There is no documented idempotency-key contract in this reference. For support, send the endpoint, HTTP status, approximate UTC time, and image or version ID to [email protected]. Redact API keys and Authorization headers.