Sora API Shutdown: Export Assets and Migrate Video Workflows

The Sora API shuts down on September 24, 2026. If your application still submits Sora jobs, use the remaining time to preserve outputs and validate a replacement video workflow. OpenAI's Sora web and app experiences already ended on April 26, 2026; that earlier date is separate from the API deadline. OpenAI's discontinuation notice explains both dates and the export process.
Switching to Kling or Seedance involves more than selecting a new model. Request bodies, reference inputs, job states, result URLs, and supported durations can differ. The migration is complete when your application can submit, track, retrieve, and retain an acceptable video through the new route.
Documentation checked September 14, 2026. The examples below were checked against published schemas; they are not reports of paid generation tests.
What to save before the Sora API shutdown
Start with an inventory of the Sora jobs your application needs to retain. Preserve the provider job ID, your internal job ID, model, prompt, reference-asset locations, requested settings, status, and completed output. Keep these records under your existing access and retention rules.
For API-generated videos, the current OpenAI API distinguishes job metadata from the downloadable media:
| Purpose | OpenAI API path |
|---|---|
| Create a video | POST /v1/videos |
| Retrieve job metadata | GET /v1/videos/{video_id} |
| Download completed content | GET /v1/videos/{video_id}/content |
The create, retrieve, and download references document these operations. Save the actual media bytes to storage you control; a list of job IDs is not a video archive. Verify that downloaded files open and that your application can find them without calling Sora.
For content made in the Sora app, use the export process described in OpenAI's notice. Do not assume an app export also archives your application's API jobs. OpenAI describes possible final export windows and notification by email; the notice does not justify promising either immediate deletion of every asset on the API deadline or indefinite recovery afterward. Archive what you need while it is accessible.
Choose a replacement with the clips you actually produce
Begin with a small evaluation set representing your production work: a product close-up, a scene with motion, a reference-driven shot, dialogue if needed, and a difficult prompt your current workflow handles poorly. Keep input assets and acceptance criteria consistent across candidates.
| Candidate | Documented capabilities worth testing | Migration questions |
|---|---|---|
| Kling 3.0 | Native audio, multi-shot generation, and first/last-frame workflows in the official model guide | Does your chosen API route expose the required mode, duration, audio controls, and reference handling? |
| Seedance 2.5 | Multimodal references, video editing and extension, and generation up to 30 seconds | Does the route support the requested resolution, reference roles, and task-specific parameter combination? |
These are capability summaries, not quality rankings. See the Kling 3.0 model guide and ByteDance's Seedance 2.5 announcement. A capability available in a vendor application is not automatically available through every API or gateway.
Seedance and Seedream are different model families. Seedance generates video; Seedream 5.0 Pro is an image model. An image-generation price cannot be used as a per-second video quote.
Browse the Tokenhot model catalog for candidate routes, then read the selected model's API page before implementing it. Record the exact model identifier and evaluation date so that later results can be compared meaningfully.
Adapt the request body, not just the base URL
OpenAI's Sora create operation uses fields such as prompt, seconds, and size, with its own supported values. Tokenhot's documented Seedance 2.5 operation uses content, duration, ratio, and resolution instead. The Tokenhot path is /v1/video/generations, with singular video.
The following text-to-video submission follows the Tokenhot Seedance 2.5 documentation. Install requests, set TOKENHOT_API_KEY in your environment, and run it only when you intend to create a potentially billable job.
import json
import os
from pathlib import Path
import requests
record_path = Path("seedance-submission.json")
if record_path.exists():
raise RuntimeError("A submission record exists; inspect it before creating another job.")
response = requests.post(
"https://api.tokenhot.ai/v1/video/generations",
headers={"Authorization": f"Bearer {os.environ['TOKENHOT_API_KEY']}"},
json={
"model": "doubao-seedance-2.5",
"content": [{
"type": "text",
"text": "A ceramic cup on a wooden table, slow camera push-in, soft daylight."
}],
"duration": 5,
"ratio": "16:9",
"resolution": "720p",
"generate_audio": False,
"output_format": "mp4"
},
timeout=(10, 60),
)
response.raise_for_status()
job = response.json()
task_id = job["id"]
record_path.write_text(json.dumps(job, indent=2), encoding="utf-8")
print(f"Submitted task: {task_id}")
This example submits once and saves the response. A network timeout can leave submission outcome uncertain: the server may have accepted a job even though the client did not receive its ID. Investigate the existing request before submitting it again. The local file guard is a convenience for this example, not a production idempotency mechanism.
The current Seedance 2.5 page documents 480p and 720p output, with durations from 4 to 30 seconds or an adaptive value of -1. Video editing requires duration=-1 and ratio=adaptive; first-frame, first-and-last-frame, and extension tasks also require the adaptive ratio. Validate the rules for your task type rather than copying a text-to-video payload into every mode. Unsupported combinations may fail after asynchronous processing begins. Tokenhot parameter requirements.
Keep submission and polling schemas separate
An accepted submission is not a completed video. The Seedance 2.5 submission page documents a top-level id and statuses including queued, processing, succeeded, and failed.
The separately published Seedance 2.0 task-query page documents GET /v1/video/generations/{task_id} and illustrates a nested response: data.status is SUCCESS, while data.result_url contains the output address. Because that page is labeled for 2.0, confirm the query contract for your selected 2.5 route before reusing a 2.0 polling parser.
Build a small adapter for each verified route. It should translate the provider response into your application's own states, such as waiting, running, completed, and failed. Preserve the raw task ID and error details for troubleshooting. Unknown states should trigger investigation rather than being treated as success.
Your worker should have a bounded polling interval, an overall deadline, and explicit handling for authentication errors, throttling, and transient server failures. When a local polling deadline expires, retain the job ID so that another worker can resume checking it. Do not submit a replacement job merely because the original has taken longer than expected.
Once a job succeeds, retrieve the result promptly and save it under your application's retention policy. Treat signed output URLs as temporary access mechanisms unless the service explicitly documents otherwise. A completed provider job and a safely retained customer asset are separate milestones.
Compare cost per accepted clip
Compare prices for the same resolution, duration, audio setting, input mode, and access route. Vendor app credits, direct API prices, and gateway quotes can use different billing rules. Our API pricing comparison explains how to keep billing units and provider routes separate.
A useful evaluation metric is:
Cost per accepted clip = total billed evaluation cost / accepted clips
For example, if an evaluation costs $12 and yields eight clips that pass your requirements, the observed cost is $1.50 per accepted clip. This is an illustrative calculation, not a Kling or Seedance price quote. Include billed rejected attempts in the numerator, and separately account for storage, editing, and human review if they affect your decision.
Track completion time and failure rate alongside visual quality. A low list price offers little help if your workflow repeatedly regenerates unusable outputs.
Cut over before September 24
- Archive required Sora outputs and verify playback from your own storage.
- Select a replacement route using representative clips and explicit acceptance criteria.
- Verify request validation, submission records, query parsing, failed jobs, and output retrieval.
- Route a controlled share of new work to the replacement and monitor completed assets, cost, and failures.
- Stop creating new Sora jobs early enough to handle remaining work before the deadline.
- Keep the old job records readable after cutover, and document a fallback that does not depend on Sora remaining available.
If you are also choosing a gateway, the OpenRouter alternatives guide covers route selection and compatibility checks. For implementation, start with the exact video-model page in the Tokenhot API documentation, then validate the complete job lifecycle in your own environment.
Sora API access ends on September 24, 2026. Preserve completed videos and job metadata, evaluate Kling and Seedance against your own clips, and migrate both submission and task handling. This guide separates confirmed shutdown details from implementation choices and shows the documented Tokenhot Seedance request format.


