Sora API Shut Down: What to Use Instead, and Is There a Free Option?
sora-2, sora-2-pro and dated snapshot models on September 24, 2026, and its deprecations page lists no recommended replacement. If your product called POST /v1/videos, the closest like-for-like replacement you can switch to today is the ZSky video API: the same asynchronous pattern (create a job, poll it, download the file), text-to-video and image-to-video, synchronized audio on every clip, clips from 1 to 10 seconds at up to 2560 px on a side, and a monthly spending cap you set instead of an open-ended per-second meter. It is self-serve on two plans: Pro ($19 a month) is pay per use, billed per second of video by resolution with a monthly cap you set, and Max ($99 a month, or $79 a month billed annually) includes 3,000 video-seconds and 1,000 images every month. There is no free API, from OpenAI or from ZSky, but the same generation pipeline runs free and unlimited in the browser, so you can judge the output before you pay. The field mapping and a working Python port are below.
Is there a free Sora API?
No, and there never was. The Sora 2 API billed every second of video from the first call ($0.10 a second for sora-2 at 720p, more on sora-2-pro), and since September 24, 2026 it does not exist at any price. Searches for a "free Sora API" usually come from one of two needs, and they have different answers:
- You want Sora-style video without paying. Use a browser generator rather than an API. ZSky's web app is free and unlimited with a free account and no credit card: HD video with synchronized audio, with a small wordmark on free outputs. Our Is Sora free? guide covers that path.
- You need video from code. Any API that renders video on GPUs charges for it. The lowest-commitment ZSky path is Pro at $19 a month, pay per use with a monthly cap you set; Max suits steady volume because it includes 3,000 video-seconds a month. The free web tier has no API key.
What replaced the Sora API?
Nothing from OpenAI. The Videos API and the sora-2 models were removed on September 24, 2026, and OpenAI's deprecations page leaves the recommended-replacement column empty, so every team that built on it picks its own successor. For developers who want the same create, poll and download job shape rather than a new architecture, the ZSky video API is the closest match available today: text-to-video and image-to-video, synchronized audio on every clip, clips of 1 to 10 seconds at up to 2560 px, and a monthly spending cap you set. Teams that need 12-second clips, completion webhooks or Sora's remix endpoints will not find them here; the rest of the migration is a handful of renamed fields, mapped below.
What OpenAI removed on September 24
On March 24, 2026, OpenAI told developers using the Videos API that the API and every Sora 2 model alias and snapshot would be removed on September 24, 2026. The consumer Sora app and website closed earlier, on April 26. The OpenAI deprecations page lists the removals as:
- the Videos API itself (
POST /v1/videos,GET /v1/videos/{id},GET /v1/videos/{id}/contentand the remix endpoint), sora-2andsora-2-pro,- the dated snapshots
sora-2-2025-10-06,sora-2-2025-12-08andsora-2-pro-2025-10-06.
The "recommended replacement" column for every one of those rows is empty. This is not a version bump. There is no Sora 3 model ID to swap in, no grace period, and no migration guide from OpenAI. Any request that names a sora-2 model now fails, and if your application stored Sora video IDs rather than the downloaded files, those downloads are no longer reachable through the API. You choose the replacement, and you port the calls.
What a replacement has to give you
Most Sora integrations are small. They submit a prompt, poll a job until it finishes, download an MP4, and store or serve it. A replacement needs to cover the same surface without a regression your users will notice:
- The same asynchronous shape. Create a job, poll a status, fetch a file. If the replacement forces a synchronous request that blocks for a minute, your queue and timeouts change.
- Text-to-video and image-to-video. Sora's
input_referenceanchored a clip to a still image. If you used it, the replacement needs an equivalent. - Audio in the clip. Sora 2 generated synchronized sound. Several video APIs return silent MP4s, which is a visible regression for anything social.
- Durations and resolutions that cover your product. Sora offered 4, 8 or 12 seconds at 720p, and 1080p-class sizes on the Pro model.
- A spend ceiling you control. Per-second metering with no cap of its own made a busy month expensive and hard to predict.
- A safety layer with a clear status. You need to know when a job was refused rather than failed, so you can tell the user.
- Ownership and retention controls. Who owns the output, how long the file is kept, and whether you can opt out of storage.
The ZSky video API covers each of those. The table below puts the two APIs side by side so you can check it against your own code.
Sora 2 API vs ZSky video API
| Item | Sora 2 API (removed) | ZSky video API |
|---|---|---|
| Status today | Removed September 24, 2026 | Live |
| Create a video | POST https://api.openai.com/v1/videos | POST https://zsky.ai/api/v1/videos/generate |
| Authentication | Authorization: Bearer | X-API-Key header |
| Model selection | model: sora-2 or sora-2-pro | None. One pipeline, no model parameter. |
| Prompt | prompt | prompt, up to 2,000 characters |
| Duration | seconds: "4", "8" or "12" (a string) | duration: any integer 1 to 10 seconds (default 5) |
| Resolution | size: 1280x720 or 720x1280; larger sizes on the Pro model | width and height, 256 to 2560 px each (default 1280×720) |
| Image to video | input_reference, a multipart image upload | init_image_base64: PNG, JPEG or WebP up to 12 MiB, base64-encoded |
| Reproducible output | Not documented | seed (integer) |
| Poll status | GET /v1/videos/{id} → queued, in_progress, completed, failed | GET https://zsky.ai/api/v1/jobs/{job_id} → queued, generating, completed, failed, blocked, plus a terminal flag |
| Download | GET /v1/videos/{id}/content | result_url in the completed job: a signed download link valid for 24 hours |
| Completion webhooks | Yes | No. Poll; most clips finish in about 30 seconds. |
| Audio | Generated with the clip | Synchronized audio on every clip, included |
| Lip-sync to your own audio | No | Yes: send audio_base64 (up to 10 MB) with lip_sync: true |
| Remix and character endpoints | Existed | Not offered |
| Price | sora-2: $0.10 per second of video. sora-2-pro: $0.30 to $0.70 per second depending on resolution. | Pro ($19 a month): pay per use, billed per second of video by resolution, with a monthly cap you set ($5 to $1,000). Max ($99 a month, or $79 a month billed annually): 3,000 video-seconds and 1,000 images included each month, then the same per-second rates up to your cap. Current rate card: zsky.ai/api-docs. |
| Rate limits | Varied by account tier | 100 image and 100 video requests a minute per account, 1 job at a time per account, and 200 images and 50 videos a day (raised on request) |
| Retention | Account data deleted after the shutdown | Results kept 7 days unless you delete them earlier. Send X-ZSky-Store: 0 to get the bytes inline and store nothing. |
| Content safety | Moderation errors | Same safety pipeline as the web app. A refused job returns status: "blocked" with a message. |
| Public feed | n/a | API outputs never appear in ZSky's public Explore feed |
| Visible watermark | None | None on Pro and Max outputs (an invisible provenance mark only) |
Two things stand out for a migration. The job lifecycle is the same, so your polling loop, retries and storage code survive with renamed fields. And spend has a ceiling: Sora billed every second with no cap of its own, while ZSky's pay-per-use stops at the monthly cap you set.
Parameter mapping
| Sora 2 field | ZSky field | Notes |
|---|---|---|
model | (drop it) | ZSky has no model parameter. |
prompt | prompt | Natural-language prompts port unchanged. Limit 2,000 characters. |
seconds: "8" | duration: 8 | Integer seconds, 1 to 10. A 12-second Sora job becomes a 10-second clip. |
size: "1280x720" | width: 1280, height: 720 | Each side 256 to 2560 px. Portrait: 720 by 1280. |
input_reference (file) | init_image_base64 (string) | Base64 of a PNG, JPEG or WebP up to 12 MiB. Image URLs are not accepted. |
| — | seed | Optional integer for reproducible runs. |
| — | X-ZSky-Store: 0 (header) | Optional zero-retention mode. |
id (video_…) | job_id | Returned by the create call together with poll_url. |
status: in_progress | status: generating | Also queued, processing or committing while it runs. Stop when terminal is true; the usual end states are completed, failed and blocked. |
GET /videos/{id}/content | result_url | Plain HTTPS GET on the signed URL; no API key needed for the download itself. |
The port, in Python and curl
Here is a typical Sora 2 integration using the OpenAI SDK, and the same job on ZSky using requests. The ZSky version is the same number of lines; only the field names and the download step change.
Before (Sora 2, OpenAI SDK):
import time
from openai import OpenAI
client = OpenAI()
video = client.videos.create(
model="sora-2",
prompt="A lighthouse beam sweeping across a black sea at night, cinematic",
seconds="8",
size="1280x720",
)
while video.status in ("queued", "in_progress"):
time.sleep(5)
video = client.videos.retrieve(video.id)
content = client.videos.download_content(video.id)
content.write_to_file("clip.mp4")
After (ZSky video API):
import os, time, requests
BASE = "https://zsky.ai/api/v1"
HEADERS = {"X-API-Key": os.environ["ZSKY_API_KEY"]}
job = requests.post(f"{BASE}/videos/generate", headers=HEADERS, json={
"prompt": "A lighthouse beam sweeping across a black sea at night, cinematic",
"duration": 8,
"width": 1280,
"height": 720,
}).json()
# {"job_id": "8a1...", "status": "queued", "kind": "video", "poll_url": "/v1/jobs/8a1..."}
while True:
state = requests.get(f"{BASE}/jobs/{job['job_id']}", headers=HEADERS).json()
if state.get("terminal"):
break
time.sleep(5)
if state["status"] == "completed":
# result_url is a signed link, valid for 24 hours; download it once and keep the file
open("clip.mp4", "wb").write(requests.get(state["result_url"]).content)
else:
print(state["status"], state.get("error"))
The same two calls with curl:
curl -s -X POST https://zsky.ai/api/v1/videos/generate \
-H "X-API-Key: $ZSKY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt":"A lighthouse beam sweeping across a black sea at night, cinematic","duration":8,"width":1280,"height":720}'
# {"job_id":"8a1...","status":"queued","kind":"video","poll_url":"/v1/jobs/8a1..."}
curl -s https://zsky.ai/api/v1/jobs/8a1... -H "X-API-Key: $ZSKY_API_KEY"
# {"job_id":"8a1...","status":"completed","kind":"video","result_url":"https://...","expires_in":86400}
Image-to-video replaces Sora's multipart input_reference with a base64 string in the same JSON body:
import base64
frame = base64.b64encode(open("frame.png", "rb").read()).decode()
job = requests.post(f"{BASE}/videos/generate", headers=HEADERS, json={
"prompt": "slow push-in, wind moving through the trees",
"duration": 5,
"init_image_base64": frame,
}).json()
Three details worth handling in production. Every 429 carries a plain-English error field naming the cause: the per-minute limit, the concurrency limit and the daily soft cap also send a Retry-After header, while an exhausted monthly allowance does not, because nothing changes until the counters reset or you enable pay-per-use. One handler that reads error and honors Retry-After when present covers all four. A blocked status means the safety filter refused the prompt or the output; show the user the error text rather than retrying. And the signed result_url expires after 24 hours, so download the file when the job completes and keep your own copy.
What Sora charged, and how ZSky bills
OpenAI published Sora 2 API rates per second of generated video: $0.10 for sora-2 at 720p, and $0.30, $0.50 or $0.70 for sora-2-pro at 720p, 1024p and 1080p. A batch tier halved those rates in exchange for up to 24-hour turnaround. An 8-second sora-2 clip was $0.80; the same clip on sora-2-pro at 1080p was $5.60, and a month's bill had no ceiling other than your own rate limiting.
ZSky's API is self-serve on two plans. Pro ($19 a month) is pay per use from the first second: video is billed per second by resolution and images per image, and you set a monthly cap between $5 and $1,000 in Settings, so generation stops at the cap. Max ($99 a month, or $79 a month billed annually) includes 3,000 video-seconds and 1,000 images each month, and usage beyond that is billed at the same rates up to your cap. The current allowance and rate card are on the API docs page. The practical difference from Sora is that your worst-case month is a number you chose in advance, not a function of how many seconds your users requested. For sustained volume beyond the daily soft cap, email [email protected].
Every limit, in one place
- Plan: Pro ($19 a month, pay per use) or Max ($99 a month, or $79 a month billed annually, with an included allowance). The free tier has no API access.
- Included each month: a monthly allowance of videos and images (Max only: 3,000 video-seconds and 1,000 images as this is written; the current figures are on the docs page). The counters reset on the 1st of each month, UTC.
- Pay per use: on Pro from the first second, on Max beyond the allowance, always up to a monthly cap you set between $5 and $1,000. Rates are on the docs page.
- Request rate: 100 image requests and 100 video requests a minute per account.
- Concurrency: 1 job at a time per account, shared by every key and sign-in on it. A second submit returns
429withRetry-After: 5. - Daily limit: 200 images and 50 videos a day per account, reset at midnight US Eastern; email [email protected] to raise it.
- Clip length: 1 to 10 seconds (
duration), default 5. - Resolution:
widthandheightfrom 256 to 2560 px each, default 1280×720. - Prompt: up to 2,000 characters.
- Uploads: image-to-video source image up to 12 MB (PNG, JPEG or WebP, base64 in the JSON body), lip-sync audio up to 10 MB, whole request up to 25 MB.
- Result link: signed URL valid 24 hours. Storage: 7 days, or none with
X-ZSky-Store: 0.DELETE /api/v1/jobs/{job_id}purges early. - Safety: every request passes the same prompt and output checks as the web app; refused work returns
blocked. - Ownership: you own the output, commercial use is allowed on every plan, and API outputs never appear in the public Explore feed.
How to get a key today
- Subscribe to Pro ($19 a month, pay per use) or Max ($99 a month, or $79 a month billed annually, allowance included).
- Open Settings → API + MCP and create your key. It is shown once; rotating it invalidates the previous key immediately.
- Confirm it works:
curl https://zsky.ai/api/v1/usage -H "X-API-Key: zsky_live_..."returns your current-month counters.
If you want to see the output before you pay, the same generation pipeline runs free in the browser at zsky.ai/create with a free account and no card. Type the prompts your Sora integration sends, and judge the clips yourself.
What ZSky does not replace
A migration guide that only lists wins is not one you can plan against. The gaps are:
- 12-second clips. The API tops out at 10 seconds per clip.
- Completion webhooks. There is no callback; you poll. Jobs usually finish in about 30 seconds, so a 5-second poll interval is fine.
- Remix and character endpoints. Sora's
/remixand character-upload features have no equivalent. - A batch tier. There is no discounted slow lane.
- 4K through the API. The API caps each side at 2560 px. 4K output is a web-app feature on Max.
- SDK compatibility. ZSky is not an OpenAI-compatible endpoint. The port is a handful of renamed fields, as shown above, not a base-URL swap.
Using it from an AI agent
The same key also drives ZSky's MCP adapter, a local stdio server for MCP clients such as Claude Code and Claude Desktop. It exposes tools to generate images and videos, animate a local image, check job status and read usage, and it runs against the same /api/v1 endpoints with the same allowance and limits. If your Sora integration lived inside an agent workflow rather than a product, that is the shorter path. Setup steps are on the API and MCP docs page.
Frequently asked questions
Is the Sora API really gone, or only deprecated?
Gone. Deprecation was announced on March 24, 2026, and removal happened on September 24, 2026. OpenAI's deprecations page lists the Videos API and every sora-2 model ID with no recommended replacement.
Is there a free Sora API alternative?
Not as an API. The Sora API was never free and no longer exists, and ZSky's API is paid: pay per use on Pro ($19 a month) or an included monthly allowance on Max ($99 a month). What is free is ZSky's web app, which is unlimited for people with a free account and no credit card, so you can evaluate the output before you subscribe.
Does the ZSky API generate audio like Sora 2 did?
Yes. Every clip comes with synchronized audio at no extra cost, and you can supply your own audio track for lip-synced video with audio_base64 and lip_sync: true.
Can I keep my existing Sora prompts?
Yes. Prompts are plain natural language on both APIs. The only hard limit on ZSky is 2,000 characters per prompt.
How long does a video take?
Typically about 30 seconds from submission to a completed status. Poll the job every few seconds; the response carries a terminal flag when it is done.
What happens when I use up the monthly allowance?
The next request returns 429 with a message naming the allowance. If you have opted into pay-per-use in Settings, generation continues at the current rates until your monthly cap is reached; if not, it resumes when the counters reset on the 1st.
Who owns the output?
You do. Commercial use is allowed on every plan, API outputs never appear in the public Explore feed, and you can opt out of storage entirely with the X-ZSky-Store: 0 header.
Is there an OpenAI-compatible endpoint I can point the SDK at?
No. The request and response fields differ, as the mapping table shows. Porting a typical integration is a matter of renaming a few fields and downloading from result_url instead of a content endpoint.
Switch your video pipeline today
API and MCP access is self-serve on Pro (pay per use) and Max (monthly allowance included), with a monthly cap you set and a key you create yourself in Settings.
Get API access on Pro or Max → Read the API overviewSources: OpenAI API deprecations page (Videos API and sora-2 model removals, September 24, 2026); OpenAI Help Center, "What to know about the Sora discontinuation" (app closure April 26, 2026; API discontinuation September 24, 2026); OpenAI's published Sora 2 API per-second rates as summarized by CostGoat and eesel; ZSky API limits and response fields from the ZSky API documentation, checked September 26, 2026.