If your code posts model="sora-2" to /v1/videos, it has nothing to call. OpenAI's video generation guide says the Sora 2 models and the Videos API were shut down on September 24, 2026, and that no one-to-one replacement API is available. The Sora 2 model page is marked deprecated. Both read on 2026-10-20.
Resold Sora 2 APIs ran on OpenAI's, so they stopped with it. We tested one on 2026-10-20 and it answered "model not found". Make one small test call before you build on any page that still advertises a Sora 2 API.
The port is three jobs: pick a model for the clip, map Sora's settings onto it, change the endpoint. Live prices for the replacements are in our guide, Sora 2 API: shut down, and what to use instead. They change, so none are typed here. Disclosure: the gateway in the examples is ours.
The field map
| Sora field | kling-o3-standard |
veo-3.1-fast |
seedance-2.5 |
|---|---|---|---|
model |
same field | same field | same field |
prompt |
prompt |
prompt |
prompt |
seconds |
duration, required |
duration, one 8-second clip |
duration, required |
size |
aspect_ratio |
aspect_ratio, resolution
|
aspect_ratio, resolution, required |
input_reference |
image_urls |
image_urls |
image_urls |
| audio, always on |
sound, required |
always on | generate_audio |
Sora's size carried shape and resolution together. 1280x720 becomes aspect_ratio 16:9 at 720p, and 720x1280 becomes 9:16. input_reference was the first frame as a multipart upload. image_urls is the same frame as a URL in a JSON list.
Audio is the one setting that differs in kind. Veo makes native audio on every clip. On Kling, sound is true or false and also picks the price tier. On Seedance, generate_audio does not change the price.
What changes in the call
-
JSON, not multipart. Send
POST /v1/generationstohttps://api.uplinkswitch.com/v1with the model and aninputobject. -
The price comes back first. The answer is a 202 with a generation id and a
chargealready set. -
One poll replaces two calls. Sora had
GET /v1/videos/{id}and a/contentdownload. Here you pollGET /v1/generations/{id}throughqueued,runningandfinalizingtosucceededorfailed. The finished mp4 is the first entry inoutputs, kept 30 days. - Failures cost nothing. A failed clip is refunded in full. One still unfinished after 6 hours is marked failed and refunded. A missing required setting, or a duration outside the model's range, gets a 400 before anything runs.
- Status codes. 401 is a missing or revoked key. 402 is an empty balance or a key at its monthly limit. 429 is the key's rate limit or a busy model, and the response says which.
Run one prompt on three models
The quickest way to choose is to send the same prompt to each and watch the clips. This starts all three, prints what each was charged, then reads each back until it finishes.
import os, time, requests
BASE = "https://api.uplinkswitch.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['UPLINK_API_KEY']}"}
PROMPT = "A paper boat drifting down a rain-filled gutter at dusk, neon reflected in the water"
jobs = { # the settings that stand in for Sora's seconds, size and audio
"kling-o3-standard": {"duration": 8, "sound": True, "multi_shots": False, "aspect_ratio": "16:9"},
"veo-3.1-fast": {"duration": 8, "resolution": "720p", "aspect_ratio": "16:9"},
"seedance-2.5": {"duration": 8, "resolution": "720p", "aspect_ratio": "16:9", "generate_audio": True},
}
gens = {}
for model, settings in jobs.items():
r = requests.post(f"{BASE}/generations", headers=HEADERS,
json={"model": model, "input": {"prompt": PROMPT, **settings}})
r.raise_for_status()
gens[model] = r.json()
print(model, "charged", gens[model]["charge"]["amount_usd"])
for model, gen in gens.items():
while gen["status"] not in ("succeeded", "failed"):
time.sleep(5)
gen = requests.get(f"{BASE}/generations/{gen['id']}", headers=HEADERS).json()
print(model, gen["status"], gen["outputs"][0]["url"] if gen["status"] == "succeeded" else "refunded")
Kling also needs multi_shots, hence the False. A short clip is usually ready within a few minutes. Long Seedance clips and 4K Veo clips take longer, as Sora's 20-second and 1080p jobs did.
Which one to pick
- Kling O3 Standard for short clips billed per second with sound on, the way Sora billed. It takes a first frame and reference images.
- Veo 3.1 Fast for the fixed 8-second shot with native audio, at 720p, 1080p or 4K.
- Seedance 2.5 for scenes longer than Sora's 20 seconds in one request, with reference images and a reference audio track.
Check the model actually answered
Whether each video model answered today is public at /proof, which calls every model on the list once a day. Every charge sits on a signed receipt and a monthly statement you can check at /statements/verify.
Get a key: prepaid, no subscription, 30-day price lock, at uplinkswitch.ai/console.
Top comments (0)