Replace videos.create_and_poll with a requests helper on Sume
The OpenAI Python SDK's create_and_poll and download_content have no Sume twin. Here is a 25-line requests helper with the same call shape and a safe retry key.

The one-liner from the OpenAI guide, client.videos.create_and_poll(...) followed by download_content, becomes a small function you own on Sume: create_video(prompt, key) that POSTs to /v1/videos, polls the job until it is terminal, and returns the artifact URL. Sume's SDK is TypeScript, so from Python you call the HTTP API directly and a requests helper is the closest equivalent.
The OpenAI guide, read 2026-10-08, marks the Videos API as shut down on September 24, 2026, and the deprecations page gives no replacement, so keep the helper behind your own function name and not behind a vendor class.
Same shape, different names
create_and_poll hid the loop from you. On Sume the loop is explicit, but the pieces map one to one.
| OpenAI Python | Sume HTTP |
|---|---|
| videos.create(model, prompt, seconds, size) | POST /v1/videos with model, prompt, duration, resolution, aspect_ratio |
| videos.create_and_poll | your loop on GET /v1/videos/{id}, 30 s sleep |
| video.status == "completed" | job["status"] == "completed" |
| videos.download_content(id, variant="video") | GET /v1/videos/{id}/content?index=0, follow the 302 |
| no request-level retry key shown in the guide | Idempotency-Key header |
The helper
requests follows the 302 by default, but it also drops the Authorization header when a redirect leaves the original host, so the one-line download is safe. Install requests and set SUME_API_KEY.
import os, time, requests
BASE = "https://api.sume.com"
HEAD = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
def create_video(prompt, key, **fields):
body = {"model": "sume/auto", "prompt": prompt, **fields}
res = requests.post(BASE + "/v1/videos", json=body,
headers={**HEAD, "Idempotency-Key": key}, timeout=60)
res.raise_for_status()
job = res.json()
while job["status"] in ("pending", "in_progress"):
time.sleep(30)
res = requests.get(BASE + "/v1/videos/" + job["id"], headers=HEAD, timeout=60)
res.raise_for_status()
job = res.json()
return job
def main():
job = create_video("A lighthouse at dusk", "lighthouse-1", duration=8)
if job["status"] != "completed":
raise SystemExit(job["status"])
url = BASE + "/v1/videos/" + job["id"] + "/content?index=0"
with open("out.mp4", "wb") as f:
f.write(requests.get(url, headers=HEAD, timeout=300).content)
main()Details that bite
Pass your own key per logical video, not per attempt. If you reuse the key with the same body you get the first job back; reuse it with a different body and Sume answers 409 idempotency_conflict. A random UUID per call defeats the purpose.
The helper treats every non-completed terminal status as a failure. Sume's poll statuses are pending, in_progress, completed, failed and cancelled, and a failed job will not become retryable by waiting.
What is not here
The helper does not handle a 402 insufficient_credits, a 429 rate_limited, or a queue_full response; see mapping Sora-style errors onto Sume codes for the branch table, and the idempotency post for why the key matters.
Sources
Related posts
More in Developers
- OpenRouter video client on Sume: swap the base URL, change webhooks
A client written for OpenRouter /videos works on Sume after you change the base URL, key and model ids. The webhook body and signature are different.
- PHP: submit a 30-second Wan 3.0 clip, poll it, save the MP4
Plain PHP 8 with curl and no SDK: send a 30-second wan-3.0 request, poll the job, and write the MP4 to disk. The 720p run is reserved at $3.75.
- Pointing the OpenAI SDK at api.sume.com: why Sora calls still fail
Changing only the base URL does not carry a Sora call to Sume. Five documented differences: model ids, body format, seconds and size, status words, download.
- Poll /v1/jobs/{id}/status, then /result, in Node with backoff
A 25-line Node function that polls a Sume job on its own next_poll_after_seconds, reads /result only when the job completed, and keeps the id on timeout.
Written by Sume