Appearance
Errors
Every error returns a flat JSON body with a machine-readable error code that maps one-to-one to the HTTP status, a human message, and sometimes a details object.
json
{
"error": "insufficient_balance",
"message": "Not enough balance for this job.",
"details": { "balance": 0.4, "required": 3 }
}Branch on error (stable), not on message (may change) or the raw status.
Codes
| HTTP | error | Meaning | What to do |
|---|---|---|---|
400 | bad_request | Malformed request: missing source, both/neither of recipeId/recipeConfig, unknown recipeId, unsupported file type, or a recipe that failed validation. | Read message and details.errors; fix and resubmit. |
401 | unauthorized | Missing, malformed, unknown, or revoked API key. | Check the Authorization: Bearer header; rotate the key if needed. |
402 | insufficient_balance | Your shared balance can't cover the job. details has balance and required. Nothing ran. | Top up in the dashboard, then resubmit. |
404 | not_found | No such resource, or it isn't yours. The two are deliberately indistinguishable (owner-scoped). | Verify the id and that it belongs to this account. |
409 | not_ready | Tried to download a variant that hasn't finished. | Poll GET /jobs/{id} until the variant is completed. |
410 | gone | A one-time download link is already spent (downloaded) or purged after 1h. | Don't retry — resubmit the job if you need the result again. |
413 | payload_too_large | Upload exceeds the 100 MB cap. | Shrink or re-encode the source. |
429 | rate_limited | Over a per-account rate limit. A Retry-After header says how long to wait. | Back off for Retry-After seconds. See Rate limits. |
500 | internal_error | An unexpected server error. | Retry with backoff; if it persists, contact support with the message. |
Validation details
A 400 from recipe validation carries rule-cited findings so you can pinpoint the problem:
json
{
"error": "bad_request",
"message": "Recipe failed validation.",
"details": {
"errors": [ { "rule": "LIMIT_COPIES_RANGE", "message": "copies must be between 1 and 50" } ],
"warnings": []
}
}Only errors block the job. warnings are advisory and won't stop it.
Retry guidance
- Safe to retry:
429(afterRetry-After),500, and network failures. Job creation is not automatically idempotent, so a retriedPOST /jobscreates a new job — only retry creation when you're sure the first didn't succeed. - Do not retry:
400,401,402,404,410— these won't change on a repeat. Fix the cause first.