Upload media
POST https://api.json2video.com/v2/media/file
Requests a presigned upload URL for a new media file. The endpoint registers the file in pending state and returns a presigned PUT URL that the client uses to upload the bytes directly. Files larger than 500 MB are rejected.
There is also POST /v2/media/folder for creating folder markers.
Request — upload URL
Path
POST /v2/media/file
Headers
| Header | Required | Value |
|---|---|---|
x-api-key |
yes | API key issued from the dashboard. Requires role render, editor, manager, or admin. |
Content-Type |
yes | application/json |
Body
{
"name": "clip.mp4",
"contentType": "video/mp4",
"size": 3145728,
"folder": "videos"
}
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Filename. Non-[a-zA-Z0-9._-] characters are replaced with _. |
contentType |
string | yes | MIME type. Determines the type (image/video/audio/other) shown by GET /v2/media. |
size |
integer | yes | File size in bytes. Must be > 0 and <= 500 MB. |
folder |
string | no | Target folder. If empty, the file lands at the root. The special folder temp flags the file as temporary (auto-deleted by lifecycle rules). |
Response — upload URL
200 OK
{
"success": true,
"uploadUrl": "https://json2video-media.s3.amazonaws.com/...&X-Amz-Signature=...",
"fileUrl": "https://media.json2video.com/{client_id}/files/videos/clip.mp4",
"expiresIn": 120
}
The client must immediately PUT the file bytes to uploadUrl. The URL expires 120 seconds after issue. After a successful upload, the record's status transitions to uploaded (asynchronously confirmed by the server).
Request — create folder
Path
POST /v2/media/folder
Body
{ "folder": "videos/raw" }
Folder names are sanitised to [a-zA-Z0-9/_-]+. Existing folders return 200 with message: "Folder already exists".
Response — create folder
200 OK
{
"success": true,
"timestamp": "2026-05-12T10:49:52.924Z"
}
Errors
| Status | Message | Cause |
|---|---|---|
400 |
name is required |
Missing name. |
400 |
contentType is required |
Missing contentType. |
400 |
size is required and must be a positive number |
Missing or invalid size. |
400 |
folder is required |
Missing folder on POST /v2/media/folder. |
400 |
Invalid folder name |
Folder name sanitises to empty. |
403 |
Storage is blocked. Add credits to continue uploading. |
Account storage is blocked. |
403 |
Insufficient permissions |
API key role is below render. |
409 |
A file with this name already exists. Delete it first. |
Filename collision. |
413 |
File exceeds maximum size of 500 MB |
size > 500 MB. |
Examples
Two-step upload
# 1. Ask for a presigned URL
RESP=$(curl -s --location --request POST 'https://api.json2video.com/v2/media/file' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "clip.mp4",
"contentType": "video/mp4",
"size": 3145728,
"folder": "videos"
}')
UPLOAD_URL=$(echo "$RESP" | jq -r .uploadUrl)
# 2. Upload the bytes directly to S3
curl --location --request PUT "$UPLOAD_URL" \
--header 'Content-Type: video/mp4' \
--upload-file ./clip.mp4
Create a folder
curl --location --request POST 'https://api.json2video.com/v2/media/folder' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{"folder": "videos/raw"}'