Video API
Video generation is asynchronous: create a task, wait for completion, then download the result. Use the same API key throughout.
1. Choose a model
Find the operation and its supported duration, resolution and aspect ratio. Replace YOUR_VIDEO_MODEL_ID and the example parameters with values from the catalog.
curl https://api.closerouter.dev/v1/videos/models \
-H "Authorization: Bearer $CLOSEROUTER_API_KEY"2. Check the price
This request neither generates video nor charges you. Save max_cost_usd from the response. To pin an option, use the same provider.option_id in the quote and generation.
curl https://api.closerouter.dev/v1/videos/quote \
-H "Authorization: Bearer $CLOSEROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_VIDEO_MODEL_ID",
"prompt": "A slow camera move over a mountain lake",
"duration": 5,
"aspect_ratio": "16:9"
}'3. Create a task
Replace MAX_COST_FROM_QUOTE with the quoted amount and use the same parameters. Another POST creates a new generation.
curl https://api.closerouter.dev/v1/videos \
-H "Authorization: Bearer $CLOSEROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_VIDEO_MODEL_ID",
"prompt": "A slow camera move over a mountain lake",
"duration": 5,
"aspect_ratio": "16:9",
"max_cost_usd": "MAX_COST_FROM_QUOTE"
}'Task accepted — HTTP 202
Abbreviated response. Save id for the next steps.
{
"id": "TASK_ID",
"status": "pending",
"polling_url": "https://api.closerouter.dev/v1/videos/TASK_ID"
}4. Check progress
Replace TASK_ID with the returned ID. While the task is unfinished, poll its status instead of submitting another generation.
curl https://api.closerouter.dev/v1/videos/TASK_ID \
-H "Authorization: Bearer $CLOSEROUTER_API_KEY"Completed result
Abbreviated example with an illustrative amount. usage.cost is the final USD cost when available in the response.
{
"id": "TASK_ID",
"status": "completed",
"unsigned_urls": [
"https://api.closerouter.dev/v1/videos/TASK_ID/content?index=0"
],
"usage": {
"cost": 0.15
}
}5. Download the file
The unsigned_urls links require authentication: use a key belonging to the task’s account. The zero-based index selects an output.
curl https://api.closerouter.dev/v1/videos/TASK_ID/content?index=0 \
-H "Authorization: Bearer $CLOSEROUTER_API_KEY" \
--output video.mp4Task states
| Status | Action |
|---|---|
pending | Accepted; keep polling. |
in_progress | Processing; do not submit a new POST. |
completed | Download the authenticated result. |
failed | Read error before taking another action. |
Extend, upscale and edit
Check operation and source support for the selected provider. Each action creates a new task. Quote each action at /videos/quote first, then submit the same parameters and returned max_cost_usd to /videos.
Extend a video
Quote request body. Use your own completed task and parameters supported by the operation.
{
"model": "YOUR_VIDEO_MODEL_ID",
"operation": "extend",
"video": {
"id": "SOURCE_TASK_ID",
"index": 0
},
"prompt": "Continue the camera movement",
"duration": 5
}Upscale a video
Quote request body. Use your own completed task and parameters supported by the operation.
{
"model": "YOUR_VIDEO_MODEL_ID",
"operation": "upscale",
"video": {
"id": "SOURCE_TASK_ID",
"index": 0
},
"resolution": "1080p"
}Edit a video
Quote request body. Use your own completed task and parameters supported by the operation.
{
"model": "YOUR_VIDEO_MODEL_ID",
"operation": "edit",
"video": {
"id": "SOURCE_TASK_ID",
"index": 0
},
"prompt": "Make the scene snowy"
}Sources and restrictions
Use video: {"url": "https://example.com/source.mp4"} instead of video.id when the operation supports an external source. For extension, duration is the number of added seconds. extend and edit require prompt; upscale requires resolution.
Do not send input, native provider fields, provider.options or callback_url. Chat Completions does not generate video; analyzing video input is a separate text-model capability.
Uncertain outcome
If the response includes closerouter.reconciliation_pending, the final outcome is still being reconciled. Keep the task ID and poll its status; submitting again may create a separate paid task.