Skip to main content
This page covers how to handle errors at each stage of a moderation request: submission, processing, and result retrieval.

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 backoff
  • 503: service degraded; retry with backoff
Permanent errors should not be retried without changing something:
  • 400 INVALID_REQUEST: fix the request (missing fields, invalid file format, file too large)
  • 401 UNAUTHORIZED: provide a valid API key
  • 403 ACCOUNT_TERMINATED: contact support; the account cannot be recovered programmatically

Retrying submissions

For 5xx errors, use exponential backoff to avoid overwhelming the API during an outage.

Handling failed jobs

A job with status: "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.
Failed jobs should be resubmitted as new requests. The original 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 a 429 RATE_LIMITED response, the error body includes details:
Wait before retrying. The standard rate limit window is 60 seconds. See rate limiting for limits by tier.

Checking job status after a timeout

If your application restarts or a webhook is missed, poll the job status endpoint to recover in-flight jobs: