Errors
Every failure uses a standard HTTP status code and the same JSON envelope — branch on success before you read anything else.
Two kinds of failure A request error (bad key, bad parameter, over quota) comes back synchronously as a non-2xx response with the envelope below. A generation failure happens later: the create call returns
200, then the asset ends at taskStatus: 3 — and its credits are refunded automatically. Read errorCategory / errorDetail on the asset to see why. See Async & polling.Error envelope
error response
{
"success": false,
"error": {
"code": 14001,
"message": "Insufficient credit",
"httpStatus": 402,
"timestamp": "2026-08-05T09:12:00.000Z",
"path": "/v1/models/from-text"
}
}There is no data on an error. error.code is a stable numeric identifier — switch on it, not on error.message, which is human-readable and may change.
error.details on some codes A few errors add an error.details object with the live numbers behind the failure — e.g. 13002 returns { "total": 15, "maxTotal": 15 }. Read those instead of hard-coding limits into your client.HTTP status codes
| Status | Meaning |
|---|---|
400 | Validation — bad or missing parameter, unsupported engine/format, or an unreadable image. |
401 | API key missing, invalid, or revoked. |
402 | Insufficient credits to cover the job. |
403 | Account not entitled to the API — no active subscription or completed credit purchase. |
404 | Asset or collection not found, or not owned by your key. |
413 | An uploaded file exceeded 20 MB. |
429 | Rate limit (10003), too many concurrent generations in flight (13002), or an upstream engine's quota — exceeded. Back off and retry. |
500 · 503 · 504 | Server error, maintenance, or an upstream engine timeout. Retry with backoff. |
Error code catalog
The codes you're most likely to meet on /v1. The numeric code is stable across releases.
| Code | HTTP | When it happens |
|---|---|---|
| 1001 | 401 | API key missing, invalid, or revoked. |
| 6014 | 403 | Account has no active subscription or completed credit purchase — not entitled to the API. |
| 14001 | 402 | Wallet can't cover the job. Top up, or check GET /v1/credits. |
| 2001 | 400 | A field failed validation (type, range, or length). |
| 2012 | 400 | Prompt or image was blocked by the content policy. |
| 7002 | 413 | An upload exceeded the 20 MB limit. |
| 7003 | 400 | Unsupported upload format. |
| 13001 | 404 | Unknown asset id, or the asset isn't owned by your key. |
| 13005 | 400 | Remesh source must be an AI-generated model — uploads can't be re-meshed. |
| 13008 | 400 | Animate source isn't riggable — needs a clear humanoid or animal form. |
| 10003 | 429 | Over the per-IP or per-user rate limit. |
| 13002 | 429 | Too many generations already in flight — see concurrency limits. Nothing is charged; retry once a slot frees. |
| 20001 | 504 | A generation engine timed out. Safe to retry. |
| 20002 | 429 | An engine's capacity is momentarily full. Retry after a short wait. |
| 20004 | 400 | An engine rejected the input (e.g. an image it can't process). |
Handling
- Retry
429,500,503,504with exponential backoff — start ~1 s, cap ~30 s, five tries. - Don't retry
400,401,403,404— fix the request instead. - On
429, slow your cadence: the limits are 240 requests/min per IP and 120 generation requests/min per user. - A job that fails after a
200(taskStatus: 3) is refunded automatically — you're billed only for successful generations.