Vidu task states mapped onto Sume job statuses in Python
Map Vidu task states (created, queueing, processing, success, failed) to Sume queued, processing, completed and failed so an old poller keeps working.

Vidu's task detail endpoint reports five states, and Sume's job status endpoint reports five statuses, so a poller written for Vidu can read Sume jobs with a small lookup table. The one gap is that Sume also has canceled, which the Vidu page does not list.
Vidu Q4 itself is not listed in the Sume Video Router catalog (catalog read 2026-10-09), so this post is about porting the polling code, not about calling Vidu through Sume.
How do the two state sets line up?
The left column is what the Vidu page documents for its task endpoint. The right column is the sume_status field that Sume returns on GET /v1/jobs/{id}/status.
| Vidu state | Sume sume_status | Terminal |
|---|---|---|
| created | queued | No |
| queueing | queued | No |
| processing | processing | No |
| success | completed | Yes |
| failed | failed | Yes |
| (not listed) | canceled | Yes |
What does the adapter look like?
Keep your loop and swap the fetch function. It returns a Vidu-shaped state, and it refuses to guess about canceled jobs.
import os, requests
FROM_SUME = {"queued": "queueing", "processing": "processing",
"completed": "success", "failed": "failed"}
def vidu_shaped_state(job_id):
r = requests.get(
f"https://api.sume.com/v1/jobs/{job_id}/status",
headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"},
timeout=30,
)
r.raise_for_status()
data = r.json()["data"]
if data["sume_status"] == "canceled":
raise RuntimeError("job canceled; Vidu has no state for this")
return FROM_SUME[data["sume_status"]], data["next_poll_after_seconds"]
print(vidu_shaped_state(os.environ["JOB_ID"]))What about error codes and credits?
Vidu returns err_code and credits on the task. Sume does not copy those names. A failed job carries an error object with category, stage, retryable and public_reason, and a completed /v1/videos job carries usage.cost in USD. Read them from GET /v1/jobs/{id} instead of translating codes one by one.
Vidu also lets you pass a payload string that comes back with the task. Sume's /v1/videos route has no such field, so key your own records on the Idempotency-Key you sent, which the job list returns in its idempotency_key column.
What do I use on Sume today for reference-driven video?
Since Vidu Q4 is not listed, the listed models that take references are the ones to test. The Video Router docs describe seedance-2.5 (4 to 30 seconds at 480p, 720p and 1080p) and gemini-omni-flash-1.1 (3 to 10 seconds up to 4K, with always-on audio), and each model's capabilities object says which reference types it accepts. Read GET /v1/video-router/models before you choose, because the catalog is the source of truth, not a blog post.
Which sleep should the loop use?
Use next_poll_after_seconds while the job is not terminal. It is null once the job is terminal, which is the signal to stop. Do not resubmit a paid job because a local timer expired.
Sources
Related posts
More in Developers
- 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.
- 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.
Written by Sume