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.

5 min readSume
All posts

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.

Poll fields and what each can drive in a UI, from the Sume video docs (read 2026-10-08)
FieldAppearsUI use
statusalwayslabel and spinner state
modelwhen knowncaption (sume/auto stays sume/auto)
unsigned_urlscompleted jobsenable the download and preview
usage.costwhen an amount existsshow the cost of the clip
errorfailed jobsone 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.

  • pending means queued, in_progress means 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

All Developers posts

Written by Sume