Wan 3.0
Wan 3.0 API — up to 30 seconds from text, frames or reference media, with 480P through 4K output. Use content_filter to select moderated or legacy API access.
Alibaba's all-in-one reference video model. Wan 3.0 generates up to 30 seconds in a single pass from text, images, video, audio, documents, or a public web page, at 480P through 4K — with an audio track by default. See current pricing on the model page.
Content filtering and Playground
Use content_filter to select the behavior without changing the model id:
true: content filtering enabled; supports 480P, 720P and 1080P.falseor omitted: existing API behavior, including 2K, 4K, documents and web pages.
Playground shows a Content filter switch, enabled by default. API requests
can set content_filter explicitly. Playground checks submitted text and images at the supplied URLs
before video generation when filtering is enabled. If input review rejects the
request or is unavailable, no video task is created and no generation credits
are charged. This precheck does not inspect video or audio content and does not
apply to API-key requests. Existing
per-resolution prices stay the same. A filtered request never falls back to
an unfiltered request. Failed tasks are refunded.
For 2K or 4K, use the same model id with content_filter: false.
Quick example
curl https://reapi.ai/api/v1/videos/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "wan3.0-video",
"content_filter": true,
"prompt": "A lighthouse keeper climbing a spiral staircase at dawn",
"resolution": "720P",
"size": "16:9",
"duration": 10
}'import requests
resp = requests.post(
"https://reapi.ai/api/v1/videos/generations",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"model": "wan3.0-video",
"content_filter": True,
"prompt": "A lighthouse keeper climbing a spiral staircase at dawn",
"resolution": "720P",
"size": "16:9",
"duration": 10,
},
timeout=30,
)
print(resp.json())const r = await fetch("https://reapi.ai/api/v1/videos/generations", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "wan3.0-video",
content_filter: true,
prompt: "A lighthouse keeper climbing a spiral staircase at dawn",
resolution: "720P",
size: "16:9",
duration: 10,
}),
});
console.log(await r.json());package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]any{
"model": "wan3.0-video",
"content_filter": true,
"prompt": "A lighthouse keeper climbing a spiral staircase at dawn",
"resolution": "720P",
"size": "16:9",
"duration": 10,
})
req, _ := http.NewRequest("POST",
"https://reapi.ai/api/v1/videos/generations", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}Authentication
Every call needs a Bearer token. Generate keys at reapi.ai/settings/apikeys.
Authorization: Bearer YOUR_API_KEYEndpoint
POST /api/v1/videos/generations
GET /api/v1/tasks/{id}Submission is async. The POST returns immediately with an id; the task
endpoint returns the same envelope until completion. Polling does not consume
credits. Generation typically takes 1–5 minutes, longer for long clips.
Modes
There is no mode field — the model id is always wan3.0-video and the mode
follows from which media fields you send:
| Mode | Trigger |
|---|---|
| Text-to-video | prompt alone |
| First-frame video | one image in the frame family |
| First + last frame | two images in image_urls, or image_with_roles with first_frame / last_frame |
| Multi-modal reference | reference images / video_urls / audio_urls / audio_url |
| Document to video | file_url (prompt optional) |
| Web page to video | link_url (prompt optional) |
Media families
Every media input belongs to one of two families, and the two cannot be mixed in one request:
| Family | Members | Meaning |
|---|---|---|
| Frame | first_frame, last_frame | Strict first / last frame of the clip |
| Reference | reference_image, reference video, reference audio, document, web page | The model interprets the content freely |
A bare image_urls array is assigned as follows:
- If
generation_typeis set, it decides (frameorreference). - Otherwise, if the request already carries reference media (
video_urls,audio_urls,audio_url,file_url,link_url), the images are reference images. - Otherwise they are frame images: the first becomes
first_frame, the secondlast_frame.
Use image_with_roles when you want explicit control.
With content_filter: true, generation requires a text prompt (either prompt or a text part in content).
Document and web-page fields, and 2K/4K output, require content_filter: false.
content_filter: true supports 21:9 in addition to the aspect ratios below. Reference
video and audio each have a combined 15-second input limit. The moderated API forwards
additional parameters to the upstream; acceptance does not prove an extension
has an effect. Unsupported combinations may fail upstream and are refunded.
Request body
| Field | Type | Default | Notes |
|---|---|---|---|
model | string | — | wan3.0-video. Required. |
prompt | string | — | Scene, motion, camera, story beats. Required when content_filter: true; optional with media when false; max 20,000 characters. In reference mode address assets as Image 1 / Video 1 / Audio 1 (Chinese prompts: 图 1 / 视频 1 / 音频 1) — numbered per media type, in array order. |
image_urls | string[] | — | Public image URLs. Frame family (max 2) or reference images (max 10) per the rules above. |
image_with_roles | object[] | — | { "url": string, "role": "first_frame" | "last_frame" | "reference_image" }. Max 1 first_frame and 1 last_frame. |
video_urls | string[] | — | Reference clips, max 5; 1–15 s each, 15 s total. |
audio_urls | string[] | — | Reference audio, max 5; 1–15 s each, 15 s total. |
audio_url | string | — | Single reference audio — the single-value form of audio_urls. |
file_url | string | — | One reference document: docx, doc, xlsx, xls, pptx, ppt, pdf, txt, key, pages, numbers, md. Max 100 MB, 50 pages. Mutually exclusive with link_url. |
link_url | string | — | One public, login-free web page. Mutually exclusive with file_url. |
generation_type | string | — | frame or reference — how bare image_urls are classified. |
size | string | adaptive | adaptive / 16:9 / 4:3 / 1:1 / 3:4 / 9:16; content_filter: true also supports 21:9. |
resolution | string | 1080P | 480P / 720P / 1080P / 2K / 4K. Case-insensitive. |
duration | integer | 5 | Output seconds, 2–30, or -1 to let the model choose the length. |
audio | boolean | true | Whether the output carries an audio track. Does not change the price. |
content_filter | boolean | false for API | true: content filtering enabled; false or omitted: existing unfiltered API behavior. The legacy alias nsfw_checker remains accepted; content_filter takes precedence. Playground defaults to true. |
prompt_extend | boolean | true | When content_filter: true: expand the prompt before generation. |
watermark | boolean | false | When content_filter: true: request an output watermark. With content_filter: false, this field is accepted but ignored. |
content | object[] | — | When content_filter: true: optional native content parts (text, image_url, video_url, audio_url), with nested { "url": "https://…" } media and role. Appended before the media fields above; reference video seconds are billed. |
seed | integer | — | Reproducibility seed, 0–2147483647; content_filter: true also accepts -1 for random. |
No data: URIs. reAPI rejects base64 inputs platform-wide — every URL
field must be a public HTTP(S) URL. Upload to your own object storage (S3, R2,
OSS, …) and pass the URL.
Media limits
| Type | Limits |
|---|---|
| First / last frame | Max 1 each |
| Reference images | Max 10 |
| Reference video | Max 5 clips, 1–15 s each, 15 s total; mp4/mov; edge 240–4096 px, ratio ≤ 8:1, ≤ 100 MB |
| Reference audio | Max 5 clips, 1–15 s each, 15 s total; wav/mp3; ≤ 15 MB |
| Images | JPEG/JPG/PNG (no alpha) / BMP / WEBP; edge 240–8000 px, ratio ≤ 8:1, ≤ 20 MB |
| Documents | ≤ 100 MB, ≤ 50 pages |
| Web pages | Public, login-free URLs |
With reference video present, the total input video duration plus the output
duration must stay within 30 seconds — including when duration is -1.
Response envelope
Submit and poll share the same shape — only status and output fill in over
time.
{
"id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
"model": "wan3.0-video",
"status": "completed",
"created_at": 1735000000,
"output": {
"video_urls": ["https://cdn.reapi.ai/media/tasks/.../0.mp4"]
},
"error": null
}Poll GET /api/v1/tasks/{id} (see the Tasks reference)
until status === "completed". output.video_urls holds the generated MP4
URL.
Pricing
Billed per billable second, scaled by resolution. The mode does not change
the rate, and audio: true costs the same as audio: false.
billable_seconds = reference_video_seconds + duration
credits = ceil(per_second_usd × billable_seconds × 1000)where 1 credit = $0.001. Current per-second rates for each resolution tier
are on the model page — that table is
dynamic and always reflects the live rate. Failed jobs are refunded
automatically.
Three things drive the bill more than anything else:
- Resolution. Omitting
resolutiongenerates and bills at1080P. Pass480Por720Pexplicitly when cost matters. - Reference video. Every clip in
video_urlsis processed as well as generated, so its own length is billable on top ofduration. reAPI measures the clips server-side at submit time, and their combined length withdurationis capped at 30 seconds. A 6-second reference clip withduration: 8bills 14 seconds. Reference images, audio, documents and web pages carry no billable length — only video does. A clip reAPI cannot read is rejected rather than billed as zero. duration: -1. The model chooses the length, so the final second count is not knowable at submit time. reAPI charges the 30-second ceiling for these requests. Pass an explicitdurationwhenever you can.
Errors
Invalid combinations are rejected before any generation is billed.
| Code | When |
|---|---|
400 invalid request | Frame and reference media mixed; both file_url and link_url; duration outside 2–30 and not -1; unsupported resolution; more than 10 reference images; neither prompt nor media |
401 unauthorized | Missing or invalid API key |
402 insufficient credits | Balance below the estimated charge |
429 rate limited | Too many requests |
Full catalog: Errors.
Tips
- Keep the frame family and the reference family apart. If you want a specific still to open the clip and a character carried across shots, the frame role wins — send the character as the first frame, not as a reference image.
generation_typeis worth setting explicitly wheneverimage_urlsis present alongside any other media. The inference rules are well-defined, but a stated role is easier to reason about six months later.- In reference mode, name the assets in the prompt (
Image 1,Video 1,Audio 1). Indices count within each media type, not across all of them. sizeonly frames the output; with a first-frame image the source aspect ratio dominates the result.- Long clips take proportionally longer. A 30-second 1080P request can sit well past the 5-minute mark — set your poll timeout accordingly.