Skip to main content

Error envelope

Every error response uses the same shape:
{ "error": { "code": "INSUFFICIENT_CREDITS", "message": "Not enough credits", "details": null } }
  • code - stable, machine-readable; branch on this.
  • message - human-readable.
  • details - present on validation errors (400); the offending fields and why they failed.

Common codes

HTTPcodeMeaning
400VALIDATION_ERRORRequest body/params failed validation (see details).
401UNAUTHORIZEDMissing, invalid, revoked, or expired API key.
402INSUFFICIENT_CREDITSNot enough credits for this generation.
402SUBSCRIPTION_REQUIREDYour plan can’t perform this action.
404NOT_FOUNDThe job, style, or upload doesn’t exist (or isn’t yours).
429RATE_LIMIT_ERRORPer-key rate limit hit - see Rate limits.
429CONCURRENT_LIMIT_REACHEDToo many generations in flight at once.
429USAGE_LIMIT_EXCEEDEDUsage allowance exceeded for the period.
500INTERNAL_ERRORUnexpected server error - safe to retry with backoff.

Job failures vs request errors

The errors above are returned by the HTTP request itself. A generation that starts but fails returns 200 with a terminal job whose status is failed:
{ "data": { "id": "...", "status": "failed", "error": { "code": "GENERATION_FAILED", "message": "..." } } }
Job-level error.code is one of GENERATION_FAILED or EXTRACTION_FAILED.

Handling guidance

  • 402 → top up credits / upgrade before retrying.
  • 429 → honor Retry-After and back off (Rate limits).
  • 400 → fix the request using details; don’t blind-retry.
  • 5xx → retry with exponential backoff (use an Idempotency-Key on creates).