Sume /v1/videos says cancelled, /v1/jobs says canceled: a status map
Two spellings and two vocabularies for the same Sume job: pending to cancelled on /v1/videos, queued to canceled on /v1/jobs. A table and a TypeScript mapping.

The same Sume video job reads differently on its two surfaces. GET /v1/videos/{jobId} uses pending, in_progress, completed, failed, and cancelled, with two l's. GET /v1/jobs/{id}/status uses queued, processing, completed, failed, and canceled, with one. A client that checks status === "canceled" against the videos endpoint never matches.
The Video generation page says you can also see the same job at /v1/jobs/{id}/status and /v1/jobs/{id}/result. Mixing the two is where the spelling bites.
The map
The first two columns come from the Video generation page and the Jobs and results page, read 2026-10-09.
| /v1/videos/{jobId} | /v1/jobs/{id}/status (`sume_status`) | Queue-shaped `status` |
|---|---|---|
pending | queued | IN_QUEUE |
in_progress | processing | IN_PROGRESS |
completed | completed | COMPLETED |
failed | failed | FAILED |
cancelled | canceled | CANCELED |
Normalize once
Pick one vocabulary for your own code and convert at the edge. The snippet maps the videos spelling to the jobs one, and treats anything unknown as an error so a new value does not pass silently.
const fromVideos = {
pending: "queued",
in_progress: "processing",
completed: "completed",
failed: "failed",
cancelled: "canceled",
} as const;
export type JobStatus = (typeof fromVideos)[keyof typeof fromVideos];
export function normalize(videoStatus: string): JobStatus {
const mapped = (fromVideos as Record<string, JobStatus>)[videoStatus];
if (!mapped) throw new Error(`unknown video status: ${videoStatus}`);
return mapped;
}
export const isTerminal = (s: JobStatus) =>
s === "completed" || s === "failed" || s === "canceled";Downloading the result
On /v1/videos, a completed job lists unsigned_urls, and GET /v1/videos/{jobId}/content?index=0 downloads the output. The OpenAPI description says the content endpoint redirects to the generated video, and that a job that terminally failed answers 409 job_failed with the public reason, not the retryable job_not_completed. So a 409 job_not_completed there means keep polling, and a 409 job_failed means stop and read the error.
If the job id is stored, either surface works for status. On the jobs side the envelope also gives terminal, result_ready, and next_action, so a client that only needs to know when to stop can use those and ignore the spelling entirely.
A note on the third column
The status endpoint also returns a queue-shaped status for clients that come from other queue APIs: IN_QUEUE, IN_PROGRESS, COMPLETED, FAILED, and CANCELED. The docs say it maps one to one to sume_status and that you should not mix the two in one check. These follow the one-l spelling. The two-l spelling belongs only to /v1/videos.
A failed job is the same job on every surface. Only the label differs. The error object and the request_id are what you should log, not the status string.
When you write tests, add one case per row of the table, including the unknown-value case, so a future status does not turn into a silent hang in your poll loop. The mapping function above already throws on a value it does not know, so the test for that case is one line.
Sources
Related posts
More in Developers
- Vidu 24-hour and FLUX 3 signed result links: copy the file first
Vidu result URLs last 24 hours and FLUX 3 signed URLs about 2 hours, or about 10 minutes by another line. Stream the Sume clip to disk and keep the job id.
- Vidu 540p has no Sume value: map Vidu resolution names
Vidu Q4 Preview offers 540p, 720p, 1080p, 2K and 4K. Sume's documented values are 480p, 720p, 768p, 1080p, 1K, 2K and 4K, per model. A lookup that fails loudly.
- Vidu 'Authorization: Token' vs Sume 'Bearer': one HTTP client
Vidu wants 'Authorization: Token <key>'; Alibaba Model Studio and Sume want 'Bearer <key>'. A small header helper for a ported client.
- Vidu is_rec and Wan prompt_extend: prompt rewrite vs Sume
Vidu's is_rec and Alibaba's prompt_extend can rewrite your prompt. Sume's documented video fields have no such switch. How to drop them and compare results.
Written by Sume