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 }, and 14001 returns { "required": 240, "available": 45, "topUpUrl": "https://picoberry.ai/pricing" }. 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. Also returned when a key is paused by its daily safety limit (6016), or when a free account asks for a paid-only model (6017). |
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. |
| 6016 | 403 | Key paused automatically after going over its daily safety limit. Only reading and downloading results work until the account owner resumes it from the dashboard, so don't retry. |
| 6017 | 403 | The model is paid-only (paidOnly: true in GET /v1/models) and the account is on the free plan. The key still works — switch to a model with paidOnly: false, or upgrade at error.details.upgradeUrl. If you omit the model (model or engine), the default is one your plan can use — except UV Unwrap, which is paid-only on every engine. |
| 14001 | 402 | Wallet can't cover the job. error.details says how much it needed (required), how much your wallet could spend on it (available), and where to top up (topUpUrl). Don't retry until the wallet is topped up; 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,402,403,404— fix the request instead (for402, top up first). - 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.