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.

5 min readSume
All posts

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.

Call mapping from the OpenAI guide and Sume docs, read 2026-10-08
OpenAI PythonSume HTTP
videos.create(model, prompt, seconds, size)POST /v1/videos with model, prompt, duration, resolution, aspect_ratio
videos.create_and_pollyour 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 guideIdempotency-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

All Developers posts

Written by Sume