Alibaba's Wan 3.0 all-in-one video model: one model name covers text-to-video, first-frame and first+last-frame image-to-video, and omni-reference generation from up to 10 reference images, 5 reference video clips and 5 audio clips — or straight from a PPTX / DOCX / XLSX / PDF or a public web page. Output is a native single shot up to 30 seconds at 30fps with a synced audio track. Billing is per OUTPUT second; every reference file you send in is free. It runs on the same unified video endpoint as VEO, Kling and Seedance, so switching models is a one-string change and one API key covers everything — with no Alibaba Cloud account and no mainland real-name verification needed.
| Model / resolution | Rate | 5s | 10s | 30s |
|---|---|---|---|---|
| wan-3.0-video · 480P | $0.0596/s | $0.30 | $0.60 | $1.79 |
| wan-3.0-video · 720P | $0.1191/s | $0.60 | $1.19 | $3.57 |
| wan-3.0-video · 1080P | $0.2382/s | $1.19 | $2.38 | $7.15 |
| wan-3.0-video-prime · 480P | $0.0893/s | $0.45 | $0.89 | $2.68 |
| wan-3.0-video-prime · 720P | $0.1787/s | $0.89 | $1.79 | $5.36 |
| wan-3.0-video-prime · 1080P | $0.3574/s | $1.79 | $3.57 | $10.72 |
POST /api/v1/video/generations — async: create, then poll the same endpoint for the result.
# Step 1: Create task (text-to-video)
curl -X POST https://api.apimodels.app/v1/video/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "wan-3.0-video",
"prompt": "A paper airplane gliding over a calm lake at sunrise, camera drifting alongside",
"resolution": "720P",
"ratio": "16:9",
"duration": 5
}'
# Omni-reference: address materials positionally in the prompt
curl -X POST https://api.apimodels.app/v1/video/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "wan-3.0-video",
"prompt": "The person in video 1 picks up the object from figure 2 and places it on the table",
"reference_image_urls": ["https://example.com/object.png"],
"reference_video_urls": ["https://example.com/person.mp4"],
"resolution": "720P",
"duration": 8
}'
# Document to video: feed a deck straight in
curl -X POST https://api.apimodels.app/v1/video/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "wan-3.0-video",
"prompt": "A polished product launch film based on this deck",
"file_url": "https://example.com/launch-deck.pptx",
"resolution": "1080P",
"duration": 10
}'
# Step 2: Poll status
curl "https://api.apimodels.app/v1/video/generations?task_id=TASK_ID" \
-H "Authorization: Bearer YOUR_API_KEY"| Mode | What you send |
|---|---|
| Text to video | prompt only |
| First / first+last frame | first_frame_url [+ last_frame_url] |
| Omni reference | reference_image_urls / reference_video_urls / reference_audio_urls |
| Document / web to video | file_url or link_url |
⚠️ Frame mode (first_frame_url / last_frame_url) and reference mode (reference_* / file_url / link_url) are mutually exclusive — mixing them makes upstream fail the task, so we reject it locally first and name both colliding sides. file_url and link_url are likewise one or the other.
In omni-reference mode the prompt addresses materials positionally — "figure 1", "figure 2", "video 1", "audio 1", with images, videos and audio numbered independently. For example: "the person in video 1 holds the object from figure 3 and plays guitar on the chair from figure 4." That is how several characters, props and environments stay consistent inside one shot.
| Field | Required | Type | Description |
|---|---|---|---|
| model | Yes | string | "wan-3.0-video" or "wan-3.0-video-prime" (high-speed tier, ~6x faster measured, 50% higher rate) |
| prompt | No | string | Text description. Send at least one of prompt / reference material; up to 20,000 characters |
| first_frame_url | No | string | First frame, used strictly as frame one. Mutually exclusive with reference material |
| last_frame_url | No | string | Last frame, used strictly as the final frame |
| reference_image_urls | No | string[] | Reference images, up to 10. Addressed in the prompt as "figure 1", "figure 2", … |
| reference_video_urls | No | string[] | Reference videos, up to 5 clips, 1-15s each and 15s total |
| reference_audio_urls | No | string[] | Reference audio, up to 5 clips, 15s total (wav / mp3) |
| file_url | No | string | Document: docx/doc/xlsx/xls/pptx/ppt/pdf/txt/key/pages/numbers/md, ≤50 pages and ≤100MB. Mutually exclusive with link_url |
| link_url | No | string | Public web page URL (must be readable without login) |
| resolution | No | string | "480P" / "720P" / "1080P". ⚠️ We default to 720P when omitted (Alibaba defaults to 1080P, which costs double) |
| ratio | No | string | "adaptive" (default — inferred from your inputs), "16:9", "4:3", "1:1", "3:4", "9:16" |
| duration | No | number | 2-30 seconds, default 5; pass -1 for smart duration (the model chooses). With reference video: input video length + output length must stay within 30s |
| audio | No | boolean | Whether the output carries an audio track, default true. Turning it off does not reduce the price |
| prompt_extend | No | boolean | Smart prompt rewriting, default true. Helps short prompts noticeably but adds latency |
| seed | No | number | Random seed, 0-2147483647, for reproducible results |
| watermark | No | boolean | Whether to add a watermark, default false |
| callback_url | No | string | Webhook URL called when the task completes |
The create call returns data.taskId right away and the video renders in the background. GET the same endpoint with that task_id and read data.state: pending means still running, completed puts the MP4 URL in data.resultUrls[0], and failed puts the reason in data.failMsg. To skip polling, pass callback_url and we POST you when the task finishes.