Video generation (per-second models)

Create image-to-video, first/last-frame, reference, avatar and video-tool tasks with POST /v1/videos, poll them, download the result and pay per second of output.

On this page
  1. Inputs
  2. Create a task
  3. Video model fields
  4. Avatar and video tools
  5. Estimate the price first
  6. Retry safely with Idempotency-Key
  7. Check status and download
  8. How you are charged
  9. Verify the setup
  10. Troubleshooting
  11. Related

The video models listed under Models → Video run as asynchronous tasks on POST /v1/videos and are priced per second of output video. You create a task, poll it, then download the file. Failed and cancelled tasks are not charged.

Step Request
Get a price estimate (optional) POST /v1/videos with "dry_run": true
Create a task POST /v1/videos
Check status GET /v1/videos/{id}
Download GET /v1/videos/{id}/content
Cancel POST /v1/videos/{id}/cancel

#Inputs

Image, video and audio inputs are public https:// URLs or base64 data URIs (data:image/png;base64,...), up to 50 MB each and 80 MB for the whole request body.

Video models need a first frame. Pass it as image. If you only have a text idea, create the frame with an image model first and pass its URL. A text-only request returns 400 with "image is required".

#Create a task

cURL
curl https://bigmodel.io/v1/videos \
  -H "Authorization: Bearer $BIGMODEL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: lantern-take-1" \
  -d '{
    "model": "seedance-2.0-fast",
    "prompt": "The lantern drifts slowly to the right, mist moving over the water",
    "image": "https://example.com/lantern.png",
    "seconds": 5,
    "resolution": "720p"
  }'
Python
import os, time, requests

BASE = "https://bigmodel.io/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['BIGMODEL_API_KEY']}"}

task = requests.post(f"{BASE}/videos", headers={**HEADERS, "Idempotency-Key": "lantern-take-1"}, json={
    "model": "seedance-2.0-fast",
    "prompt": "The lantern drifts slowly to the right, mist moving over the water",
    "image": "https://example.com/lantern.png",
    "seconds": 5,
}).json()

while task["status"] in ("queued", "running"):
    time.sleep(10)
    task = requests.get(f"{BASE}/videos/{task['id']}", headers=HEADERS).json()

print(task["status"], task.get("output", {}).get("url"), task.get("cost_usd"))

An accepted task returns 202, a Location header and:

json
{"id": "6f1c...", "object": "video", "model": "seedance-2.0-fast", "status": "queued", "created_at": 1760000000, "estimated_cost_usd": 0.4272}

#Video model fields

Field Notes
model Required.
prompt What happens in the shot.
image Required: the first frame. first_frame is accepted as an alias.
last_frame Optional end frame, on models with first/last frame. Needs image.
reference_images, reference_videos, reference_audios Arrays of inputs on models that take references. With references, image counts as one more reference image.
seconds Output length (duration is an alias). Default 5, kept within the model's range.
resolution One of the model's resolutions, such as 720p. Default 720p when the model has it.
aspect_ratio For example 16:9 or 9:16. size like 1280x720 also sets it.
audio true or false on models with native audio.
seed Integer, for repeatable results where the model supports it.

Each model's range of seconds, resolutions and reference limits is shown in the catalog. A value outside them returns 400 with the allowed values.

#Avatar and video tools

The same endpoint runs avatar and tool models:

Model Inputs
infinitetalk image (a portrait) or video (one person), plus input_audio (the voice track)
latentsync, latentsync-music video (one person, face visible) and input_audio
wan-animate-2 image (a person), video (the motion to copy), or both
video-upscale, seedvr2-upscale video; target_resolution 1080p (default) or 2k on video-upscale
video-to-clay video; mode clay_masked (default), clay or sculpt; keep_audio

Avatar models are charged by the length of the voice track (or the video), tools by the input video's length.

#Estimate the price first

Add "dry_run": true to the same body. Nothing is generated and nothing is charged; inputs are still read so the estimate can use their length.

bash
curl https://bigmodel.io/v1/videos \
  -H "Authorization: Bearer $BIGMODEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "seedance-2.0-fast", "image": "https://example.com/lantern.png", "seconds": 5, "dry_run": true}'
json
{"object": "quote", "model": "seedance-2.0-fast", "unit": "per_second", "estimated_units": 5, "estimated_cost_usd": 0.4272}

#Retry safely with Idempotency-Key

Send an Idempotency-Key header (up to 200 characters) when you create a task. If the response is lost and you send the request again with the same key and API key, you get the original task back instead of a second generation. Use a new key for each new video.

#Check status and download

bash
curl https://bigmodel.io/v1/videos/TASK_ID \
  -H "Authorization: Bearer $BIGMODEL_API_KEY"

curl -L -o video.mp4 https://bigmodel.io/v1/videos/TASK_ID/content \
  -H "Authorization: Bearer $BIGMODEL_API_KEY"

status is queued, running, succeeded, failed or canceled. Poll every 5 to 15 seconds. While running, progress may show 0–100. A succeeded task has output: {"type": "video", "url": "...", "expires_in": 86400} and cost_usd, the amount charged. A failed task has error.message.

/content redirects (302) to the file; with curl use -L. The link in output.url works without an API key for 24 hours, and each status call returns a fresh one. Save the file if you need it longer. Any API key on the same account can read the task.

POST /v1/videos/TASK_ID/cancel asks the model to stop. The call returns the task; it moves to canceled shortly after, unless it had already finished. Tasks that do not finish within 3 hours end as failed and are not charged.

#How you are charged

When you create a task, your balance must cover the estimate on top of tasks still running. The charge is made when the task succeeds, based on the video actually produced, so cost_usd can differ slightly from estimated_cost_usd. It appears in Usage. Each model's price is on Pricing.

Some video models are priced by output resolution (for example Seedance 2.0 Fast: 480p and 720p differ). Without resolution, 720p is used where the model offers it. Each model page lists the price per resolution, and dry_run quotes the resolution you send.

#Verify the setup

Send the dry-run example with your own first-frame URL. A 200 quote means your key can use the model. Then create the task and poll it until succeeded.

#Troubleshooting

400 "image is required". Video models animate a first frame. Pass image; create one with an image model if needed.

400 "seconds must be between …" or "resolution must be one of …". The value is outside the model's limits. Use one from the message or the catalog.

400 "… could not be read". An input URL is not public https://, or the data URI is malformed or over 50 MB.

402 insufficient_balance. Your balance, minus tasks still running, does not cover the estimate. Top up in Billing.

403 permission_error. The key is not in a group. Assign it to one in API keys.

404 model_not_available. The model is not offered to this key, or it belongs on another endpoint (speech and music use /v1/audio/*).

404 not_found_error. The task ID is wrong or belongs to another account.

409 not_ready on /content. The task has not succeeded yet. Keep polling.

503 api_error. Generation is temporarily unavailable. Retry with the same Idempotency-Key.

Updated · View as Markdown