Skip to content

Assets API

The Assets API takes your own audio and turns it into an asset the Video API can make a video from. Upload the file in the request, or send an https link and Scenema downloads it during the call. Either way the audio is checked before the call answers, so an asset you get back is ready to use.

Voiceover or soundtrack

Every asset says how a video should use it, with type:

type Use it for How the video is cut
voiceover A recorded voice, a podcast segment, speech from another tool On the sentences: every idea gets its shot
soundtrack A music bed or a song On the beats and sections, for a beat synced explainer

For a soundtrack, Scenema listens to the track first: its tempo, beats, sections and mood decide where the shots cut. Say what the video is about in the video’s prompt.

Upload a file

POST https://api.scenema.ai/v1/assets with multipart/form-data:

Terminal window
curl -X POST "https://api.scenema.ai/v1/assets" \
-H "Authorization: Bearer $SCENEMA_API_KEY" \
-F "file=@launch-voiceover.mp3" \
-F "type=voiceover" \
-F "title=Launch voiceover"
Form field Meaning
file The audio file.
type voiceover or soundtrack.
title Optional name. The file name by default.
language Optional language of the speech or lyrics, e.g. en. Detected when left out.

Send JSON with an https link instead, and Scenema downloads the file during the call:

Terminal window
curl -X POST "https://api.scenema.ai/v1/assets" \
-H "Authorization: Bearer $SCENEMA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/music/upbeat-bed.mp3", "type": "soundtrack", "title": "Upbeat bed"}'

The link must be public https, at most 3 redirects, and answer within 60 seconds. When the file cannot be downloaded, the request fails with 422 ASSET_DOWNLOAD_FAILED and says why (the status the link answered, a timeout, or a host that could not be reached). Nothing is kept.

The asset

Both ways answer 201 with the asset:

{
"id": "file_8b1c2d3e4f5a6b7c8d",
"type": "voiceover",
"title": "Launch voiceover",
"format": "mp3",
"contentType": "audio/mpeg",
"durationMs": 61250,
"sizeBytes": 982144,
"language": null,
"source": "upload",
"createdAt": "2026-10-28T09:12:44.120Z",
"audio": { "url": "https://...", "expiresAt": "2026-10-28T10:12:44.120Z" }
}

Pass its id as audioId to POST /v1/videos. The video is as long as the asset, and its price is counted on durationMs. One asset can make any number of videos.

GET /v1/assets/{id} returns an asset with a fresh audio.url (valid for one hour), and GET /v1/assets lists the workspace’s assets, newest first, with page and perPage (up to 100).

Limits

Limit Value
Format MP3 only. The format is read from the file itself, so a WAV or M4A renamed to .mp3 is refused
Size 50 MB per file, uploaded or linked. That holds 30 minutes of MP3 at up to 192 kbps
Length 3 seconds to 30 minutes
Uploads 60 an hour per workspace, uploads and links together
Storage Assets count toward the workspace’s storage

A file over a limit is refused before anything is kept. See Errors for every code.

Upload rate

A workspace can send 60 uploads an hour to POST /v1/assets, counted together for every key and for both uploads and links. A refused upload counts too. The 61st request in an hour answers 429 UPLOAD_RATE_LIMITED, with a Retry-After header that gives the seconds until the hour’s count starts over:

HTTP/1.1 429 Too Many Requests
Retry-After: 1740
{
"error": "This workspace uploaded 60 files in the last hour. Try again in 29 min.",
"code": "UPLOAD_RATE_LIMITED"
}

The hour runs on the clock (10:00 to 11:00 UTC, for example). One asset can make any number of videos, so upload a file once and reuse its id. This limit comes on top of the workspace’s request rate limit.