No progress percent on the Sume video poll: status plus elapsed time
The poll has status, not a percentage. How to build an honest progress label from pending, in_progress and elapsed seconds, with a 30-second interval.

The Sume /v1/videos poll response has no progress percentage. It has status (pending, in_progress, completed, failed, cancelled) and, when a job is done, unsigned_urls. If a Sora-era UI drew a bar from a percent value, replace it with a status label and an elapsed-time counter that you keep yourself.
What the poll does return
The poll object carries id, generation_id, polling_url, status, model, and then unsigned_urls, usage and error when they apply. Nothing in it estimates how far along the render is. Sume also sends no progress webhooks: delivery is terminal events only, so a webhook cannot feed a bar either.
| Field | Appears | UI use |
|---|---|---|
| status | always | label and spinner state |
| model | when known | caption (sume/auto stays sume/auto) |
| unsigned_urls | completed jobs | enable the download and preview |
| usage.cost | when an amount exists | show the cost of the clip |
| error | failed jobs | one string for the error toast |
A label that stays true
Docs say video generation usually takes from 30 seconds to several minutes, depending on model, parameters and load. A fake percentage would mislead a user in that range, so map each status to a sentence and let the elapsed counter do the work of showing life.
The function below returns the text for a status and the seconds since you submitted. Call it from a one-second timer in the UI and from your 30-second poll.
type VideoStatus = "pending" | "in_progress" | "completed" | "failed" | "cancelled";
const LABEL: Record<VideoStatus, string> = {
pending: "Queued",
in_progress: "Rendering",
completed: "Ready",
failed: "Failed",
cancelled: "Cancelled",
};
export function progressLine(status: VideoStatus, startedAtMs: number): string {
const secs = Math.floor((Date.now() - startedAtMs) / 1000);
const mm = String(Math.floor(secs / 60)).padStart(2, "0");
const ss = String(secs % 60).padStart(2, "0");
return status === "completed" || status === "failed" || status === "cancelled"
? LABEL[status]
: `${LABEL[status]} ${mm}:${ss}`;
}Two states worth separate copy
pending and in_progress deserve different words because they tell the user different things. pending says the job is waiting for capacity, and a long wait there is normal when many jobs are queued. in_progress says the render has started. A user who sees Queued 03:10 understands that nothing is wrong; a user who sees a bar stuck at 40 percent does not.
When a job ends in failed, show the error string as returned. Sume maps raw provider wrappers to a public message before it reaches this field, so it is safe to display. For cancelled, there is no message, so write your own line, such as Cancelled before it finished.
Polling cadence
Poll no faster than the docs suggest. A 30-second interval gives ten GETs for a five-minute job, and the jobs surface throttles reads, so a tight loop gains nothing. See the SDK poll floor for the numbers on the SDK helper, and SSE or websocket for video progress for why neither is offered.
If you used the OpenAI Videos API before it was removed on 2026-09-24 (OpenAI deprecations, read 2026-10-08), you may have shown a percent from that API. There is no equivalent to copy over, so show the status line instead.
pendingmeans queued,in_progressmeans the render is running.- Stop the timer on any of the three terminal statuses.
- Never display a percentage you invented.
Sources
Related posts
More in Developers
- Node 26.11 isValidHeaderValue: check a Sume Idempotency-Key first
Node 26.11 adds http.isValidHeaderValue. Use it to reject a bad Idempotency-Key before POST /v1/images, with a fallback for older Node, and see its limits.
- Node 26.11 ships Undici 8.11.2: tell a Sume poll timeout from an abort
Catch TimeoutError separately from AbortError when a Sume status poll in Node fetch times out, and know which Sume calls are safe to repeat after that timeout.
- Node 26 enters LTS in October 2026: pin your Sume webhook receiver
Node 26 moves to LTS this month and Node 27 Alpha starts. Pin the runtime that runs your Sume webhook receiver and prove it with a signed self-test.
- node:test mock.method on fetch: test a Sume status poll offline
Node 26 goes LTS this month. Test a Sume job status poll with node:test and mock.method on fetch: four cases, no network, no key, no third-party test library.
Written by Sume