Skip to main content
A video renders for minutes, so POST /v1/media/videos does not wait: it answers 202 with a media job in queued, and you read the job back until it is completed or failed. The finished clip is a file. Images are the synchronous case — see Images.

The media job object

string
med_….
string
Always media_job.
string
video. Other async media kinds share the object and the routes below.
string
queuedprocessingcompleted | failed.
string | null
The model rendering it.
object
The request as accepted.
object | null
On completed: { files: [{ file_id, content_type, width, height, duration_seconds }] }. Dimensions are null where the model did not report them.
object | null
On failed: { code, message } — the reason, safe to repeat, so a refusal and an outage read differently.
integer | null
What was debited, in integer micro-USD, once the job finished: null while it runs, 0 on a failure — a job that fails is not billed.
string | null
The session whose agent submitted it; null for a job submitted through this API.
string
Submission time.
string | null
When it reached a terminal status.

Generate a video

POST /v1/media/videos202 Accepted — scope agents:write, Idempotency-Key required.
string
required
A model id from GET /v1/media/models?kind=video. Video models publish no price, so there is no default to pick for you.
string
required
What to render.
string[]
One public http(s) image to animate from. A private or loopback host is validation_failed.
integer
Target duration, 1–60. Models honour it as they can.
string
Such as 16:9 or 9:16.
integer
Repeat an earlier result.

Retrieve a job

GET /v1/media/{id}200 OK — scope agents:read. Poll it; a job left rendering for over thirty minutes is failed and not billed. Any med_ reads here, a clip job included — the same object GET /v1/media/clips/{id} answers.
Response
Read the clip with GET /v1/files/{file_id}?download=true. The file carries source.type = video_generation and source.job_id = this job. A job an agent submitted with generate_video carries its session_id, and that session’s event stream announces it: media.job.queued, then media.job.completed or media.job.failed. A job submitted here has no session, so poll it.

List jobs

GET /v1/media200 OK, cursor-paginated — scope agents:read. See Pagination.
string
video (or another async kind).
string
queued, processing, completed or failed.
string
Jobs an agent submitted from one session.
number
Page size, 1–100.
string
The next_cursor of the previous page.

Billing

A job is billed what it actually cost, on the media tier, when it completes; nothing is quoted beforehand. At submit the organization’s prepaid balance is checked against a small floor — insufficient_credits if it is below it — and the debit settles under the job id at completion, exactly once. A job that fails, is refused, or is abandoned is not billed.

Errors