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, invalid or missing API key, or insufficient credits. |
401 |
Quota / plan limit 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: a movie JSON over 2 MB (POST /v2/movies) or a media upload over 500 MB. |
500 |
Internal error. |
Authentication errors
Returned when the request lacks a valid API key or is using one without sufficient permissions. Note that an invalid or missing API key returns HTTP 400, not 401.
| Status | Message | Endpoint |
|---|---|---|
400 |
Error: API Key not provided |
All endpoints |
400 |
Error: Invalid API Key |
All endpoints |
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.
The two Source URL errors below also carry "code": "media_src_required" in the response body, the AWS keys error carries "code": "aws_keys_in_movie", and the movie JSON is too large error carries "code": "movie_json_too_large". Elements at movie level are named Movie element #M instead of Scene #N, Element #M. When several elements have the problem, the message names the first one and lists the others.
| 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 |
Source URL is required: the {type} element in Scene #N, Element #M has no "src". β¦ |
POST /v2/movies β an image, video or audio element has no src, or an empty one. |
400 |
Source URL is invalid: the {type} element in Scene #N, Element #M has "src" set to "β¦", which is not a URL. β¦ |
POST /v2/movies β src is not a URL starting with http:// or https://. |
400 |
AWS keys cannot be sent in the movie (exports[0].destinations[0]). Save them in a connection (Dashboard β Connections β Output destinations) and reference it with "id", e.g. { "type": "aws-s3", "id": "my-bucket" }. If these keys are real, rotate them in AWS: they were sent in a request. |
POST /v2/movies β a destination in exports carries AWS keys (access-key-id, secret-access-key or a similar field, or an access key ID in an aws-s3 destination). Save them in an Amazon S3 destination instead. Nothing is rendered. |
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 |
413 |
The movie JSON is too large: 2.35 MB (2,461,234 bytes). The maximum size of a movie JSON is 2 MB (2,097,152 bytes). |
POST /v2/movies β the request body is over 2 MB. Nothing is created. Shorten media URLs or split the movie: see Create movie β Size limit. |
Server errors
| Status | Message | Endpoint |
|---|---|---|
500 |
Error creating movie: the movie JSON could not be stored. No movie was created; please try again. |
POST /v2/movies β a temporary storage error; "code": "movie_json_not_stored". Nothing was created or charged. Retry. |
413 |
Error creating movie: the movie record is larger than the database limit β¦ |
POST /v2/movies β "code": "movie_record_too_large". Should not happen with a body under 2 MB; contact support. |
500 |
Error creating movie: β¦ |
POST /v2/movies β any other failure to save the movie. Retry. |
Older integrations may have seen 500 Error creating movie: Item size has exceeded the maximum allowed size for a movie JSON above roughly 200 KB. That limit is gone: bodies up to 2 MB are accepted.
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 | Source URL is required for video element in Scene #1, Element #2 |
An image, video or audio element's src came from a variable ("{{video_url}}") that resolved to an empty value or to something that is not a URL. A src that is missing or invalid in the JSON you send is rejected earlier, by POST /v2/movies (see Validation errors). |
| Positioning / sizing | /Movie/scenes[0]/elements[1]: 'x' has an invalid value "auto". Use a number in pixels, a percentage of the canvas like "30%", one of: left, center, right |
x, y, width or height held a value that is neither a number nor one of the accepted strings. See Positioning and sizing values. |
| 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. |
| Voice synthesis | Errors from the speech provider. | Invalid voice ID, unsupported language, rate-limit, or a transient 5xx. For voices on your own ElevenLabs key, see below. |
| 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.
Voices on your own API key
When an ElevenLabs voice runs on your own key β your default key (β
) or a key chosen with connection β a failure never falls back to JSON2Video's key. The render fails with one of these messages (prefixed with Scene #n, element #m: ):
| Message | Cause | Fix |
|---|---|---|
Voice "<voice>" was not found in your ElevenLabs account. Use a voice ID from your ElevenLabs account, or a voice listed at https://json2video.com/ai-voices/elevenlabs/. |
The key works, but the voice is not in the ElevenLabs account the key belongs to. | Add the voice to that ElevenLabs account, or use another voice. |
Voice "<voice>" cannot be used with your ElevenLabs account: <reason>. β¦ |
The ElevenLabs account has no access to that voice. | Use another voice, or check the voice in ElevenLabs. |
Your default ElevenLabs key (connection "<id>") failed: <reason>. Update it in Dashboard β Connections, or remove its star (β
) there. To use JSON2Video's key in one render, set "connection": "none". |
Your default key was rejected, is out of quota or credits, has a payment problem or lacks a permission β or the connection was deleted while the render ran. | Replace the key in Dashboard β Connections, remove its star, or set "connection": "none" on the voice. |
The ElevenLabs key in connection "<id>" failed: <reason>. Update it in Dashboard β Connections. |
The same, for a key chosen with connection. |
Replace the key, or reference another connection. |
Connection <id> not found in your list of connections. Add your connection from the dashboard. |
No connection has the ID in connection. IDs are case-sensitive. |
Fix the ID or create the connection. |
Could not read your connections to check for a default API key. Please try the render again. |
A temporary error while looking up your default key. | Render again. |
Any other ElevenLabs error is shown with the reason ElevenLabs gives. See the voice element's connection property.
On JSON2Video's key, voices are limited to the ElevenLabs catalog: an unknown voice fails with Voice "<voice>" is not found in the list of supported voices for ElevenLabs. β¦, and a catalog voice with a higher credit cost with Voice "<voice>" has a credit cost of <n>x. Only 1x voices are supported with JSON2Video API keys. Use your own ElevenLabs API key to generate this voice.
Delivery errors
Output destinations (webhooks, FTP, SFTP, Amazon S3, email) run after the render. A failed delivery does not change the movie's status: it is recorded in movie.destinations_result (Get movie status) and in the dashboard under Render logs β the render β Deliveries. Examples of message:
| Status | Example message |
Meaning |
|---|---|---|
ok |
Delivered to https://example.com (HTTP 200, 3 attempts). |
Delivered, here after two retries. |
error |
The receiver at https://example.com answered HTTP 404. Not retried. |
Your receiver answered with a 3xx or 4xx status. |
error |
The receiver at https://example.com answered HTTP 503 (3 attempts). |
Your receiver kept answering with a 5xx status. |
error |
No response from https://example.com within 30 s (1 attempt). The receiver may still have processed the request, so it was not sent again. |
Your receiver took more than 30 seconds to answer. |
error |
Could not reach https://example.com: β¦ (3 attempts). |
DNS, connection or TLS error. |
error |
Not delivered: https://example.com resolves to a private, loopback or link-local network address. JSON2Video only connects to public internet addresses. |
The host points at a non-public address. Nothing was sent. |
error |
Connection "<id>" was not found. Create it in Dashboard β Connections, or remove it from the movie. |
The destination id does not exist. |
error |
The password of connection "<id>" could not be read. Save the connection again in Dashboard β Connections. |
Enter the password again in the dashboard. |
error |
A movie can deliver through one export only, and this one has 2. Nothing was delivered. |
Put every destination in a single exports object. |
error |
β¦ Stopped retrying: the delivery ran out of time. / Not attempted: the delivery ran out of time. |
All destinations share a budget of about 5 minutes. |
skipped |
Nothing to upload: the render did not produce a video. |
FTP, SFTP, Amazon S3 and email destinations of a failed render. |
Amazon S3 deliveries
The same messages are shown by the Test button of an Amazon S3 destination (see below). my-videos, videos and the regions stand for your own values. Causes and fixes: Amazon S3 delivery β Troubleshooting.
| Status | Example message |
Meaning |
|---|---|---|
ok |
Uploaded abc123.mp4 to bucket my-videos, folder videos/2026. |
Delivered. At the root of the bucket: Uploaded abc123.mp4 to bucket my-videos. |
ok |
β¦ The bucket is in eu-west-1, not us-east-1: edit the connection. |
Delivered, but the destination's region is wrong. Edit it. |
error |
AWS does not know this access key ID: it was deleted, deactivated or mistyped. Check it in IAM (the user β Security credentials) and edit the connection. |
Unknown, deleted or deactivated access key. |
error |
The secret access key does not match the access key ID. Paste the secret access key again in the connection. |
Wrong secret access key. |
error |
The access key may not write to bucket my-videos, folder videos. Allow s3:PutObject on arn:aws:s3:::my-videos/videos/* in the IAM user's policy. |
AWS denied the upload: the IAM policy, a bucket policy, an SCP or a permissions boundary. At the root of the bucket: β¦to the root of bucket my-videos. Allow s3:PutObject on arn:aws:s3:::my-videos/* β¦ |
error |
Bucket my-videos encrypts objects with an AWS KMS key this access key may not use. Allow kms:GenerateDataKey and kms:Decrypt on that key for the IAM user. |
SSE-KMS bucket; the IAM user may not use the key. |
error |
Bucket my-videos does not exist. Check its name in the S3 console and edit the connection. |
Wrong bucket name. |
error |
Bucket my-videos is in region eu-west-1, not us-east-1. Edit the connection and choose eu-west-1. |
Wrong region, not corrected. Also Bucket my-videos is not in region us-east-1. Check its region (S3 console β the bucket β Properties β AWS Region) and edit the connection. |
error |
Amazon S3 is not available in region <region>. Check the bucket's region (S3 console β the bucket β Properties β AWS Region) and edit the connection. |
The region does not exist. |
error |
The connection to Amazon S3 (region eu-west-1) failed: <reason>. |
Network error or timeout. |
error |
Amazon S3 answered <code> (HTTP <status>): <reason>. |
Any other AWS error. |
error |
Stopped: the delivery ran out of time. |
The upload did not finish within the render's delivery budget (about 5 minutes for all destinations). It was cancelled. |
error |
An aws-s3 destination needs the ID of a saved connection (Dashboard β Connections β Output destinations). |
An aws-s3 destination without id. There is no inline form. |
error |
In an aws-s3 destination the movie can only set remote-path and file. Bucket, region and keys come from the connection. |
The movie's destination has other fields next to id. Nothing was delivered. |
error |
Connection "<id>" is of type aws-s3, not ftp. Remove "type" from the movie or use another connection. |
The movie's type does not match the saved destination. |
error |
The secret-access-key of connection "<id>" could not be read. Save the connection again in Dashboard β Connections. |
Enter the secret access key again in the dashboard. |
error |
The object key is β¦ bytes long; Amazon S3 allows at most 1024. Shorten remote-path or file. / The object key cannot contain a ".." folder. Edit remote-path or file. |
Fix the folder or the file name. |
Connections (dashboard)
Messages shown in Dashboard β Connections when saving or testing:
| Message | Cause |
|---|---|
You can run up to 20 tests per hour. Try again after HH:MM UTC. |
More than 20 tests (keys and destinations together) in the current hour. Tests refused before contacting anything do not count. |
ElevenLabs API keys start with "sk_". Check that you copied the whole key. |
The key does not look like an ElevenLabs key. |
A connection with this ID already exists. Choose another ID. |
IDs are unique per account. |
"none" is reserved: "connection": "none" tells a render to use JSON2Video's own key. Choose another ID. |
none cannot be used as an ID. |
The ID looks like an API key. IDs are not encrypted: β¦ |
Don't put secrets in IDs. |
The ID can only contain lowercase letters, numbers, "-" and "_", and must start with a letter or a number. |
See Connection IDs. |
The webhook URL must start with https:// |
Webhooks are saved with https:// URLs only. |
The webhook URL cannot point at localhost: JSON2Video calls it from the internet. |
Also for private IP addresses and JSON2Video's own API. |
Enter only the host name, without ftp:// or sftp:// |
FTP/SFTP host must be a bare host name or IP. |
The port must be a whole number between 1 and 65535 (21 for FTP, 22 for SFTP). |
Invalid port. |
Amazon S3 connections
When you save or test an Amazon S3 destination, its fields are checked first. The API answers 400 with a code and the field:
code |
field |
Message |
|---|---|---|
missing_field |
bucket |
Enter the bucket name, e.g. my-videos. |
invalid_bucket |
bucket |
Enter only the bucket name, without s3://, a URL or a folder. Put the folder in the remote path. |
invalid_bucket |
bucket |
A bucket name can only contain lowercase letters, numbers, dots (.) and hyphens (-). β also β¦is 3 to 63 characters long., β¦must start and end with a lowercase letter or a number., β¦cannot contain two dots in a row., β¦cannot be an IP address., and names with a prefix or suffix that AWS reserves (xn--, -s3alias, β¦). |
blocked_bucket |
bucket |
This bucket belongs to JSON2Video. Enter the name of a bucket in your own AWS account. |
missing_field |
region |
Choose the bucket's region, e.g. eu-west-1. |
invalid_region |
region |
Choose the bucket's region, e.g. eu-west-1. You find it in the S3 console: your bucket β Properties β AWS Region. |
unsupported_region |
region |
AWS regions in China (cn-β¦) are not supported: they are a separate AWS partition. Use a bucket in another region. β also for GovCloud (us-gov-β¦) and isolated regions. |
missing_field |
access-key-id |
Paste the access key ID of an IAM user. It starts with AKIA. |
temporary_access_key |
access-key-id |
This is a temporary access key (it starts with ASIA): it stops working within hours. Create an access key for an IAM user (it starts with AKIA). |
invalid_access_key_id |
access-key-id |
An access key ID has 20 characters and starts with AKIA. Check that you copied all of it, and that it is the access key ID, not the secret access key. |
missing_field |
secret-access-key |
"secret-access-key" is required for an aws-s3 connection. |
invalid_secret_access_key |
secret-access-key |
The secret access key is 40 characters long. Check that you copied all of it. β also The secret access key only contains letters, numbers, "/" and "+". β¦ and This is the access key ID, not the secret access key. β¦ |
The Test button of an Amazon S3 destination writes json2video-test.txt to the folder and answers Wrote json2video-test.txt to bucket my-videos, folder videos. JSON2Video does not delete it: you can. when it works. Other test messages: the Amazon S3 deliveries table, plus No answer from Amazon S3 for bucket my-videos (region eu-west-1) within 10 s. Try again in a moment. and The secret-access-key of this connection could not be read. Enter it again and save the connection, then test again.
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). |
413 payload too large |
Do not retry the same payload. Make it smaller. |
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. |