Error types
Transient vs permanent errors
Transient errors are temporary and safe to retry:429 RATE_LIMITED: wait and retry (see rate limiting)500 INTERNAL_ERROR: server-side failure; retry with backoff503: service degraded; retry with backoff
400 INVALID_REQUEST: fix the request (missing fields, invalid file format, file too large)401 UNAUTHORIZED: provide a valid API key403 ACCOUNT_TERMINATED: contact support; the account cannot be recovered programmatically
Retrying submissions
For5xx errors, use exponential backoff to avoid overwhelming the API during an outage.
Handling failed jobs
A job withstatus: "failed" means processing encountered an unrecoverable error after the job was accepted. is_prohibited will be null.
error_code is a diagnostic hint, present only on some failures. Treat it as optional and never branch on it being there. Six values are worth handling:
PROVIDER_RATE_LIMITED: the AI provider rate-limited the request and the limit did not clear within the retry window. Resubmit after a short delay.PROVIDER_UNAVAILABLE: the AI provider returned server errors for every attempt. Resubmit after a short delay.PROVIDER_TIMEOUT: the AI provider did not answer within the time allowed, on every attempt. Resubmit after a short delay.MODEL_UNAVAILABLE: the configured model is not served for this input. Resubmit after a short delay.MODEL_REFUSED: the moderation service refused this exact input. An identical resubmission returns the same result, so change the input or handle the job as undecidable.MEDIA_UNREACHABLE: the media URL submitted with the job did not resolve when fetched (for example HTTP 404, or an expired signed link). Resubmitting the same URL fails the same way. Fix the URL, then resubmit.
job_id cannot be retried. If the
job carried a webhook_url, the same error_code arrives on the failed webhook.
Rate limit recovery
When you receive a429 RATE_LIMITED response, the error body includes details: