Video
POST/v1/videos
One endpoint, three modes — which one you get depends only on which fields you pass alongside model/prompt.
Parameters
promptstringRequired for most models; optional for the one model with no text-to-video mode at all (fal/happy-horse, animates the image with no guidance if omitted).modelstringOptional, default "machgen/minimax-h3" (also the "auto" resolution). No auto-router for video yet — pin a slug from the catalog.duration_secsnumberOptional, default 4. Snapped to the nearest value the model actually supports; some models bill a fixed length regardless of what's requested.aspect_ratio / resolutionstringOptional. Combine to request a size — e.g. resolution: "720p" + aspect_ratio: "9:16". aspect_ratio is one of 16:9/9:16/1:1/4:3/3:4/21:9; resolution is a tier the specific model supports (varies per model — see its catalog entry). An unsupported combination is silently ignored (model default used), never a 400.height / widthintegerOptional. Explicit pixel dimensions — overrides aspect_ratio/resolution when given, same precedence as size on /v1/images.start_image_urlstringOptional — image-to-video. Public https:// URL or inline data:image/...;base64,... URI, animates that starting frame.input_referencesarrayOptional — reference-to-video. Up to 9 {"type":"image_url","image_url":{"url":...}} entries, model-dependent cap.input_video_references / input_audio_referencesarrayOptional, reference-to-video only. Same shape, video_url/audio_url — up to 3 each on supporting models.input_audio_urlstringOptional — single-file audio-to-video, LTX-2.5 only.input_video_urlstringOptional — video editing. A single URL to an existing clip to modify (not guide a new generation with, unlike input_video_references); requires a non-empty prompt describing the edit on every model except Kling v3.0 Motion Control (see next row), and is mutually exclusive with every other input field above on every model except that one. See Video editing.draftbooleanOptional — Seedance 2.5 draft mode. true renders a cheap 480p preview (resolution is forced to 480p); text/image-to-video only. The response carries "draft": true and draft_expires_at. See Draft mode.task_typestringOptional — Seedance 2.5 reference-video task: auto (default — the prompt decides, and an edit/extension then follows the clip’s own length and ratio), reference (generate a new video guided by the references; your duration_secs / aspect_ratio are honored), edit (edit the single reference clip; output length and ratio follow it, billed on the clip’s length) or extend (continue the clip; ratio follows it). Requires input_video_references (exactly one clip for edit/extend). A pinned value routes only to hosts with an explicit task field (Atlas Cloud, Fal, MachGen, and for edit/extend only, TOAPIS and WaveSpeed); reference can’t be pinned on TOAPIS/WaveSpeed/OpenSand, which decide from the prompt whether a call is a new generation, edit or extension. A pin no host can honor 400s with task_type_not_supported.auto_upscalebooleanOptional — Seedance 2.5 auto upscale. Renders at your resolution and AI-upscales one tier up (480p→720p, 720p→1080p, 1080p→1440p), priced at that upscaled tier. Can’t combine with draft. Otherwise 400 auto_upscale_not_supported.draft_idstringOptional — the id of a completed draft; renders its 1080p final as a new job (from_draft on the response). Must be the only field (plus optional model) — no prompt/inputs/duration. Valid for 7 days, once.webhook_urlstringOptional — an https:// URL that is POSTed the finished job (the same object the status route returns, with cost_usd) when it completes or fails, signed with X-VideoRouter-Signature. Must resolve to a public address, else 400 invalid_webhook_url. Omit it to use the default saved under Settings → Webhooks; null skips webhooks for this request. Polling still works. Webhooks →storebooleanOptional. false deletes the output 24 hours after the job completes instead of after the default 30 days. It shortens the lifetime; the result is still stored so it can be delivered. See Data retention.output_ttl_secsintegerOptional. Delete the output this many seconds after the job completes: 86400 (24 hours) to 2592000 (30 days), overriding store. A smaller value is raised to 24 hours. The finished job reports output_expires_at.provider / failoverobjectOptional. Same provider-preference shape as chat's provider, plus a timeout-triggered hedge (failover.on_timeout_sec) that resubmits to the next-cheapest untried host — both attempts get billed.
Motion control exception: novita/kling-motion-control-{std,pro}
are the one case on this platform where start_image_url combines with
a reference field — either input_video_references (one entry, fixed ~4s
output) or input_video_url (output matches the reference video's own
length, up to 30s) — and neither orientation requires prompt. See
Motion control for both worked examples.
Example response (202, job just created)
{
"id": "video_...",
"status": "queued",
"data": null,
"error": null,
"provider": "fal"
}
Billed once, in full, at creation time from the requested/snapped duration_secs — polling is free. Exact extra fields (e.g. seconds, size, fallback_used) vary a little by which provider actually served the job.
GET/v1/videos/models
Unbilled. Live list of every valid model slug for POST /v1/videos — bare ids only, no price or capability breakdown (see /models for that).
Example response
{
"object": "list",
"data": [
{ "id": "machgen/minimax-h3", "object": "model" },
{ "id": "veo-3.1", "object": "model" },
{ "id": "grok-imagine-video", "object": "model" }
]
}
GET/v1/videos/{id}
Unbilled — polling is free. Once the job has finished, cost_usd is what it was charged (0 for a failed, refunded job). It can be absent for a few seconds after completion while the host's final price lands — the next poll has it. The same field is returned by GET /v1/lipsync/{id} and GET /v1/face-swap/{id}.
Parameters
idstring (path)The id returned by POST /v1/videos.Example response (status: "completed")
{
"id": "video_...",
"status": "completed",
"data": [{ "url": "https://..." }],
"error": null,
"cost_usd": 0.42,
"output_expires_at": 1760745600
}
status is one of queued → in_progress → completed/failed. On failure, error carries the provider's message and data is null.
DELETE/v1/videos/{id}
Permanently deletes a finished video’s stored output; the job then answers 404. Needs the video scope. The request-log entry (prompt, settings, cost) is kept for billing. Unbilled. Lifetimes and the other ways to expire an output: Data retention.
Parameters
idstring (path)The id returned by POST /v1/videos.Example response
{
"id": "video_...",
"object": "video.deleted",
"deleted": true,
"files_deleted": 1
}
Errors: 409 job_in_progress while the video is rendering or still being finalized, 403 delete_not_allowed_yet within 24 hours of generation (retry_after_s says how long), 404 for an unknown or already deleted id, 502 storage_error if nothing could be removed (safe to retry). A video whose store / output_ttl_secs lifetime ran out answers 410 output_expired on GET.