curl --request POST \
--url https://api.apiyi.com/v1/videos \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "sora-2",
"prompt": "A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion"
}
'import requests
url = "https://api.apiyi.com/v1/videos"
payload = {
"model": "sora-2",
"prompt": "A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: 'sora-2',
prompt: 'A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion'
})
};
fetch('https://api.apiyi.com/v1/videos', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1/videos",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'sora-2',
'prompt' => 'A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1/videos"
payload := strings.NewReader("{\n \"model\": \"sora-2\",\n \"prompt\": \"A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1/videos")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"sora-2\",\n \"prompt\": \"A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1/videos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"sora-2\",\n \"prompt\": \"A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion\"\n}"
response = http.request(request)
puts response.read_body{
"id": "video_abc123def456",
"object": "video",
"model": "sora-2",
"status": "queued",
"progress": 0,
"created_at": 1712697600,
"completed_at": 1712697900,
"size": "1280x720",
"seconds": "8",
"quality": "standard"
}Text-to-Video APIリファレンス
Sora 2 の text-to-video APIリファレンスとライブプレイグラウンド — JSON リクエストボディ、非同期の3段階フロー、柔軟な 4 / 8 / 12 秒のデュレーション。
curl --request POST \
--url https://api.apiyi.com/v1/videos \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "sora-2",
"prompt": "A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion"
}
'import requests
url = "https://api.apiyi.com/v1/videos"
payload = {
"model": "sora-2",
"prompt": "A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: 'sora-2',
prompt: 'A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion'
})
};
fetch('https://api.apiyi.com/v1/videos', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.apiyi.com/v1/videos",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'sora-2',
'prompt' => 'A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.apiyi.com/v1/videos"
payload := strings.NewReader("{\n \"model\": \"sora-2\",\n \"prompt\": \"A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.apiyi.com/v1/videos")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"sora-2\",\n \"prompt\": \"A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apiyi.com/v1/videos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"sora-2\",\n \"prompt\": \"A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion\"\n}"
response = http.request(request)
puts response.read_body{
"id": "video_abc123def456",
"object": "video",
"model": "sora-2",
"status": "queued",
"progress": 0,
"created_at": 1712697600,
"completed_at": 1712697900,
"size": "1280x720",
"seconds": "8",
"quality": "standard"
}Bearer sk-xxx)、prompt を入力して、model / size / seconds を選択し、送信してください。input_reference はなく、リクエストボディは application/json です。参照画像からアニメーション化する場合(image-to-video)は、Image-to-Video endpoint を使用してください(同じ path + multipart アップロード)。- Step 1(このページ):
POST /v1/videos→video_id+status: "queued"を返します - Step 2:
GET /v1/videos/{video_id}をstatus: "completed"になるまでポーリングします - Step 3:
GET /v1/videos/{video_id}/contentからダウンロードします(MP4 ファイルを返します)
コードサンプル
Python (OpenAI SDK ドロップイン)
from openai import OpenAI
import time
client = OpenAI(
api_key="sk-your-api-key",
base_url="https://api.apiyi.com/v1"
)
# Step 1: Submit the task
video = client.videos.create(
model="sora-2",
prompt="A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion",
seconds="8",
size="1280x720"
)
print(f"Video ID: {video.id}, status: {video.status}")
# Step 2: Poll status
while True:
video = client.videos.retrieve(video.id)
print(f"Status: {video.status}, progress: {getattr(video, 'progress', 0)}%")
if video.status == "completed":
break
if video.status == "failed":
raise RuntimeError(f"Generation failed: {video}")
time.sleep(15)
# Step 3: Download the video
content = client.videos.download_content(video.id)
content.write_to_file("output.mp4")
print("Saved: output.mp4")
Python (Raw requests)
import requests
import time
API_KEY = "sk-your-api-key"
BASE_URL = "https://api.apiyi.com/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
# Step 1: Submit (JSON body)
resp = requests.post(
f"{BASE_URL}/videos",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"model": "sora-2",
"prompt": "A serene Japanese garden with cherry blossoms, koi pond, traditional bridge, golden hour, ultra detailed",
"seconds": "8",
"size": "1280x720"
},
timeout=30 # The POST is just enqueueing; 30 seconds is enough
).json()
video_id = resp["id"]
print(f"Video ID: {video_id}, status: {resp['status']}")
# Step 2: Poll (max wait 15 minutes)
deadline = time.time() + 900
while time.time() < deadline:
status_resp = requests.get(f"{BASE_URL}/videos/{video_id}", headers=HEADERS).json()
print(f"Status: {status_resp['status']}, progress: {status_resp.get('progress', 0)}%")
if status_resp["status"] == "completed":
break
if status_resp["status"] == "failed":
raise RuntimeError(f"Generation failed: {status_resp}")
time.sleep(15)
# Step 3: Download
with requests.get(f"{BASE_URL}/videos/{video_id}/content", headers=HEADERS, stream=True) as r:
r.raise_for_status()
with open("output.mp4", "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
print("Saved: output.mp4")
cURL
{/* Step 1: Submit the task */}
curl -X POST "https://api.apiyi.com/v1/videos" \
-H "Authorization: Bearer sk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "sora-2",
"prompt": "A futuristic cityscape at night with neon lights and flying vehicles, cyberpunk style, cinematic",
"seconds": "8",
"size": "1280x720"
}'
{/* Step 2: Poll status (replace video_id) */}
curl -X GET "https://api.apiyi.com/v1/videos/video_abc123" \
-H "Authorization: Bearer sk-your-api-key"
{/* Step 3: Download the video file */}
curl -X GET "https://api.apiyi.com/v1/videos/video_abc123/content" \
-H "Authorization: Bearer sk-your-api-key" \
-o output.mp4
Node.js (fetch)
import fs from 'node:fs';
const API_KEY = 'sk-your-api-key';
const BASE_URL = 'https://api.apiyi.com/v1';
// Step 1: Submit
const submitResp = await fetch(`${BASE_URL}/videos`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify({
model: 'sora-2',
prompt: 'Aerial drone shot over snowy mountain range at sunrise, cinematic, ultra wide',
seconds: '8',
size: '1280x720'
})
});
const { id: videoId } = await submitResp.json();
console.log(`Video ID: ${videoId}`);
// Step 2: Poll
let status = 'queued';
while (status !== 'completed' && status !== 'failed') {
await new Promise(r => setTimeout(r, 15000));
const statusResp = await fetch(`${BASE_URL}/videos/${videoId}`, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
const data = await statusResp.json();
status = data.status;
console.log(`Status: ${status}, progress: ${data.progress ?? 0}%`);
}
if (status === 'failed') throw new Error('Generation failed');
// Step 3: Download
const contentResp = await fetch(`${BASE_URL}/videos/${videoId}/content`, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
const buffer = Buffer.from(await contentResp.arrayBuffer());
fs.writeFileSync('output.mp4', buffer);
console.log('Saved: output.mp4');
Browser JavaScript
{/* Demo only; route through your backend in production to avoid leaking the API key. Browsers also aren't ideal for downloading large video files. */}
const submitResp = await fetch('https://api.apiyi.com/v1/videos', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer sk-your-api-key'
},
body: JSON.stringify({
model: 'sora-2',
prompt: 'Watercolor northern lights over snowy mountains, gentle motion',
seconds: '4',
size: '720x1280'
})
});
const { id } = await submitResp.json();
console.log('Video ID:', id);
{/* After polling completes, hand the video URL to a backend proxy for download and serve it back to the client. */}
パラメーター早見表
| パラメーター | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
model | string | はい | — | sora-2(720p のみ)または sora-2-pro(720p / 1024p / 1080p のティア) |
prompt | string | はい | — | 動画の説明。シーン、カメラの動き、スタイル、ライティングを詳細に記述してください |
seconds | string | いいえ | "4" | 期間は 文字列の列挙型 として指定します: "4" / "8" / "12" (数値ではありません) |
size | string | いいえ | 720x1280 | 出力解像度。モデルが対応するティアと一致している必要があります(技術仕様を参照) |
input_reference upload)については、Image-to-Video エンドポイント を参照してください。応答形式
Step 1 — 即時送信応答
{
"id": "video_abc123def456",
"object": "video",
"model": "sora-2",
"status": "queued",
"progress": 0,
"created_at": 1712697600,
"size": "1280x720",
"seconds": "8",
"quality": "standard"
}
Step 2 — 実行中のポーリング
{
"id": "video_abc123def456",
"object": "video",
"model": "sora-2",
"status": "in_progress",
"progress": 45,
"created_at": 1712697600,
"size": "1280x720",
"seconds": "8"
}
Step 2 — 完了後のポーリング
{
"id": "video_abc123def456",
"object": "video",
"model": "sora-2",
"status": "completed",
"progress": 100,
"created_at": 1712697600,
"completed_at": 1712697900,
"size": "1280x720",
"seconds": "8"
}
video_urlフィールドは直接ありません — 動画ファイルはGET /v1/videos/{id}/contentからダウンロードする必要があります(video/mp4のバイナリストリームを返します)。JSON 応答に CDN URL が含まれるとは期待しないでください。progressは厳密に直線的ではありません — 飛ぶことがあります(例: 0 → 45 → 80 → 100)status: "failed"では、errorフィールドが常に存在するとは限りません — 失敗の多くはコンテンツポリシーまたはキャパシティの問題です。再試行するか、prompt を見直してください- 動画コンテンツは OpenAI 上で 1 日のみ 保持されます — 期限切れ後は
/contentが 404 を返します
seconds レートで課金が確定します(料金表 を参照してください)。POST 送信、ステータスポーリング、コンテンツのダウンロード自体は課金対象ではなく、失敗したタスクも課金されません。承認
API Key from the APIYI console (must use Sora2官转 group + usage-based billing)
ボディ
Model ID. sora-2 supports 720p only; sora-2-pro supports 720p / 1024p / 1080p tiers
sora-2, sora-2-pro Video generation prompt; describe scene, camera motion, style, lighting, and character actions in detail
"A serene Japanese garden with cherry blossoms, koi pond, traditional bridge, golden hour, ultra detailed"
Video duration as a string enum (not a number):
"4"— 4 seconds (default), ideal for short demos, single shots, fast prompt iteration"8"— 8 seconds, standard short-form video, most common"12"— 12 seconds, long shots and continuous action
Passing "10" / "15" or the integer 4 returns 400
4, 8, 12 Output resolution. sora-2 and sora-2-pro support different tiers:
sora-2(720p only):720x1280(portrait, default) /1280x720(landscape)sora-2-proadditionally supports:1024x1792/1792x1024(1024p, $0.50/sec)1080x1920/1920x1080(1080p, $0.70/sec)
Passing 1024p / 1080p sizes to sora-2 returns 400
720x1280, 1280x720, 1024x1792, 1792x1024, 1080x1920, 1920x1080 レスポンス
Task submitted, returns video_id with queued status
Task ID for subsequent polling and download
"video_abc123def456"
Object type, fixed video
"video"
Model ID used for this task
"sora-2"
Task status:
queued— submitted, waiting in queuein_progress— generatingcompleted— done, ready to download (/v1/videos/{id}/content)failed— failed (not billed), safe to retry
queued, in_progress, completed, failed "queued"
Generation progress percentage (0–100), not strictly linear
0
Task creation Unix timestamp (seconds)
1712697600
Task completion Unix timestamp (seconds), present only on completed status
1712697900
Actual output resolution (matches the requested size)
"1280x720"
Actual duration generated (matches the requested seconds)
"8"
Quality tier (standard for sora-2, high for sora-2-pro)
"standard"
このページは役に立ちましたか?