Sora polling loop ported: Sume statuses and a 30-second poll

Sora's guide polled every 10 to 20 seconds for queued, in_progress, completed, failed. Sume's jobs read pending, in_progress, completed, failed, cancelled.

4 min readSume
All posts

Port a Sora polling loop to Sume by changing three things: the status names, the poll interval and the place the file comes from. Sume's /v1/videos jobs report pending, in_progress, completed, failed or cancelled, the docs suggest a 30-second interval, and the video is read from unsigned_urls once the job is completed.

OpenAI's guide, read 2026-10-01, listed the states queued, in_progress, completed and failed, suggested polling at 10 to 20 second intervals, and offered video.completed and video.failed webhooks. The API was shut down on 2026-09-24.

How do the statuses map?

Sora guide states versus Sume job statuses, read 2026-10-01.
SoraSumeDo this
queuedpendingkeep polling
in_progressin_progresskeep polling
completedcompleteddownload unsigned_urls[0]
failedfailedread the error field
(none)cancelledstop; the job was canceled

How often should I poll?

Sume's best-practice note suggests about 30 seconds, and says video generation typically takes 30 seconds to several minutes. A tighter Sora-style interval adds requests without finishing sooner. To skip polling, pass an HTTPS callback_url; Sume POSTs its standard job webhook envelope when the job reaches a terminal state, signed with x-sume-webhook-signature. Field details are in the video docs.

What does the ported loop look like?

Submit, then poll the polling_url from the response. This Python runs as written with SUME_API_KEY set.

import os
import time

import requests

headers = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
job = requests.post(
    "https://api.sume.com/v1/videos",
    headers=headers,
    json={"model": "wan-3.0", "prompt": "A paper boat on a rainy street",
          "duration": 4, "resolution": "480p"},
    timeout=60,
).json()

while True:
    time.sleep(30)
    status = requests.get(job["polling_url"], headers=headers, timeout=60).json()
    print(status["status"])
    if status["status"] == "completed":
        print(status["unsigned_urls"][0])
        break
    if status["status"] in ("failed", "cancelled"):
        print(status.get("error"))
        break

Sources

Related posts

More in Developers

All Developers posts

Written by Sume