LogoSoraVideo 문서
API Reference

Code Examples

Implementation examples in various programming languages

Overview

This page provides complete code examples for integrating with the Sora 2 Video API in various programming languages.

JavaScript / Node.js

Basic Text to Video

text-to-video.js
const API_KEY = process.env.SORA_API_KEY;
const BASE_URL = 'https://soravideo.art/api/v1';

async function generateVideo(prompt) {
  // Start generation
  const response = await fetch(`${BASE_URL}/sora2/text-to-video`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      prompt,
      aspectRatio: '16:9'
    })
  });

  const result = await response.json();

  if (result.code !== 200) {
    throw new Error(result.error || result.msg);
  }

  return result.data.task_id;
}

async function waitForVideo(taskId) {
  while (true) {
    const response = await fetch(`${BASE_URL}/tasks/${taskId}`, {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    });

    const result = await response.json();
    const task = result.data;

    console.log(`Status: ${task.status} (${task.progress || 0}%)`);

    if (task.status === 'completed') {
      return task.video_url;
    }

    if (task.status === 'failed') {
      throw new Error('Video generation failed');
    }

    await new Promise(r => setTimeout(r, 3000));
  }
}

// Usage
async function main() {
  const taskId = await generateVideo('A cat playing with a ball of yarn');
  console.log('Task started:', taskId);

  const videoUrl = await waitForVideo(taskId);
  console.log('Video ready:', videoUrl);
}

main().catch(console.error);

TypeScript with Full Types

sora-client.ts
interface ApiResponse<T> {
  code: number;
  msg: string;
  data?: T;
}

interface GenerationParams {
  prompt: string;
  negativePrompt?: string;
  aspectRatio?: '16:9' | '9:16' | '1:1';
  duration?: 5 | 10 | 15;
  quality?: 'standard' | 'high';
}

interface TaskResult {
  task_id: string;
  status: 'pending' | 'processing' | 'completed' | 'failed';
  progress?: number;
  video_url?: string;
  thumbnail_url?: string;
  created_at: string;
  completed_at?: string;
}

class SoraClient {
  private apiKey: string;
  private baseUrl: string;

  constructor(apiKey: string, baseUrl = 'https://soravideo.art/api/v1') {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }

  private async request<T>(
    endpoint: string,
    options: RequestInit = {}
  ): Promise<T> {
    const response = await fetch(`${this.baseUrl}${endpoint}`, {
      ...options,
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json',
        ...options.headers
      }
    });

    const result: ApiResponse<T> = await response.json();

    if (result.code !== 200) {
      throw new Error(result.msg);
    }

    return result.data!;
  }

  async textToVideo(params: GenerationParams): Promise<string> {
    const data = await this.request<{ task_id: string }>(
      '/sora2/text-to-video',
      {
        method: 'POST',
        body: JSON.stringify(params)
      }
    );
    return data.task_id;
  }

  async textToVideoPro(params: GenerationParams): Promise<string> {
    const data = await this.request<{ task_id: string }>(
      '/sora2-pro/text-to-video',
      {
        method: 'POST',
        body: JSON.stringify(params)
      }
    );
    return data.task_id;
  }

  async getTask(taskId: string): Promise<TaskResult> {
    return this.request<TaskResult>(`/tasks/${taskId}`);
  }

  async waitForCompletion(
    taskId: string,
    onProgress?: (progress: number) => void
  ): Promise<TaskResult> {
    while (true) {
      const task = await this.getTask(taskId);

      if (onProgress && task.progress) {
        onProgress(task.progress);
      }

      if (task.status === 'completed' || task.status === 'failed') {
        return task;
      }

      await new Promise(r => setTimeout(r, 3000));
    }
  }
}

// Usage
const client = new SoraClient(process.env.SORA_API_KEY!);

async function generateVideo() {
  const taskId = await client.textToVideoPro({
    prompt: 'Cinematic sunset over mountains',
    duration: 10,
    quality: 'high'
  });

  const result = await client.waitForCompletion(taskId, (progress) => {
    console.log(`Progress: ${progress}%`);
  });

  console.log('Video URL:', result.video_url);
}

Python

Basic Example

sora_client.py
import os
import time
import requests
from typing import Optional, Dict, Any

API_KEY = os.environ.get('SORA_API_KEY')
BASE_URL = 'https://soravideo.art/api/v1'

def generate_video(prompt: str, aspect_ratio: str = '16:9') -> str:
    """Generate a video from text prompt"""
    response = requests.post(
        f'{BASE_URL}/sora2/text-to-video',
        headers={
            'Authorization': f'Bearer {API_KEY}',
            'Content-Type': 'application/json'
        },
        json={
            'prompt': prompt,
            'aspectRatio': aspect_ratio
        }
    )

    result = response.json()

    if result['code'] != 200:
        raise Exception(result.get('error') or result.get('msg'))

    return result['data']['task_id']


def get_task(task_id: str) -> Dict[str, Any]:
    """Get task status"""
    response = requests.get(
        f'{BASE_URL}/tasks/{task_id}',
        headers={'Authorization': f'Bearer {API_KEY}'}
    )

    result = response.json()

    if result['code'] != 200:
        raise Exception(result.get('error') or result.get('msg'))

    return result['data']


def wait_for_completion(task_id: str, poll_interval: int = 3) -> str:
    """Wait for task to complete and return video URL"""
    while True:
        task = get_task(task_id)
        status = task['status']
        progress = task.get('progress', 0)

        print(f'Status: {status} ({progress}%)')

        if status == 'completed':
            return task['video_url']

        if status == 'failed':
            raise Exception('Video generation failed')

        time.sleep(poll_interval)


if __name__ == '__main__':
    task_id = generate_video('A golden retriever running through a field')
    print(f'Task started: {task_id}')

    video_url = wait_for_completion(task_id)
    print(f'Video ready: {video_url}')

Async Python with aiohttp

async_client.py
import asyncio
import aiohttp
import os

API_KEY = os.environ.get('SORA_API_KEY')
BASE_URL = 'https://soravideo.art/api/v1'


class AsyncSoraClient:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        }

    async def text_to_video(
        self,
        session: aiohttp.ClientSession,
        prompt: str,
        **kwargs
    ) -> str:
        async with session.post(
            f'{BASE_URL}/sora2/text-to-video',
            headers=self.headers,
            json={'prompt': prompt, **kwargs}
        ) as response:
            result = await response.json()
            if result['code'] != 200:
                raise Exception(result['msg'])
            return result['data']['task_id']

    async def get_task(
        self,
        session: aiohttp.ClientSession,
        task_id: str
    ) -> dict:
        async with session.get(
            f'{BASE_URL}/tasks/{task_id}',
            headers=self.headers
        ) as response:
            result = await response.json()
            if result['code'] != 200:
                raise Exception(result['msg'])
            return result['data']

    async def wait_for_completion(
        self,
        session: aiohttp.ClientSession,
        task_id: str
    ) -> dict:
        while True:
            task = await self.get_task(session, task_id)
            if task['status'] in ('completed', 'failed'):
                return task
            await asyncio.sleep(3)


async def main():
    client = AsyncSoraClient(API_KEY)

    async with aiohttp.ClientSession() as session:
        # Generate multiple videos concurrently
        prompts = [
            'A cat sleeping in sunlight',
            'Waves crashing on a beach',
            'City lights at night'
        ]

        # Start all tasks
        task_ids = await asyncio.gather(*[
            client.text_to_video(session, prompt)
            for prompt in prompts
        ])

        print(f'Started {len(task_ids)} tasks')

        # Wait for all to complete
        results = await asyncio.gather(*[
            client.wait_for_completion(session, task_id)
            for task_id in task_ids
        ])

        for result in results:
            print(f'Video: {result.get("video_url")}')


if __name__ == '__main__':
    asyncio.run(main())

cURL

Generate Video

Generate text-to-video
curl -X POST https://soravideo.art/api/v1/sora2/text-to-video \
  -H "Authorization: Bearer sk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A beautiful sunrise over mountains",
    "aspectRatio": "16:9"
  }'

Check Task Status

Get task status
curl https://soravideo.art/api/v1/tasks/task_abc123 \
  -H "Authorization: Bearer sk_your_api_key"

Upload Image

Upload an image
curl -X POST https://soravideo.art/api/v1/upload \
  -H "Authorization: Bearer sk_your_api_key" \
  -F "file=@/path/to/image.jpg"

Image to Video

Generate from image
curl -X POST https://soravideo.art/api/v1/sora2/image-to-video \
  -H "Authorization: Bearer sk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "imageUrl": "https://cdn.example.com/uploads/image123.jpg",
    "prompt": "The flower slowly blooms"
  }'

Get Credit Balance

Check credits
curl https://soravideo.art/api/v1/credits \
  -H "Authorization: Bearer sk_your_api_key"

Go

sora_client.go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

const baseURL = "https://soravideo.art/api/v1"

type Client struct {
    apiKey     string
    httpClient *http.Client
}

type ApiResponse struct {
    Code int             `json:"code"`
    Msg  string          `json:"msg"`
    Data json.RawMessage `json:"data"`
}

type TaskResult struct {
    TaskID       string `json:"task_id"`
    Status       string `json:"status"`
    Progress     int    `json:"progress"`
    VideoURL     string `json:"video_url"`
    ThumbnailURL string `json:"thumbnail_url"`
}

func NewClient(apiKey string) *Client {
    return &Client{
        apiKey:     apiKey,
        httpClient: &http.Client{Timeout: 30 * time.Second},
    }
}

func (c *Client) TextToVideo(prompt string) (string, error) {
    payload := map[string]string{
        "prompt":      prompt,
        "aspectRatio": "16:9",
    }

    body, _ := json.Marshal(payload)

    req, _ := http.NewRequest("POST", baseURL+"/sora2/text-to-video", bytes.NewBuffer(body))
    req.Header.Set("Authorization", "Bearer "+c.apiKey)
    req.Header.Set("Content-Type", "application/json")

    resp, err := c.httpClient.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    data, _ := io.ReadAll(resp.Body)
    var result ApiResponse
    json.Unmarshal(data, &result)

    if result.Code != 200 {
        return "", fmt.Errorf(result.Msg)
    }

    var taskData struct {
        TaskID string `json:"task_id"`
    }
    json.Unmarshal(result.Data, &taskData)

    return taskData.TaskID, nil
}

func (c *Client) GetTask(taskID string) (*TaskResult, error) {
    req, _ := http.NewRequest("GET", baseURL+"/tasks/"+taskID, nil)
    req.Header.Set("Authorization", "Bearer "+c.apiKey)

    resp, err := c.httpClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    data, _ := io.ReadAll(resp.Body)
    var result ApiResponse
    json.Unmarshal(data, &result)

    if result.Code != 200 {
        return nil, fmt.Errorf(result.Msg)
    }

    var task TaskResult
    json.Unmarshal(result.Data, &task)

    return &task, nil
}

func (c *Client) WaitForCompletion(taskID string) (*TaskResult, error) {
    for {
        task, err := c.GetTask(taskID)
        if err != nil {
            return nil, err
        }

        fmt.Printf("Status: %s (%d%%)\n", task.Status, task.Progress)

        if task.Status == "completed" || task.Status == "failed" {
            return task, nil
        }

        time.Sleep(3 * time.Second)
    }
}

func main() {
    client := NewClient(os.Getenv("SORA_API_KEY"))

    taskID, err := client.TextToVideo("A butterfly landing on a flower")
    if err != nil {
        panic(err)
    }

    fmt.Println("Task started:", taskID)

    result, err := client.WaitForCompletion(taskID)
    if err != nil {
        panic(err)
    }

    fmt.Println("Video URL:", result.VideoURL)
}

PHP

sora_client.php
<?php

class SoraClient {
    private string $apiKey;
    private string $baseUrl;

    public function __construct(string $apiKey, string $baseUrl = 'https://soravideo.art/api/v1') {
        $this->apiKey = $apiKey;
        $this->baseUrl = $baseUrl;
    }

    private function request(string $endpoint, string $method = 'GET', ?array $data = null): array {
        $ch = curl_init($this->baseUrl . $endpoint);

        $headers = [
            'Authorization: Bearer ' . $this->apiKey,
            'Content-Type: application/json'
        ];

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }
        }

        $response = curl_exec($ch);
        curl_close($ch);

        $result = json_decode($response, true);

        if ($result['code'] !== 200) {
            throw new Exception($result['msg']);
        }

        return $result['data'];
    }

    public function textToVideo(string $prompt, string $aspectRatio = '16:9'): string {
        $result = $this->request('/sora2/text-to-video', 'POST', [
            'prompt' => $prompt,
            'aspectRatio' => $aspectRatio
        ]);
        return $result['task_id'];
    }

    public function getTask(string $taskId): array {
        return $this->request('/tasks/' . $taskId);
    }

    public function waitForCompletion(string $taskId): array {
        while (true) {
            $task = $this->getTask($taskId);

            echo "Status: {$task['status']} ({$task['progress']}%)\n";

            if ($task['status'] === 'completed' || $task['status'] === 'failed') {
                return $task;
            }

            sleep(3);
        }
    }
}

// Usage
$client = new SoraClient($_ENV['SORA_API_KEY']);

$taskId = $client->textToVideo('A serene lake at dawn');
echo "Task started: $taskId\n";

$result = $client->waitForCompletion($taskId);
echo "Video URL: {$result['video_url']}\n";

Next Steps