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.

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 | Sume | Do this |
|---|---|---|
| queued | pending | keep polling |
| in_progress | in_progress | keep polling |
| completed | completed | download unsigned_urls[0] |
| failed | failed | read the error field |
| (none) | cancelled | stop; 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"))
breakSources
Related posts
More in Developers
- Sora remix and edits ended: edit a video with Gemini Omni Flash
Sora's remix, then its edits endpoint, went away with the Videos API on 2026-09-24. On Sume, send video_url and an edit prompt to gemini-omni-flash-1.1.
- Sora extensions to 120 seconds: 30-second clips and Timeline
Sora's Videos API let you extend a clip up to 6 times, 120 seconds in all, and shut down 2026-09-24. On Sume, chain 30-second clips and join them in Timeline.
- Sume editing tool source limits: 1,800 s and 300 s
Video trim, audio detach and video inspect accept a source up to 1,800 seconds. Video filter, Timeline compose and video frames stop at 300 seconds.
- Spotify HDR video podcast: tone-mapped to SDR Rec.709
Spotify converts HDR (Rec.2100) uploads to SDR Rec.709. A Sume exact trim re-encodes to yuv420p and has no colour fields, so tone-map before you trim.
Written by Sume