Sora API Shutdown — Migrating to Veo 3.1, a Code-Level Guide
OpenAI's Sora API is officially scheduled to shut down on 2026-09-24. From 2026-09-25 onward, requests to the Sora video endpoints are expected to return HTTP 410 Gone, and OpenAI has announced no official successor — every integration built on sora-2 or sora-2-pro needs a new home before that date. This guide walks the shortest path: migrating to Veo 3.1 (gemini-veo31) through byesu, an AI API gateway with OpenAI-compatible and Anthropic-native endpoints where one key covers Claude, GPT-5.6, Grok, Gemini and media models, billed pay-as-you-go with no subscription. Because byesu's video endpoint mirrors the async shape a Sora integration already uses, most migrations reduce to a base URL and model-name swap.
Shutdown timeline and what it affects
| Date | What happens |
|---|---|
| Now → 2026-09-24 | Sora API keeps working; this is your migration window |
| 2026-09-24 | Official shutdown date |
| 2026-09-25 onward | Video endpoints expected to return 410 Gone; no official replacement inside OpenAI's API |
Everything on the Sora video surface stops: task creation via POST /v1/videos, status polling, /content downloads, and any pipeline downstream of them. There is nothing to "upgrade to" within OpenAI's API — this is a full provider migration, not a version bump. Prompts also behave differently across video models, so budget time for a side-by-side test run rather than a deadline-day cutover.
Why Veo 3.1 is the natural replacement
- Visual quality: Google's flagship text-to-video model — high fidelity, cinematic camera work, lifelike motion.
- 1080p support: request
1920x1080directly; Sora's public tiers topped out lower for most sizes. - Image-to-video: first-frame reference via
input_reference(up to 2 images) — the same field name Sora uses, so i2v code ports almost unchanged. - Same async workflow: create task → poll status → download mp4, identical in shape to the Sora flow you already run.
- Official upstream via byesu: served over an official channel (not reverse-engineered or mirrored), with automatic refunds on failed tasks.
Request field mapping: Sora → byesu /v1/videos
Change the base URL from https://api.openai.com/v1 to https://byesu.com/v1. The auth header stays Authorization: Bearer sk-....
| Sora request field | Sora values | Veo 3.1 via byesu | Migration note |
|---|---|---|---|
model | sora-2 / sora-2-pro | gemini-veo31 | One model replaces both tiers |
prompt | free text | prompt — unchanged | Keep the scene + action + camera style |
seconds | "4" / "8" / "12" | "4" / "6" / "8" | Map 12 → 8; 4 and 8 carry over |
size | 1280x720, 720x1280, 1792x1024, 1024x1792 | 1280x720, 720x1280, 1920x1080 | Map pro landscape sizes to 1920x1080, portrait to 720x1280 |
input_reference | first-frame image | input_reference — same name | Multipart requests only; up to 2 images |
| Poll | GET /v1/videos/{id} | GET /v1/videos/{id} | Unchanged |
| Download | GET /v1/videos/{id}/content | GET /v1/videos/{id}/content | Unchanged, returns the mp4 |
Token must use the media group
Video models require a token in the media / media-gen group, otherwise you'll get a "no available channel" error. Create one in the console before testing.
Before / after: creating a task
# BEFORE — Sora (scheduled to shut down 2026-09-24)
curl https://api.openai.com/v1/videos \
-H "Authorization: Bearer sk-OPENAI_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "sora-2", "prompt": "A hummingbird hovering over a red flower, macro lens, morning light", "seconds": "8", "size": "1280x720"}'
# AFTER — Veo 3.1 via byesu (two strings changed)
curl https://byesu.com/v1/videos \
-H "Authorization: Bearer sk-YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-veo31", "prompt": "A hummingbird hovering over a red flower, macro lens, morning light", "seconds": "8", "size": "1280x720"}'Full flow in Python (create → poll → download)
import requests, time
BASE = "https://byesu.com" # was: https://api.openai.com
H = {"Authorization": "Bearer sk-YOUR_TOKEN"}
task = requests.post(f"{BASE}/v1/videos", headers=H, json={
"model": "gemini-veo31", # was: sora-2 / sora-2-pro
"prompt": "Waves crashing on rocks, slow motion, cinematic, dusk light",
"seconds": "8", # Veo 3.1 supports 4 / 6 / 8
"size": "1920x1080", # 1080p — an upgrade over most Sora sizes
}).json()
while task["status"] not in ("completed", "failed"):
time.sleep(5) # tens of seconds to a few minutes is normal
task = requests.get(f"{BASE}/v1/videos/{task['id']}", headers=H).json()
if task["status"] == "completed":
mp4 = requests.get(f"{BASE}/v1/videos/{task['id']}/content", headers=H)
open("out.mp4", "wb").write(mp4.content)If a task ends as failed, the cost is automatically refunded — no manual claim needed.
Image-to-video (same input_reference field)
curl https://byesu.com/v1/videos \
-H "Authorization: Bearer sk-YOUR_TOKEN" \
-F model="gemini-veo31" \
-F prompt="Slow push-in shot as wind stirs the leaves in the frame" \
-F seconds="8" \
-F size="1280x720" \
-F input_reference=@first_frame.pngPolling and downloading are identical to text-to-video.
Billing comparison
| Model | Per-second price | 8-second clip |
|---|---|---|
| sora-2 (official list price) | $0.10/sec | $0.80 |
| sora-2-pro (official list price) | $0.30–$0.50/sec by resolution | $2.40–$4.00 |
| Veo 3.1 via byesu | $0.01875/sec | ≈ $0.15 |
Veo 3.1 on byesu bills strictly per second: total = $0.01875 × seconds (6s ≈ $0.1125, 8s ≈ $0.15). The console shows your live billed price next to the crossed-out official list price, and failed tasks never bill. Top up with USDT, Alipay or WeChat Pay — pay only for what you generate, no subscription.
Migration checklist
- Create a byesu token in the
media / media-gengroup. - Swap the base URL:
https://api.openai.com/v1→https://byesu.com/v1. - Replace the model name:
sora-2/sora-2-pro→gemini-veo31. - Remap
seconds:12→8(4and8unchanged). - Remap
size:1792x1024/1024x1792→1920x1080/720x1280. - Keep the create → poll →
/contentloop as-is; if you relied on webhooks, switch completion detection to pollingGET /v1/videos/{id}. - Re-test your prompt library side by side — identical wording can render differently across models.
- Test image-to-video with a multipart
input_referencerequest. - Run both providers in parallel, then cut over well before 2026-09-24.
Related links
- Veo 3.1 model page (parameters & pricing detail)
- Media generation overview (image / video)
- Calling via the API (full request format)
- Quickstart (3-step setup)
- Online generation playground
- Console sign-up / create a token
FAQ
When does the Sora API shut down?
OpenAI's Sora API is officially scheduled to shut down on 2026-09-24. From 2026-09-25 onward, requests to the Sora video endpoints are expected to return HTTP 410 Gone, and OpenAI has not announced an official replacement video API — integrations built on sora-2 or sora-2-pro must migrate to another provider before that date.
What is the best alternative to the Sora API?
Veo 3.1 is one of today's leading mainstream text-to-video alternatives: strong visual quality, 1080p support, image-to-video via a first-frame reference, and an async task workflow. Through the byesu AI API gateway it is served as gemini-veo31 over an OpenAI-compatible /v1/videos endpoint, so a Sora integration migrates with a base URL and model-name swap.
How much code changes when migrating from Sora to Veo 3.1?
Very little. byesu's video endpoint mirrors the async shape a Sora integration already uses: POST /v1/videos creates the task, GET /v1/videos/{id} polls its status, and GET /v1/videos/{id}/content downloads the mp4. Point the base URL at https://byesu.com/v1, set model to gemini-veo31, and remap seconds and size to Veo's supported values.
How does Veo 3.1 pricing compare to Sora pricing?
On byesu, Veo 3.1 is billed per second at $0.01875/sec, so an 8-second clip costs about $0.15. For comparison, OpenAI's official list price at the time of writing is $0.10/sec for sora-2 and $0.30–$0.50/sec for sora-2-pro depending on resolution. Failed Veo tasks on byesu are automatically refunded.
Does Veo 3.1 support image-to-video like Sora's input_reference?
Yes, and it keeps the same field name. Send the create request as multipart/form-data and attach the first-frame image in the input_reference file field (Veo 3.1 accepts up to 2 images). The model animates the video starting from that image; polling and the mp4 download work exactly the same as text-to-video.
