Find the six removed Sora identifiers in your repo, then move to Sume
OpenAI's removal list names the Videos API and five model ids, all dated 2026-09-24. A runnable repo scan finds them, and what changes on Sume's /v1/videos.

To find what the Sora shutdown broke in your code, search the repository for six strings: the Videos API path and the five model identifiers that OpenAI listed for removal. OpenAI's deprecations page (read 2026-10-08) says the Videos API and the Sora 2 models were removed from the API on 2026-09-24, after a notice on 2026-03-24. The script below does that search. The second half of this post covers what you then change to call Sume's POST /v1/videos.
What OpenAI's page lists
The entry dated 2026-03-24 says OpenAI notified developers who use the Videos API and the Sora 2 model aliases and snapshots that they would be removed on September 24, 2026. The shutdown table has six rows. The recommended-replacement column shows a dash for each of them, so the page names no successor.
| Model or system | Shutdown date | Recommended replacement |
|---|---|---|
| Videos API | 2026-09-24 | none listed |
| sora-2 | 2026-09-24 | none listed |
| sora-2-pro | 2026-09-24 | none listed |
| sora-2-2025-10-06 | 2026-09-24 | none listed |
| sora-2-2025-12-08 | 2026-09-24 | none listed |
| sora-2-pro-2025-10-06 | 2026-09-24 | none listed |
A scan that finds every hit
Dated snapshot names hide in config files, test fixtures, and environment templates, not only in application code. The scan reads every text file under the current directory and prints file, line, and the matched string. It lists the longest identifiers first, so a line with sora-2-pro-2025-10-06 reports that full name and not the shorter sora-2-pro. It also flags any existing /v1/videos path, which you must check by hand, because the host in front of that path decides which API it is.
Run it from the repository root with python3 scan.py, and treat the count on the last line as the size of the job. A count of zero is also useful: it means the removed identifiers are gone from the files you scanned, though not from environment variables or secrets managers that live outside the repo.
import asyncio, pathlib, re
IDS = ["sora-2-pro-2025-10-06", "sora-2-2025-12-08", "sora-2-2025-10-06",
"sora-2-pro", "sora-2"]
PATTERN = re.compile("|".join(re.escape(i) for i in IDS) + r"|/v1/videos")
SKIP = {".git", "node_modules", ".venv", "dist"}
def scan(root: pathlib.Path) -> list[str]:
hits = []
for path in root.rglob("*"):
if SKIP & set(path.parts) or not path.is_file():
continue
try:
text = path.read_text(encoding="utf-8")
except (UnicodeDecodeError, OSError):
continue
for n, line in enumerate(text.splitlines(), 1):
for m in PATTERN.finditer(line):
hits.append(f"{path}:{n}: {m.group(0)}")
return hits
async def main() -> None:
hits = await asyncio.to_thread(scan, pathlib.Path("."))
print("\n".join(hits) or "no Sora identifiers found")
print(f"{len(hits)} hit(s)")
asyncio.run(main())What changes on the Sume side
Sume documents /v1/videos as agreeing field-for-field with the OpenRouter Video Generation API, not with OpenAI's Videos API. A client written from OpenRouter's docs works after you change the base URL and the key. A client written for OpenAI's Videos API needs its request and response handling checked against the Sume docs. Sume does not list Sora models, so a model id in your config must be replaced, not renamed.
| Step | Sume behavior |
|---|---|
| Base URL | https://api.sume.com/v1/videos, with no /api segment |
| Model ids | Bare catalog ids such as seedance-2, or sume/auto to let Sume pick |
| Discovery | GET /v1/videos/models lists durations, resolutions, and aspect ratios for each model |
| Submit | 202 with id, polling_url, status pending |
| Poll | GET /v1/videos/{jobId} until completed, failed, or cancelled |
| Download | GET /v1/videos/{jobId}/content, with your key; the index query parameter defaults to 0 |
| Retries | Send Idempotency-Key; a replay returns the original job |
Order of work
Run the scan first and keep its output as the migration list. Then read GET /v1/videos/models once and choose models from the supported_durations and supported_resolutions fields, since limits differ for each model. Last, add an Idempotency-Key to every submit that your code can retry. Do not resubmit a paid request only because a local timeout fired; poll the job id you already hold, as the jobs docs say.
Keep the first migration small. Pick one prompt from your old Sora library, submit it on one Sume model with an Idempotency-Key, poll to completed, download the file from the content URL, and read usage.cost from the poll response. That one round trip proves the key, the base URL, the model id, and the billing field before you change the rest of the code. Then repeat the scan to confirm that none of the six identifiers remain.
Sources
Related posts
More in Developers
- Grok Image n is 1 on Sume: four images mean four calls, $0.10
Sume's catalog caps n at 1 for Grok Image. A Python loop for four images costs $0.10, and runs sync. Ratios incl. 9:19.5 and 9:20 stay available.
- Group failed Sume jobs by error category with curl and jq
One curl and jq command that lists the last 100 failed jobs, groups them by error.category, code and retryable, and prints a sample job id for each group.
- Recast 400 "exactly one source video and 1-4 images": five causes
The Videos API refuses an h3-max-recast request that is not one video plus 1-4 images in input_references. Five causes of that 400 and what to send instead.
- Haiku 5.5 prompt caching for a Sume tool list: what breaks the cache
Haiku 5.5 cache hits cost $0.01 per million tokens. Keep the Sume tool list and effort setting stable so a long agent run keeps hitting the cache.
Written by Sume