
A client that re-sends the create call on every timeout does not fail loudly. In the worked example below it adds $900 to a $4,000 month of Wan3.0 video, 22.5% of the bill, and no log line looks broken. The API is fine. The integration is the bill.
NAIVE CLIENT PRODUCTION CLIENT
create -> wait -> timeout reserve budget -> create once
-> create again (2 tasks) store task_id before anything else
poll until done poll every 15 s, retry by status
use video_url when needed archive the MP4 inside 24 hours
settle actual seconds to the team
leak: $900 on $4,000 (22.5%) leak: designed to be $0
Every generated second should be reserved before it is requested and accounted for after it is made.
In this guide
- A five-part architecture for any async video generation API: intake, job store, submitter, poller, archiver
- A fix for the orphan task, the billed generation your system never recorded
- A retry table by task status and a rate-limit budget that accounts for polling
- Per-team spend caps with worked math: reserve, submit, settle
Wan3.0 does not answer in the same HTTP request that asks for the video.
The Wan3.0 Video Generation API Reference is explicit: you create a task with the X-DashScope-Async: enable header, receive output.task_id, then query the task until output.task_status reaches a final state (Alibaba Cloud Model Studio, Wan3.0 Video Generation API Reference, accessed Nov 13, 2026). The reference suggests polling about every 15 seconds. Task IDs and the returned video_url are valid for 24 hours, after which the video is purged.
That contract has three consequences for a platform team:
So the unit of work is a job record with a lifecycle, not an API call. Article 06 in this series follows a video team's pipeline and review gates; this article is the code layer underneath, written for the engineer who owns it.
Wiring Wan3.0 into an internal tool this quarter? Walk through your task states, polling and archive path with the Wan team before the first producer gets an API key: Map your job states before launch →
Model the job, not the call.
Five components, each with one job, keep the integration boring.
[Intake API] -> [Job store + spend ledger]
|
[Submitter] --(rate limiter)--> POST video-synthesis
|
[Poller] --(every 15 s)------> GET tasks/{task_id}
|
[Archiver] -> object storage + checksum + usage.duration
| Component | Owns | Writes to the job record |
|---|---|---|
| Intake API | Validating the request, assigning the idempotency key | key, team, model, resolution, duration, prompt hash |
| Job store and ledger | The single source of truth; reservations per team | state, reserved amount, settled amount |
| Submitter | The only code path allowed to call create |
task_id, request_id, submitted time |
| Poller | Querying status on an interval, classifying results |
task_status, code, message
|
| Archiver | Copying the MP4 before expiry, settling cost | storage path, checksum, usage.duration
|
Five components for a Wan3.0 integration; field names in code style come from the API reference. (Wan.)
Only the submitter can spend money. Product code never calls create directly; it inserts a job and walks away.
One code path spends; every other path reads.
The most expensive bug in a video generation API integration is invisible.
I call it the orphan task: a generation the provider created, and can bill, whose task_id your system never recorded. The create call succeeds on the server, the response never reaches your code, and a retry creates a second task for the same take.
The reference itself says it plainly: "Do not create duplicate tasks. Instead, use polling to retrieve the result." The reference documents no idempotency field on the create request, so the guarantee has to live on your side.
# Intake: one key per intended take
key = hash(team_id, brief_id, take_no, model, resolution, duration, prompt)
INSERT job(key, state='QUEUED', ...) # unique index on key
ON CONFLICT(key): return existing job # a retry from the caller is a no-op
# Submitter
job = claim_one(state='QUEUED') # row lock, so one worker wins
set job.state = 'SUBMITTING' # written BEFORE the network call
resp = POST create(headers: X-DashScope-Async=enable,
body: {model, input: {prompt},
parameters: {resolution, duration}})
if resp has output.task_id:
job.task_id = resp.output.task_id
job.request_id = resp.request_id
job.state = 'POLLING'
elif resp is a definite rejection (code + message returned):
job.state = 'REJECTED'; release reservation
else: # timeout, reset, no body
job.state = 'UNCERTAIN' # never auto-resubmit
The UNCERTAIN state is the honest part. If you cannot know whether a task was created, do not guess by creating another.
Park, alert, decide. Park the job, alert its owner, and let a person decide. A stuck job costs one manual decision; a blind resubmit may cost a second billed generation.
When the create call's outcome is unknown, stop: never pay twice to find out.
Each task status deserves its own action.
The reference lists six: PENDING, RUNNING, SUCCEEDED, FAILED, CANCELED and UNKNOWN.
| Status | Meaning for your job | Action | Re-create the task? |
|---|---|---|---|
| PENDING / RUNNING | Work in progress | Poll again in 15 s | No |
| SUCCEEDED |
video_url returned |
Hand to the archiver now | No |
| FAILED | Generation did not complete | Read code and message; classify |
Only if the class is transient, once |
| CANCELED | Task ended without output | Return to owner | No, unless a person re-queues it |
| UNKNOWN | Task not found or expired | Check task age against 24 h | No; route to UNCERTAIN review |
| Network error on the query | Your call failed, not the task | Back off and query again | Never |
Retry policy by Wan3.0 task status. (Wan.)
Two rules carry most of the value:
task_id; re-creating would be an orphan by another name.Billing check. Before you set your retry budget, check in the billing console how failed tasks are treated for your account.
on poll_result(job, r):
if r.output.task_status in ('PENDING', 'RUNNING'): schedule(job, 15s)
elif r.output.task_status == 'SUCCEEDED': enqueue_archive(job, r)
elif r.output.task_status == 'FAILED' and transient(r.code) and job.retries == 0:
job.retries += 1; new_attempt(job) # new key suffix, new reservation
else: close(job, r.code, r.message); release_unspent(job)
Retry the network forever, the task once, and the input never.
Wan3.0 publishes a limit of 300 requests per minute for both wan3.0-video and wan3.0-video-prime (Model Studio model pages, accessed Nov 13, 2026). Run your limiter well under it, for example at 80%: 300 x 0.8 = 240 requests per minute.
Then ask a question most teams skip: do your status queries count toward the same budget? Confirm it for your account. If they do, polling becomes the largest consumer, and I call that the polling tax.
Assumptions (illustrative). Limiter at 240 requests per minute; a 15-second poll interval means 60 / 15 = 4 queries per minute per task in flight. For the math only, assume a task stays in flight 5 minutes; measure yours.
Queries per created task = 4 per minute x 5 minutes = 20
Requests per created task = 1 create + 20 queries = 21
Sustainable creates / minute = 240 / 21 = 11.4
A 500-job batch drains in = 500 / 11.4 = about 44 minutes
If queries do not count = 240 creates / minute = about 2 minutes
Result: under these assumptions, polling is 20 of every 21 requests. Do not shorten the interval below the suggested 15 seconds to "speed things up"; it only spends the budget faster.
Three practices keep bursts from hurting:
Spend your request budget on creates; spend your patience on polls.
The returned video_url is valid for 24 hours and then purged, so the archive step belongs in the poller's success path, not in someone's afternoon.
usage.duration and the file's actual length (with a video input, usage.duration also counts the input seconds). A job is only DONE when the archive copy exists.If it is not in your storage, you do not own it yet.
Spending decisions now sit with business teams: more than 80% of AI spending now sits outside enterprise IT (BCG, Applied AI Index 2026, September 2026). A shared Wan3.0 key with one monthly invoice cannot tell you which team spent what. The ledger can.
The loop is reserve, submit, settle:
usage.duration x price, and release the difference.When duration is set to -1 (smart duration mode), reserve the maximum, 30 seconds, and let settlement return the rest.
Prices below are Alibaba Cloud Model Studio list prices, Singapore region, per generated second (accessed Nov 13, 2026): wan3.0-video $0.05 / $0.10 / $0.20 and wan3.0-video-prime $0.068 / $0.14 / $0.28 at 480P / 720P / 1080P.
| Team | Monthly cap | Default model and resolution | Price per second | Reserve per 10 s job |
|---|---|---|---|---|
| Growth marketing | $2,000 | wan3.0-video, 720P | $0.10 | $1.00 |
| Ecommerce catalog | $1,500 | wan3.0-video, 480P | $0.05 | $0.50 |
| Brand finals | $1,000 | wan3.0-video-prime, 1080P | $0.28 | $2.80 |
Example per-team caps and reservations; smart duration on brand finals reserves 30 x $0.28 = $8.40. (Wan.)
Worked example: what the controls are worth. Assumptions (illustrative): 4,000 jobs a month, 10 seconds each, wan3.0-video at 720P; every duplicate task completes and is billed like any other.
Intended spend: 4,000 jobs x 10 s x $0.10 = $4,000
Orphan tasks: 4% of creates time out = 160 jobs,
each re-created twice = 320 tasks
320 x 10 s x $0.10 = $320
Expired URLs: 2% of outputs missed the 24 h window,
regenerated: 80 x 10 s x $0.10 = $80
Runaway script: one 500-job batch re-run by mistake
500 x 10 s x $0.10 = $500
------
Leak without controls: $320 + $80 + $500 = $900
Leak as share of intended spend: $900 / $4,000 = 22.5%
Result: idempotency removes the $320, archiving removes the $80, and a team cap stops the $500 re-run at the cap instead of on the invoice. Alert each team at 80% of its cap and pause non-final work at 100%.
Find the leak in your own integration
Send your monthly job count, average duration, resolution mix and how your client handles timeouts today. The Wan team will walk through your orphan-task exposure, rate-limit budget and per-team caps with you. Price your Wan3.0 integration leaks →
Reserve before you request, settle after you archive.
Not every Wan3.0 user needs a queue, a ledger and an archiver.
UNCERTAIN jobs and straggler alerts. If no engineer owns it, a creative tool built on top of the API is the better buy. The build-or-partner reasoning is the same one we broke down in Build vs. Buy, or Both? The Enterprise AI Decision.Build the queue when the volume, the teams or the money demand it, not before.
A one-week plan for a single engineer:
task_id and request_id before anything else.usage.duration, page on anything unarchived after 12 hours.Prices and rate limits are on the wan3.0-video and wan3.0-video-prime pages; durations from 2 to 30 seconds and 30 fps MP4 output are on the Video generation overview; request and response fields are in the Wan3.0 Video Generation API Reference. Plan at list price; promotions vary by platform and change over time.
Week one is plumbing; every week after is cheaper because of it.
Key takeaways
- Kill the orphan task. The create call has no documented idempotency field, so keys, a SUBMITTING state and an UNCERTAIN lane must live in your job store.
- Respect the clocks. Poll about every 15 seconds, archive inside the 24-hour window, and budget the 300 requests per minute for polls as well as creates.
- Cap spend per team in the ledger. Reserve, submit, settle: in the worked example, controls close a $900 leak on a $4,000 month.
Bring your integration; leave with a hardened job lifecycle
Tell us where Wan3.0 calls happen in your stack today and which teams share the key. The Wan team will review your queue, retry policy, archive path and spend caps with you, mapped to the fields in the API reference. Get your Wan3.0 queue and caps reviewed →
See Wan3.0 in action at wan.video.
About Wan. Wan is Alibaba Cloud's generative video model family. Wan3.0 is available through Alibaba Cloud Model Studio and Qwen Cloud, with API pricing billed per generated second.
Sources: BCG, Applied AI Index 2026 (September 2026); Alibaba Cloud Model Studio, Wan3.0 Video Generation API Reference, https://www.alibabacloud.com/help/en/model-studio/wan3-video-generation-api-reference (accessed Nov 13, 2026); Alibaba Cloud Model Studio, wan3.0-video model page, https://www.alibabacloud.com/help/en/model-studio/wan3-0-video (accessed Nov 13, 2026); Alibaba Cloud Model Studio, wan3.0-video-prime model page, https://www.alibabacloud.com/help/en/model-studio/wan3-0-video-prime (accessed Nov 13, 2026); Alibaba Cloud Model Studio, Video generation overview, https://www.alibabacloud.com/help/en/model-studio/video-generation (accessed Nov 13, 2026).
By Johnny Mai, Director, Gen AI Product Strategy & GTM.
Disclaimer: This post is provided for general information only. Worked examples are illustrative and use stated assumptions; your costs will vary. Prices are Alibaba Cloud Model Studio list prices for the Singapore region as published in November 2026, vary by region, and may change over time. Figures from third-party research (BCG 2026) are quoted as published in those reports and are not independently verified by WAN or Alibaba Cloud. Product and service availability, features, and program terms vary by region and may change over time. Nothing in this post constitutes professional, legal, or investment advice. © 2026 WAN. All rights reserved.
Batch vs. Real-Time Inference: Which Workloads Should Wait for Half Price
21 posts | 2 followers
FollowJohnny Mai - October 7, 2026
Johnny Mai - October 7, 2026
Johnny Mai - August 27, 2026
Alibaba Cloud Community - August 13, 2026
Johnny Mai - October 7, 2026
Alibaba Cloud Community - August 7, 2026
21 posts | 2 followers
Follow
Image Search
An intelligent image search service with product search and generic search features to help users resolve image search requests.
Learn More
CT Image Analytics Solution
This technology can assist realizing quantitative analysis, speeding up CT image analytics, avoiding errors caused by fatigue and adjusting treatment plans in time.
Learn More
API Gateway
API Gateway provides you with high-performance and high-availability API hosting services to deploy and release your APIs on Alibaba Cloud products.
Learn More
Architecture and Structure Design
Customized infrastructure to ensure high availability, scalability and high-performance
Learn MoreMore Posts by Johnny Mai