Overview
This page documents the Wan video generation API on LaoZhang. The API uses a DashScope-compatible asynchronous task flow: create a task, persist task_id, poll task status, then download the MP4 from result_url after completion.
Do not use the Sora / Veo /v1/videos endpoint for Wan. Wan image-to-video, reference-to-video, and video editing requests require the native DashScope input.media[] payload, so task creation must use /wan/api/v1/services/aigc/video-generation/video-synthesis.
Authentication
Create a dedicated token in Token Management:
| Setting | Value |
|---|
| Console entry | Token Management → Create token |
| Group | Wan |
| Billing mode | Pay-as-you-go / pay-per-use |
| Header | Authorization: Bearer YOUR_API_KEY |
| Recommendation | Use a dedicated Wan token so task logs and billing records can be audited by model and task |
Wan requests must use a Wan group token with pay-as-you-go billing enabled. Default, Veo, Sora, or other video groups can return unavailable-channel, model-routing, or billing-group errors.
Billing And Pricing
The table below uses the official upstream public pricing as a cost-estimation baseline. LaoZhang API billing is determined by the console model price and call logs; because of tax, FX, payment-channel, and upstream settlement costs, the LaoZhang API charge may be 0% - 10% above the official upstream list price.
Official reference: Alibaba Cloud Model Studio pricing.
| Request pattern | Official billing basis | Official 720P price | Official 1080P price |
|---|
| Text-to-video, or image-to-video with only image/audio input | Billed by successfully generated output-video seconds; failed tasks are not billed | 0.6 RMB/second | 1 RMB/second |
| Reference-to-video with input video | Input-video billable duration + output-video duration, billed by second | 0.6 RMB/second | 1 RMB/second |
| Video editing | Input-video duration + output-video duration, billed by second | 0.6 RMB/second | 1 RMB/second |
duration and resolution directly affect cost. Production clients should estimate cost before task creation and reconcile actual billing from console call logs after task completion.
Flow
Create task
Send POST /wan/api/v1/services/aigc/video-generation/video-synthesis with a JSON body. Set model to a Wan model ID, input.prompt to the prompt, and input.media[] for i2v, r2v, and video editing inputs.
Poll status
Send GET /v1/tasks/{task_id}. Client logic should branch on the top-level status field instead of upstream-specific nested fields.
Download result
When status=completed, download the top-level result_url. This is a signed object-storage URL; do not send the LaoZhang Authorization header to it.
API Reference
Request Conventions
| Setting | Value |
|---|
| Base URL | https://api.laozhang.ai |
| Authentication | Authorization: Bearer YOUR_API_KEY |
| Create request format | application/json |
| Required create header | X-DashScope-Async: enable |
| Polling interval | 5-10 seconds recommended |
| Client timeout | 20 minutes recommended |
Endpoints
| Purpose | Method | Path |
|---|
| Create video task | POST | /wan/api/v1/services/aigc/video-generation/video-synthesis |
| Poll task status | GET | /v1/tasks/{task_id} |
| Download video | GET | result_url returned by a completed task |
Status Machine
| Status | Terminal | Client action |
|---|
submitted | No | Task accepted, continue polling |
in_progress | No | Generation is running, continue polling |
completed | Yes | Read result_url and download MP4 |
failed | Yes | Read error.message or fail_reason and stop polling |
Wan / DashScope progress is coarse-grained. It is normal for progress to stay at 30% for a while and then jump to 100%.
| Model ID | Capability | Media input |
|---|
wan2.7-t2v | Text to video | Do not send media |
wan2.7-i2v | Image to video, optionally audio-driven | At least one first_frame; optional driving_audio |
wan2.7-r2v | Reference to video | One or more reference_image entries |
wan2.7-videoedit | Video editing | One video plus one or more reference_image entries |
wan2.6-t2v / wan2.6-i2v / wan2.6-r2v / wan2.6-r2v-flash | Wan 2.6 family | Same pattern as the matching Wan 2.7 capability |
happyhorse-1.0-t2v / happyhorse-1.0-i2v / happyhorse-1.0-r2v / happyhorse-1.0-video-edit | HappyHorse video models | Same pattern as the matching capability; media count depends on model limits |
wan2.7-image-pro is an image model, not a video-generation model for this endpoint.
Request Body
| Field | Type | Required | Notes |
|---|
model | string | Yes | Model ID, for example wan2.7-t2v |
input.prompt | string | Yes | Natural-language prompt |
input.media | array | Model-dependent | Omit for t2v; required for i2v, r2v, and video editing |
parameters.resolution | string | No | Common values: 480P, 720P, 1080P; use uppercase P |
parameters.duration | integer | No | Common values: 5 or 10; send an integer, not a string |
parameters.prompt_extend | boolean | No | Enables upstream prompt expansion |
parameters.watermark | boolean | No | Adds an AI-generated watermark |
parameters.seed | integer | No | Reproducibility seed; send an integer |
type | Purpose |
|---|
first_frame | First-frame image for image-to-video |
last_frame | Last-frame image, when supported by the selected model |
reference_image | Reference image for r2v or video editing |
driving_audio | Driving audio, commonly used with wan2.7-i2v |
video | Input video, commonly used with wan2.7-videoedit |
Media URLs must be publicly reachable HTTPS direct links. Login-only URLs, cookie-gated URLs, private network URLs, or temporarily inaccessible links can cause task failure.
Environment Variables
Examples below use:
export BASE_URL="https://api.laozhang.ai"
export API_KEY="YOUR_API_KEY"
Text To Video
curl -X POST "$BASE_URL/wan/api/v1/services/aigc/video-generation/video-synthesis" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "X-DashScope-Async: enable" \
--data-raw '{
"model": "wan2.7-t2v",
"input": {
"prompt": "A lighthouse at sunset, slow cinematic push-in, ocean waves hitting rocks, seabirds in the distance"
},
"parameters": {
"resolution": "720P",
"duration": 5,
"prompt_extend": true,
"watermark": true
}
}'
Image To Video
curl -X POST "$BASE_URL/wan/api/v1/services/aigc/video-generation/video-synthesis" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "X-DashScope-Async: enable" \
--data-raw '{
"model": "wan2.7-i2v",
"input": {
"prompt": "A graffiti character comes alive and performs energetic rap under a railway bridge at night",
"media": [
{
"type": "first_frame",
"url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250925/wpimhv/rap.png"
},
{
"type": "driving_audio",
"url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250925/ozwpvi/rap.mp3"
}
]
},
"parameters": {
"resolution": "720P",
"duration": 10,
"prompt_extend": true,
"watermark": true
}
}'
Reference To Video
curl -X POST "$BASE_URL/wan/api/v1/services/aigc/video-generation/video-synthesis" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "X-DashScope-Async: enable" \
--data-raw '{
"model": "wan2.7-r2v",
"input": {
"prompt": "A girl wearing the referenced dress walks slowly through a sunset garden with cinematic lighting",
"media": [
{
"type": "reference_image",
"url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20260402/fwjpqf/wan2.7-videoedit-change-clothes.png"
}
]
},
"parameters": {
"resolution": "720P",
"duration": 5,
"prompt_extend": true,
"watermark": true
}
}'
Video Editing
curl -X POST "$BASE_URL/wan/api/v1/services/aigc/video-generation/video-synthesis" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "X-DashScope-Async: enable" \
--data-raw '{
"model": "wan2.7-videoedit",
"input": {
"prompt": "Replace the girl's outfit in the video with the outfit shown in the reference image",
"media": [
{
"type": "video",
"url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20260403/nlspwm/T2VA_22.mp4"
},
{
"type": "reference_image",
"url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20260402/fwjpqf/wan2.7-videoedit-change-clothes.png"
}
]
},
"parameters": {
"resolution": "720P",
"prompt_extend": true,
"watermark": true
}
}'
Poll And Download
curl "$BASE_URL/v1/tasks/$TASK_ID" \
-H "Authorization: Bearer $API_KEY"
Completed tasks return status=completed and result_url. Client logic should rely on these top-level fields:
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"task_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"object": "task",
"platform": "wan",
"action": "text_to_video",
"task_type": "text_to_video",
"status": "completed",
"progress": "100%",
"result_url": "https://dashscope-xxx.oss-accelerate.aliyuncs.com/...",
"result": {
"data": {
"model": "wan2.7-t2v",
"parameters": {
"resolution": "720P",
"duration": 5,
"prompt_extend": true,
"watermark": true
}
}
}
}
curl -L -o wan-output.mp4 "$RESULT_URL"
Do not send the LaoZhang Authorization header when downloading result_url. It is a signed upstream object-storage URL and extra auth headers can cause 403 errors.
Minimal Python Client
import json
import time
import urllib.request
from urllib.error import HTTPError
BASE_URL = "https://api.laozhang.ai"
API_KEY = "YOUR_API_KEY"
def request(method, path, body=None, extra_headers=None):
headers = {"Authorization": f"Bearer {API_KEY}"}
if extra_headers:
headers.update(extra_headers)
data = None
if body is not None:
headers["Content-Type"] = "application/json"
data = json.dumps(body).encode("utf-8")
req = urllib.request.Request(BASE_URL + path, data=data, method=method, headers=headers)
try:
with urllib.request.urlopen(req, timeout=60) as resp:
return json.loads(resp.read().decode("utf-8"))
except HTTPError as exc:
error_body = exc.read().decode("utf-8", errors="replace")
raise RuntimeError(f"HTTP {exc.code}: {error_body}") from exc
created = request(
"POST",
"/wan/api/v1/services/aigc/video-generation/video-synthesis",
{
"model": "wan2.7-t2v",
"input": {"prompt": "A lighthouse at sunset, cinematic light, slow push-in"},
"parameters": {"resolution": "720P", "duration": 5, "prompt_extend": True},
},
{"X-DashScope-Async": "enable"},
)
task_id = created["output"]["task_id"]
while True:
task = request("GET", f"/v1/tasks/{task_id}")
if task["status"] == "completed":
# result_url is a signed download URL. Do not attach Authorization.
urllib.request.urlretrieve(task["result_url"], "wan-output.mp4")
break
if task["status"] == "failed":
raise RuntimeError(task.get("error") or task.get("fail_reason"))
time.sleep(10)
Troubleshooting
| Symptom | Likely cause | Fix |
|---|
未提供令牌 | Missing Authorization header | Send Authorization: Bearer $API_KEY |
Current group Wan has no available channels for model ... | Invalid model name or missing model route in the Wan group | Check the model ID or route configuration |
[InvalidParameter] Field required: input.media | Missing media for i2v/r2v/edit, or using the wrong /v1/videos endpoint | Use the Wan DashScope passthrough endpoint and send input.media[] |
任务不存在 | Wrong or expired task_id | Use the exact task_id returned by create |
| Download returns 403 | Signed result_url expired or extra auth header was sent | Re-poll the task for a fresh URL and download without Authorization |