OpenAI Videos API
Menu
Video

OpenAI Videos API

Sora-compatible endpoints to create, poll, download and remix videos.

POST /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
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"
Python
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)
Node.js
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:

json
{
  "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

text
GET /v1/videos/{task_id}
cURL
curl https://rutoken.ai/v1/videos/task_6Fh2kVb0mQ9xYzA1pL3sT8uWcR4nE7dJ \
  -H "Authorization: Bearer $API_KEY"

Returns the video object shown above.

Download the video

text
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
curl https://rutoken.ai/v1/videos/task_6Fh2kVb0mQ9xYzA1pL3sT8uWcR4nE7dJ/content \
  -H "Authorization: Bearer $API_KEY" \
  --output video.mp4

Remix a video

text
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
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.