Errors
The API surfaces errors in two places:
- HTTP responses — synchronous endpoint errors (validation, auth, quota). The response body is
{ "success": false, "message": "…" }with an HTTP status code in the 4xx–5xx range. - Render status — asynchronous errors discovered while a render is being produced. The render completes with
movie.status = "error"andmovie.messagedescribing what failed. The HTTP status ofGET /v2/moviesis still200.
All error messages are short, descriptive strings. They are not stable identifiers — match on HTTP status and on the endpoint plus message family rather than on exact text.
HTTP status code summary
| Status | Meaning |
|---|---|
200 |
Request accepted. For GET /v2/movies, also check movie.status. |
400 |
Validation error in the request. |
401 |
Authentication or quota error. |
403 |
Authorisation error (role, blocked storage, invalid admin token). |
404 |
Resource (template, movie, file) not found. |
405 |
HTTP method not supported on this endpoint. |
409 |
Conflict (duplicate filename on upload, etc.). |
413 |
Payload too large (media upload > 500 MB). |
500 |
Internal error. |
Authentication errors
Returned when the request lacks a valid API key or is using one without sufficient permissions.
| Status | Message | Endpoint |
|---|---|---|
403 |
Insufficient permissions |
/v2/templates, /v2/media, POST /v2/movies (admin endpoints) |
403 |
Invalid token |
Admin-only query parameters |
To resolve: confirm the x-api-key header is present and that the key has the right role for the action — Render to render videos, Editor to create / edit templates, Manager to manage Connections. See API keys → Permission roles.
Quota and plan errors
Returned when the account has exhausted its plan allowance.
| Status | Message | Endpoint |
|---|---|---|
401 |
You exceeded the quota of movies in your plan. Please upgrade your plan to continue. |
POST /v2/movies |
401 |
You exceeded the quota of drafts in your plan. Please upgrade your plan to continue. |
POST /v2/movies |
401 |
Movie is larger ({w}x{h}) than your plan allowance ({w}x{h}) |
POST /v2/movies |
400 |
Insufficient credits |
Render submission paths |
403 |
Storage is blocked. Add credits to continue uploading. |
POST /v2/media/file |
To resolve: top up credits or upgrade the plan. See Credits & limits.
Validation errors
Returned when the request payload is missing required fields or has the wrong shape.
| Status | Message | Endpoint |
|---|---|---|
400 |
No movie JSON received |
POST /v2/movies |
400 |
Error parsing movie JSON or the movie was empty |
POST /v2/movies |
400 |
No valid movie JSON received |
POST /v2/movies |
400 |
Project ID must be a 16-character string. Received ID: '…' (length: N) |
GET /v2/movies |
400 |
Invalid start date / Invalid end date |
GET /v2/movies |
400 |
Maximum date range is 3 months. |
GET /v2/movies |
400 |
No payload provided |
POST /v2/templates, POST /v2/media/file, PUT /v2/media/file, DELETE /v2/media/file |
400 |
Tags must be a string or an array |
POST /v2/templates |
400 |
Payload movie must be a JSON string or JSON object |
POST /v2/templates |
400 |
Template movie is not valid JSON or it's too large |
POST /v2/templates |
400 |
name is required |
/v2/media/file |
400 |
contentType is required |
POST /v2/media/file |
400 |
size is required and must be a positive number |
POST /v2/media/file |
400 |
path is required / Invalid path: no filename |
GET /v2/media/file |
400 |
destination is required |
PUT /v2/media/file |
400 |
folder is required / Invalid folder name |
/v2/media/folder |
400 |
Cannot delete root folder / Cannot delete the temp folder |
DELETE /v2/media/folder |
400 |
Folder is not empty. Delete all files first. |
DELETE /v2/media/folder |
400 |
Invalid movie status |
Render submission |
404 |
Template {id} not found |
/v2/templates, POST /v2/movies (template ref) |
404 |
File not found |
/v2/media/file |
404 |
Movie ID {id} not found |
Render submission |
403 |
Template {id} is not owned by you / Movie ID {id} is not owned by you |
POST /v2/templates, render submission |
405 |
Method not supported |
All endpoints |
409 |
A file with this name already exists. Delete it first. |
POST /v2/media/file |
409 |
A file with this name already exists in the destination folder |
PUT /v2/media/file |
413 |
File exceeds maximum size of 500 MB |
POST /v2/media/file |
Rendering errors
Surfaced asynchronously via GET /v2/movies when movie.status = "error". The movie.message field contains the underlying error. Examples seen in production:
| Family | Example message |
Trigger |
|---|---|---|
| Element validation | Scene #1 Element #2: The element type 'video' requires a 'src' property. |
A required field was missing or null. |
| Asset download | Asset fetch errors propagate from the downloader. | The element src URL is unreachable, requires authentication, or returns an unsupported media type. |
| Webpage capture | Errors from the HTML / webpage renderer. | An html element pointed at a URL that timed out, returned non-2xx, or required interaction. |
| AI generation | Errors from the upstream AI provider. | The provider declined the prompt, rate-limited the request, or returned a transient 5xx. |
| Voice synthesis | Errors from the speech provider. | Invalid voice ID, unsupported language, or empty text. |
| Subtitles | Speech-to-text transcription error. | Source audio was missing or unreadable. |
For rendering errors, the movie.success field is false even though the HTTP status is 200.
Timeouts
When a render is running for more than 15 minutes, GET /v2/movies returns movie.status = "timeout" with message = "Movie took too long to render". The original render may still eventually complete; treat timeout the same as error for client code paths.
Retry guidance
| Class | Retry strategy |
|---|---|
400 validation |
Do not retry. Fix the payload. |
401 quota |
Do not retry until credits are topped up. |
403 auth |
Do not retry. Fix the key or role. |
404 not found |
Do not retry. Confirm the ID. |
409 conflict |
Do not retry blindly. Resolve the conflict (rename, delete the existing file). |
500 internal |
Retry with exponential backoff, up to 3–5 attempts. |
movie.status = "error" |
Inspect the message. Re-submit a fixed payload if the cause was client-side. |
movie.status = "timeout" |
Re-submit the same job; treat as a transient failure. |