OpenAI Videos API
Sora-compatible endpoints to create, poll, download and remix videos.
/v1/videos
These endpoints follow the OpenAI Videos API, so tools built for Sora work with RuToken by changing only the base URL and key. Besides sora-2 and sora-2-pro, other video models connected to the gateway (Kling, Vidu, Veo, …) can also be called here — task status is always returned in the OpenAI video object format.
| Method | Path | Purpose |
|---|---|---|
POST |
/v1/videos |
Create a video task. |
GET |
/v1/videos/{task_id} |
Get task status. |
GET |
/v1/videos/{task_id}/content |
Download the finished video. |
POST |
/v1/videos/{video_id}/remix |
Create a new video from a finished one (Sora). |
Authentication
Send your key in the Authorization: Bearer sk-xxxx header.
Request body
Content type: multipart/form-data (as in the OpenAI API) or application/json.
| Parameter | Type | Required | Description |
|---|---|---|---|
model |
string | Yes | Model ID, e.g. sora-2, sora-2-pro. |
prompt |
string | Yes | Text description of the video. |
seconds |
string | No | Duration in seconds. Sora: 4 (default), 8 or 12. |
size |
string | No | Resolution. sora-2: 720x1280 (default) or 1280x720. sora-2-pro also supports 1792x1024 and 1024x1792. |
input_reference |
file | No | Reference image used as the first frame. Its size should match size. |
For Sora models the price scales with seconds; sora-2-pro at 1792x1024 / 1024x1792 costs more than at 720p. Check the Model Square for exact prices.
Request example
curl https://rutoken.ai/v1/videos \
-H "Authorization: Bearer $API_KEY" \
-F model="sora-2" \
-F prompt="A calico cat playing a piano on stage, spotlight, cinematic" \
-F seconds="8" \
-F size="1280x720"
import time
from openai import OpenAI
client = OpenAI(base_url="https://rutoken.ai/v1", api_key="sk-xxxx")
video = client.videos.create(
model="sora-2",
prompt="A calico cat playing a piano on stage, spotlight, cinematic",
seconds="8",
size="1280x720",
)
# Poll until the task finishes
while video.status in ("queued", "in_progress"):
time.sleep(10)
video = client.videos.retrieve(video.id)
if video.status == "completed":
client.videos.download_content(video.id).write_to_file("cat.mp4")
else:
print("Failed:", video.error)
import OpenAI from "openai";
import fs from "node:fs";
const client = new OpenAI({ baseURL: "https://rutoken.ai/v1", apiKey: "sk-xxxx" });
let video = await client.videos.create({
model: "sora-2",
prompt: "A calico cat playing a piano on stage, spotlight, cinematic",
seconds: "8",
size: "1280x720",
});
// Poll until the task finishes
while (video.status === "queued" || video.status === "in_progress") {
await new Promise((r) => setTimeout(r, 10000));
video = await client.videos.retrieve(video.id);
}
if (video.status === "completed") {
const content = await client.videos.downloadContent(video.id);
fs.writeFileSync("cat.mp4", Buffer.from(await content.arrayBuffer()));
}
Response
Both create and status calls return a video object:
{
"id": "task_6Fh2kVb0mQ9xYzA1pL3sT8uWcR4nE7dJ",
"object": "video",
"model": "sora-2",
"status": "completed",
"progress": 100,
"created_at": 1760000000,
"completed_at": 1760000180,
"expires_at": 1760086400,
"seconds": "8",
"size": "1280x720"
}
| Field | Type | Description |
|---|---|---|
id |
string | Task ID (task_…). |
status |
string | queued, in_progress, completed or failed. |
progress |
integer | Progress from 0 to 100. |
seconds / size |
string | Duration and resolution of the video. |
expires_at |
integer | When the provider deletes the video (Unix time). |
error |
object | { "message", "code" } when the task has failed. |
metadata |
object | Extra data for non-Sora providers, e.g. metadata.url with the video URL. |
Get task status
GET /v1/videos/{task_id}
curl https://rutoken.ai/v1/videos/task_6Fh2kVb0mQ9xYzA1pL3sT8uWcR4nE7dJ \
-H "Authorization: Bearer $API_KEY"
Returns the video object shown above.
Download the video
GET /v1/videos/{task_id}/content
Streams the finished video file (usually video/mp4). The gateway proxies the file from the provider, so you do not need provider credentials. If the task has not completed yet, the endpoint returns 400 with the current status.
curl https://rutoken.ai/v1/videos/task_6Fh2kVb0mQ9xYzA1pL3sT8uWcR4nE7dJ/content \
-H "Authorization: Bearer $API_KEY" \
--output video.mp4
Remix a video
POST /v1/videos/{video_id}/remix
Creates a new task that changes a completed Sora video according to a new prompt. The remix runs on the same model and provider as the original video.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt |
string | Yes | Description of the change. |
curl https://rutoken.ai/v1/videos/task_6Fh2kVb0mQ9xYzA1pL3sT8uWcR4nE7dJ/remix \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-d '{"prompt": "Same scene, but the cat wears a tiny top hat"}'
The response is a new video object with remixed_from_video_id set.
See also: Video generation, Errors.