Errors
Errors are JSON with an error key:
{ "error": "Content not found" }
Two endpoints deviate, and both are noted below.
Status codes
| Status | Meaning | What to do |
|---|---|---|
400 | Validation failed, or a plan limit was exceeded | Read error; it names the field or limit. Do not retry unchanged. |
401 | Key missing, malformed, invalid or revoked | Check the key with GET /api-keys/introspect. |
402 | Not enough credits | Top up, or check GET /users/credits before a batch. |
403 | Key is valid but lacks a scope | Mint a key with the scope in required. |
404 | No such resource for this key's owner | Another user's resource is indistinguishable from one that doesn't exist. |
409 | Conflict with in-flight work | See below — usually resolvable by being explicit. |
429 | Rate limited | Wait Retry-After seconds. |
5xx | Server-side failure | Retry with backoff. If it persists, it's ours. |
401 — authentication
{ "error": "Invalid or revoked API key" }
The key is missing, malformed, expired from your account, or revoked. Confirm
it independently with GET /api-keys/introspect, which needs no scope — that
separates "the key is wrong" from "the request is wrong". See
Authentication.
403 — insufficient scope
{
"error": "insufficient_scope",
"required": ["write"]
}
required lists what the endpoint needs. Scopes are fixed for a key's life, so
this means minting a new key — see Scopes.
409 — conflicts
Two situations produce it.
Editing content while it is generating. PUT /contents/{id} refuses,
because the edit would silently discard the running job's work:
{
"error": "This content is currently being generated. Editing it will cancel the generation in progress.",
"code": "generation_in_progress"
}
Resend with "cancel_generation": true to cancel the job and apply the edit.
Publishing something already being published. POST /contents/upload/{id}
refuses a second dispatch while one is in flight, so a client that retries
after a timeout doesn't post the same video twice. It clears once the first
dispatch passes the stall threshold, so genuine recovery still works.
429 — rate limits
Carries Retry-After in seconds. Honour it rather than retrying immediately —
see Rate limits.
Endpoints that deviate
GET /contents/{id}/versionsreturns{"message": ...}on404, not{"error": ...}. Handle both keys if you parse error bodies generically.GET /subscription/currentwraps its payload insuccessand returns{"success": false, "error": ...}on failure.
Retrying safely
- Retry:
429(afterRetry-After) and5xx, with exponential backoff. - Don't retry unchanged:
400,401,403,404— they will fail the same way. - Careful with
409on upload: a naive retry loop is what that guard exists to catch. Polltask-statusto find out what actually happened before dispatching again.