Vidu, Wan 3.0 and Sume job states in one poller
Vidu says created/queueing/processing/success/failed, Wan says PENDING/RUNNING/SUCCEEDED/FAILED, Sume says pending/in_progress/completed. One mapping table.

If you poll more than one video API, normalize the state names once and branch on your own words. Vidu Q4 Preview reports created, queueing, processing, success or failed; Alibaba's Wan 3.0 reports PENDING, RUNNING, SUCCEEDED or FAILED; a Sume /v1/videos job reports pending, in_progress, completed, failed or cancelled.
Which state names does each API use?
Both vendor lists come from their own API pages. The Sume list comes from the video generation docs.
| Meaning | Vidu Q4 Preview | Wan 3.0 (Model Studio) | Sume /v1/videos |
|---|---|---|---|
| Accepted, not started | created, queueing | PENDING | pending |
| Generating | processing | RUNNING | in_progress |
| Done, file available | success | SUCCEEDED | completed |
| Failed | failed | FAILED | failed |
| Canceled before start | not listed on the page | not listed on the page | cancelled |
Why is the spelling worth a mapping table?
Sume has two vocabularies. The video endpoint says pending and in_progress. The generic jobs endpoint, GET /v1/jobs/:id/status, lists queued and processing as non-terminal and completed, failed and canceled as terminal (one l). A poller written for one will spin forever on the other if it only checks for completed.
What does the mapping look like in code?
Keep the raw value for logs and branch on the normalized one. Unknown strings fall through unchanged, so a new vendor state does not crash the loop.
NORMAL = {
"created": "pending", "queueing": "pending", "queued": "pending",
"processing": "in_progress", "in_progress": "in_progress",
"success": "completed", "completed": "completed",
"failed": "failed",
"canceled": "cancelled", "cancelled": "cancelled",
"PENDING": "pending", "RUNNING": "in_progress",
"SUCCEEDED": "completed", "FAILED": "failed",
}
DONE = {"completed", "failed", "cancelled"}
def normalize(raw):
return NORMAL.get(raw, raw)
for raw in ["queueing", "RUNNING", "success", "cancelled", "weird"]:
s = normalize(raw)
print(raw, "->", s, "stop" if s in DONE else "keep polling")Which state should end the loop?
Stop on any terminal value: completed, failed or cancelled. Read the download URL only after completed; the video generation docs list the job statuses and what each one means.
Sources
Related posts
More in Developers
- waitForRun or waitForJob? Pick by which Sume endpoint made the id
A Sume run id cannot be read as a job id. Which create endpoint made your id decides waitForRun or waitForJob, with a TypeScript example of each.
- Wan 3.0 says 30 fps MP4: check your Sume download with ffprobe
Alibaba says Wan 3.0 outputs 30 fps MP4. Sume's docs do not repeat it, so probe your download. A Python ffprobe script for fps, size, length and audio.
- Wan 3.0 duration -1 (smart length) vs Sume's whole seconds
Alibaba lets Wan 3.0 pick the length with duration -1. Sume's duration is a whole number from 2 to 30 for wan-3.0, so choose it before you pay for it.
- Wan 3.0 'Image 1' and 'Audio 1' prompt labels on Sume
Alibaba says to name references 'Image 1', 'Video 1', 'Audio 1' in the prompt. How Sume's input_references order maps to those labels, and a cheap test.
Written by Sume