Video Generation
POST /v1/videos/generations — async video generation, fully compatible with vendor-native parameters
Video generation is asynchronous, in three steps: create the job, poll for status, download the result.
POST /v1/videos/generations — submit the job; returns an id and status: "processing" immediately
GET /v1/videos/{video_id} — poll until status becomes completed or failed
GET /v1/videos/{video_id}/content — download the video bytes (or use output_url from the response)
Generation typically takes 30 seconds to several minutes depending on the model and duration. Poll every 5-10 seconds, no tighter. The id is an opaque encrypted token carrying provider / model / duration — pass it back verbatim; do not parse or truncate it.
Full example
The model names in the examples (e.g. wan2.5-t2v-preview) are illustrative. The video models actually available to your account are those returned by the models page or GET /v1/models — depending on which upstreams the platform has enabled for you. The vendor-native parameters below apply to any video model.
import time, requests
BASE = "https://api.modelsite.ai/v1"
H = {"Authorization": "Bearer ms_live_sk_xxx", "Content-Type": "application/json"}
# 1. Create the job
job = requests.post(f"{BASE}/videos/generations", headers=H, json={
"model": "wan2.5-t2v-preview",
"prompt": "A cat playing piano on a rooftop at sunset",
"seconds": 5,
"size": "1280x720",
}).json()
video_id = job["id"]
# 2. Poll
while True:
v = requests.get(f"{BASE}/videos/{video_id}", headers=H).json()
if v["status"] in ("completed", "failed"):
break
time.sleep(5)
if v["status"] == "failed":
raise RuntimeError(v["error"]["message"])
# 3. Download
mp4 = requests.get(f"{BASE}/videos/{video_id}/content", headers=H).content
open("out.mp4", "wb").write(mp4)The API cards below are rendered from the OpenAPI spec (request-body parameter table, response schema).
Authorization
BearerAuth Authorization: Bearer $MODELSITE_API_KEY
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
标准跨厂商字段。除此之外的任何顶层字段都作为上游原生参数原样透传。
Response Body
application/json
application/json
curl -X POST "https://example.com/videos/generations" \ -H "Content-Type: application/json" \ -d '{ "model": "string", "prompt": "string" }'{ "id": "string", "object": "video", "status": "processing", "model": "string", "seconds": 0, "created_at": 0, "completed_at": 0, "output_url": "string", "usage": { "completion_tokens": 0, "total_tokens": 0 }, "error": { "code": "string", "message": "string" }, "vendor_data": {}}Authorization
BearerAuth Authorization: Bearer $MODELSITE_API_KEY
In: header
Path Parameters
创建任务时返回的 id(不透明加密令牌,内含 provider / model / 时长,请原样回传)。
Response Body
application/json
curl -X GET "https://example.com/videos/video_ual7J0gEbKHcrUcqI7nV7wkR6_V57Y_vlasce6jMjWOSfTKbgVcoIhA5"{ "id": "string", "object": "video", "status": "processing", "model": "string", "seconds": 0, "created_at": 0, "completed_at": 0, "output_url": "string", "usage": { "completion_tokens": 0, "total_tokens": 0 }, "error": { "code": "string", "message": "string" }, "vendor_data": {}}Authorization
BearerAuth Authorization: Bearer $MODELSITE_API_KEY
In: header
Path Parameters
创建任务时返回的 id。
Response Body
video/mp4
curl -X GET "https://example.com/videos/string/content""string"Full vendor-native parameter compatibility
The standard fields above are only the cross-vendor common subset. Any parameter the upstream vendor accepts can be written at the top level of the request under its original vendor name and is forwarded verbatim — no wrapper needed, and no waiting for the platform to add field support.
{
"model": "veo-3.0-generate-001",
"prompt": "A cat playing piano",
"seconds": 8,
"sampleCount": 2,
"personGeneration": "dont_allow",
"storageUri": "gs://my-bucket/output/"
}Three rules:
- Native names win. When a standard field and a native field both set the same thing, the native one wins.
{"seconds": 8, "durationSeconds": 4}sends4upstream — if you write a native parameter you want exact control, so the translation layer yields. - Each model only accepts its own vendor's parameters. Sending a parameter that belongs to a different vendor is rejected with a
400— for example passing Seedance'scamera_fixedto a DashScope (wan) model, or Sora'sn_secondsto a Veo model. Look up parameters under the vendor of the model you are actually calling. Cross-vendor-common names (duration,seed,size,resolution,negative_prompt, …) are not restricted. - Nested structures merge recursively. Nova Reel's
videoGenerationConfig: {"fps": 30}merges with thedurationSeconds/dimensionderived from standard fields instead of replacing the whole object.
The response side is lossless too: every non-standard field the vendor returns is preserved under vendor_data, including fields this documentation does not yet cover.
Native parameter names by vendor
The same concept often has a different name and type at each vendor. Standard fields are translated for you; when writing native parameters you must use the original names below.
| Vendor | Duration | Size | Aspect ratio | Notes |
|---|---|---|---|---|
| DashScope (wan) | duration | size, asterisk-separated 1280*720 | ratio | Native media[] is appended to frame_images, not replaced |
| ModelArk (Seedance) | duration (-1 = model decides, 1.5 pro only) | — | ratio | A non-empty native content[] replaces the derived one; frames takes precedence over duration |
| Vertex AI (Veo) | durationSeconds | — | aspectRatio | Native names are camelCase; snake_case aliases are accepted and converted |
| OpenAI (Sora) | seconds, a string "8" | size | — | — |
| Azure (Sora) | n_seconds, an integer | width / height | — | Has no size / seconds |
| OneRouter | duration (string; format varies by model family) | — | aspect_ratio | — |
These tables are not allow-lists — parameters not listed here pass through as well. A newly released upstream parameter works the same day, with no platform version to wait for.
Commonly used native parameters
Vertex AI Veo (land in the request's parameters object):
| Parameter | Type | Description |
|---|---|---|
sampleCount | integer | Number of candidate videos (1-4) |
personGeneration | string | allow_adult (default) / dont_allow / allow_all (requires approval) |
enhancePrompt | bool | Auto-enhance the prompt with Gemini (Veo 2 only) |
compressionQuality | string | optimized (default) / lossless |
resizeMode | string | Image-to-video resize mode: pad (default) / crop (Veo 3 image-to-video only) |
storageUri | string | Write output to a GCS path; omit to get base64 |
Instance-level native fields (last_frame, input_video, mask, mask_mode, reference_images) are placed correctly into Veo's instances rather than leaking into parameters.
ModelArk Seedance (merged into the top level of the request):
| Parameter | Type | Description |
|---|---|---|
camera_fixed | bool | Lock the camera |
watermark | bool | Add a watermark |
draft | bool | Draft preview mode (Seedance 1.5 pro only) |
callback_url | string | Callback URL for status changes |
content | array | Native content-block array (text / image_url / audio_url / video_url / draft_task) |
DashScope wan: input-level native parameters (media, template, reference_urls, first_frame_url, last_frame_url, audio_url, …) are routed into the request's input object automatically, while other generation knobs go to parameters — write them at the top level and the platform places them.
Image-to-video and reference material
Two field groups with different semantics — don't mix them up:
| Field | Semantics | Use for |
|---|---|---|
frame_images | Hard constraint | Pin the first / last frame; the model must reproduce it exactly |
input_references | Soft guidance | Supply style / composition / camera-motion references, not reproduced exactly |
{
"model": "wan2.5-i2v-preview",
"prompt": "The cat stands up and walks away",
"seconds": 5,
"frame_images": [
{ "image_url": "https://example.com/first.jpg", "frame_type": "first_frame" },
{ "image_url": "https://example.com/last.jpg", "frame_type": "last_frame" }
],
"input_references": [
{ "type": "video", "url": "https://example.com/motion.mp4", "role": "reference_video" }
]
}Vendor support for reference material varies widely; vendors that don't support it silently ignore input_references rather than erroring.
Size: two equivalent forms
size and resolution + aspect_ratio express the same thing — pick one:
{ "size": "1280x720" }
{ "resolution": "720p", "aspect_ratio": "16:9" }Sending both with conflicting values returns 400. The alias ratio (the DashScope / ModelArk native name) is equivalent to aspect_ratio.
Billing
Billed by video duration: cost = duration (seconds) × the model's per-second rate. Duration is taken from the actual generated result; failed jobs are not billed. Rates are on the models page.
When you override the duration with a native parameter (Veo's durationSeconds, ModelArk's duration), billing follows the duration the vendor actually returns, not the value of the standard seconds field.
Error handling
When status is failed, read the error object:
{
"id": "video_xxx",
"object": "video",
"status": "failed",
"error": { "code": "content_policy_violation", "message": "..." }
}Common causes: the prompt tripped content moderation, a reference image was unreachable, or the requested duration / size combination is unsupported by that model. Parameter errors are returned as 400 at creation time and never enter the async flow. Full error codes are on the error handling page.