Sora Videos API removed: same submit-and-poll curl on Sume /v1/videos

OpenAI removed the Sora 2 models and Videos API on Sept 24, 2026. Sume POST /v1/videos keeps the async shape: submit, poll polling_url, download. Curl included.

5 min readSume
All posts

If your code called the OpenAI Videos API, it broke on September 24, 2026. The loop it used (submit, poll, download) still exists on Sume at POST /v1/videos, which follows the OpenRouter video shape. Change the base URL, the key and the model id. Sora ids are not Sume catalog ids, so you pick a model from the Sume catalog.

What OpenAI removed

OpenAI's deprecations page lists the Videos API, sora-2, sora-2-pro and two dated snapshots of each as removed on September 24, 2026. The recommended replacement column is empty, so no vendor successor exists to point at (OpenAI Deprecations, read 2026-10-05). A redirect or a model-name swap on your side will not bring the old endpoint back.

The practical task is therefore to pick another video model and keep the integration shape you already have.

    The loop that carries over

    Sume documents the same four steps: submit to POST /v1/videos, receive an id and a polling_url, poll until status is completed, then download from unsigned_urls[0]. Authentication is a Bearer key in SUME_API_KEY. The docs say a client written from the OpenRouter video docs works after you change the base URL and key.

    curl -X POST "https://api.sume.com/v1/videos" \
      -H "Authorization: Bearer $SUME_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "seedance-2",
        "prompt": "A golden retriever playing fetch on a sunny beach"
      }'
    
    # poll the polling_url from the response
    curl "https://api.sume.com/v1/videos/<job_id>" \
      -H "Authorization: Bearer $SUME_API_KEY"

    What to change in your code

    Three edits cover most ports. Replace the model id with a bare Sume catalog id such as seedance-2. Map the status values you branch on: /v1/videos returns pending, in_progress, completed and failed. Read the clip from unsigned_urls[0] instead of a Sora content path.

    Duration and resolution are not free-form. Each model publishes supported_durations and supported_resolutions in GET /v1/videos/models, so read them before you submit rather than copying Sora's 4, 8 or 12 second values.

    Pick the replacement model from the catalog

    Call GET /v1/videos/models and filter on the fields your old prompts depend on. If you do not want to choose, model: "sume/auto" lets Sume select one for you. Sume does not disclose which model ran, so use it for drafts and pin a model id for work you need to reproduce.

    Poll every few seconds or use a webhook, and keep the job id so a restart can resume. For the model-by-model mapping, see the migration table linked below.

    Errors your old code will meet

    Sume wraps errors in its public envelope with code, message and request_id, which is close enough to the OpenRouter shape that clients reading error.message keep working. The codes worth handling on a video port are below.

    Log the request_id with every failure. It is safe to share with support, unlike keys or signed URLs.

    HTTPCodeWhat to do
    400unsupported_capabilityValue is not in the model's published list; read the catalog
    402insufficient_creditsBalance is below the reserve; add funds, do not loop
    404model_not_foundId is not a catalog id; an id outside the catalog lands here
    409job_not_completedContent was requested early; keep polling
    429rate_limitedBack off using retry-after

    Protect the retry

    The old integration probably retried on network errors. On Sume, add an Idempotency-Key header to the submit so a retried POST returns the original job instead of creating a second paid one. The same key with a different body returns 409.

    Sources

    Related posts

    More in Developers

    All Developers posts

    Written by Sume