Getting started
Errors & limits
Every error is JSON with an "error" field and an honest status code. Nothing is charged on a request that fails validation, auth, or the balance check.
Status codes
| Code | Meaning | What to do |
|---|---|---|
| 400 | Validation failed — a field is missing, malformed, or over a cap. | Fix the request; the error message names the exact problem. |
| 401 | Missing or invalid API key. | Check the header format in Authentication. |
| 402 | INSUFFICIENT_CREDITS — balance below the estimate. | Top up, or shorten the script / lower the resolution. |
| 404 | Resource not found — or not yours. Also: no library voice matched a requested language. | Verify the id came from your own account; for voices, try a broader language name. |
| 409 | VOICE_LIMIT_REACHED — voice cap hit (cloned and library are capped separately). | Delete an unused voice to free a slot. |
| 422 | Selfie images could not be loaded (character photo mode). | Make sure the URLs are public https and serve real images. |
| 429 | TOO_MANY_ACTIVE_JOBS — concurrent job cap hit. | Wait for a running job to finish, then re-queue. |
| 5xx | Something failed on our side. | Safe to retry reads immediately; for POSTs see the retry note below. |
Error shape
{ "error": "mode must be \"talking_head\" or \"scenes\"" }
// Some errors carry extra context:
{ "error": "INSUFFICIENT_CREDITS", "credits_required": 620, "credits_balance": 214 }
{ "error": "TOO_MANY_ACTIVE_JOBS", "max_active_jobs": 5 }
{ "error": "VOICE_LIMIT_REACHED", "max_voices": 3 }404 never leaks existence
Asking for another client's character, voice, asset, or job returns the same 404 as an id that was never created. If you see an unexpected 404, the id is wrong or belongs to a different key.
Account limits
| Limit | Default | Where it bites |
|---|---|---|
| Active video jobs at once | 5 | 429 from POST /videos — queued + running jobs count. |
| Cloned voices | 3 | 409 from POST /voices — delete one to free a slot. |
| Library voices | 10 | Separate cap — free picks don't eat clone slots, same 409 when full. |
| Talking-head audio length | 59 s measured | Over-length scripts / audio are rejected with 400 at queue time. |
| Multi-scene narration length | 60.5 s estimated | Same — a 400 up front, before anything is charged. |
| TTS text | 5,000 characters | 400 from POST /tts. |
| List page size | 100 rows max | limit above 100 is rejected on assets / usage lists. |
Retry guidance
- GETs are always safe to retry. Status polls, lists, and summaries have no side effects.
- Don't blind-retry a POST that may have succeeded. If
POST /videostimes out on your side, first checkGET /usage/jobs— if a new job is there, it's running and reserved. A duplicate POST queues (and reserves credits for) a second job. - A failed job is not a bug in your request loop. Generation occasionally fails downstream; the reservation is refunded automatically. Re-queue the same request — see Jobs & polling.