Sora 2 API Documentation

Use the Sora 2 API to build AI video generation into your applications. Turn text prompts and images into high-quality videos programmatically with simple REST API calls.

What You Can Build

With this API, you can integrate powerful video generation capabilities:

  • Text-to-video: Transform written descriptions into videos
  • Image-to-video: Animate still images with AI
  • Status tracking: Monitor generation progress in real-time
  • Watermark removal: Process external videos (optional)

Access requires an API key and Premium subscription. All endpoints use standard REST conventions with JSON responses.

Quick Start

To start using the Sora 2 API, you'll need an API key:

🔑 Generate your API key: https://usesora.pro/api-keys

Create and manage API keys from your account dashboard. Premium subscription required.


Authentication

Include your API key in the Authorization header of every request:

Header Format

Authorization: Bearer YOUR_API_KEY

Getting Your API Key

  1. Upgrade to Premium (required for API access)
  2. Visit https://usesora.pro/api-keys
  3. Click Generate New API Key
  4. Copy and store your key securely

⚠️ Security: Never expose API keys in client-side code or public repositories. Treat them like passwords.


Base URL

https://usesora.pro/api/v1

Endpoints

1. Generate Video

Start video generation from text descriptions or images. This is the core endpoint of the Sora 2 API.

HTTP Request

POST /api/v1/videos/generate

Headers

HeaderValueRequired
AuthorizationBearer YOUR_API_KEYYes
Content-Typeapplication/jsonYes

Request Body

ParameterTypeRequiredDescription
promptstringYesText description of the video to generate (max 1000 characters)
modestringYesGeneration mode: "text-to-video" or "image-to-video"
modelstringYesAI model identifier. Currently: "sora-2"
reference_imagestringConditionalImage URL (required when mode is "image-to-video")
durationnumberNoVideo duration in seconds: 10 or 15 (default: 10)
ratiostringNoAspect ratio: "16:9", "9:16", or "1:1" (default: "16:9")
qualitystringNoVideo quality: "SD" (720p) or "HD" (1080p, default: "SD")

Example Request Body

{
  "prompt": "A majestic eagle soaring over snow-capped mountains at sunrise",
  "mode": "text-to-video",
  "model": "sora-2",
  "duration": 10,
  "ratio": "16:9",
  "quality": "HD"
}

Success Response

Status Code: 200 OK

{
  "success": true,
  "data": {
    "task_id": "abc123xyz456",
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "status": "processing"
  }
}

Response Fields:

  • task_id (string): Unique identifier for tracking video generation progress
  • uuid (string): Video record UUID in the database
  • status (string): Initial status, always "processing"

Error Responses

401 Unauthorized - Invalid or missing API Key

{
  "success": false,
  "error": "Invalid or inactive API Key"
}

402 Payment Required - Insufficient credits

{
  "success": false,
  "error": "Insufficient credits. You need at least 20 credits to generate a 10s video. Current balance: 15 credits"
}

403 Forbidden - Non-Premium user

{
  "success": false,
  "error": "API access is only available for Premium subscribers. Please upgrade to Premium plan."
}

400 Bad Request - Invalid parameters

{
  "success": false,
  "error": "Missing required fields: prompt, mode, and model are required"
}

Code Examples

curl -X POST https://usesora.pro/api/v1/videos/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A majestic eagle soaring over snow-capped mountains at sunrise",
    "mode": "text-to-video",
    "model": "sora-2",
    "duration": 10,
    "ratio": "16:9",
    "quality": "HD"
  }'

2. Get Video Status

Poll this endpoint to check generation progress and get the final video URL once processing completes.

HTTP Request

GET /api/v1/videos/status/{task_id}

Path Parameters

ParameterTypeRequiredDescription
task_idstringYesThe task ID returned from the generate endpoint

Headers

HeaderValueRequired
AuthorizationBearer YOUR_API_KEYYes

Success Response

Status Code: 200 OK

{
  "success": true,
  "data": {
    "task_id": "abc123xyz456",
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "status": "completed",
    "video_url": "https://cdn.usesora.pro/videos/abc123.mp4",
    "progress": 100
  }
}

Response Fields:

  • task_id (string): The task identifier
  • uuid (string): Video record UUID
  • status (string): Generation status - "processing", "completed", or "failed"
  • video_url (string, optional): Download URL (only present when status is "completed")
  • progress (number, optional): Progress percentage (0-100)
  • error (string, optional): Error message (only present when status is "failed")

Status Values

StatusDescription
processingVideo is being generated
completedVideo generation completed successfully
failedVideo generation failed

Error Responses

404 Not Found - Video not found

{
  "success": false,
  "error": "Video not found"
}

403 Forbidden - Unauthorized access

{
  "success": false,
  "error": "Unauthorized: This video does not belong to your account"
}

Code Examples

curl -X GET https://usesora.pro/api/v1/videos/status/abc123xyz456 \
  -H "Authorization: Bearer YOUR_API_KEY"

3. Remove Watermark

Remove watermarks from official Sora 2 shared videos (optional feature).

Important:

  • This endpoint only supports videos shared from ChatGPT's official Sora interface at https://sora.chatgpt.com
  • Videos generated through the Sora 2 API are already watermark-free
  • Third-party video URLs are not supported

HTTP Request

POST /api/v1/videos/remove-watermark

Headers

HeaderValueRequired
AuthorizationBearer YOUR_API_KEYYes
Content-Typeapplication/jsonYes

Request Body

ParameterTypeRequiredDescription
video_urlstringYesOfficial Sora 2 shared video URL (must start with https://sora.chatgpt.com)

Example Request Body

{
  "video_url": "https://sora.chatgpt.com/share/abc123xyz"
}

Success Response

Status Code: 200 OK

{
  "success": true,
  "data": {
    "output_url": "https://cdn.usesora.pro/processed/no-watermark-abc123.mp4"
  }
}

Response Fields:

  • output_url (string): URL of the processed video without watermark

Error Responses

400 Bad Request - Missing video_url

{
  "success": false,
  "error": "video_url is required"
}

400 Bad Request - Unsupported video URL

{
  "success": false,
  "error": "Only official Sora 2 shared videos (https://sora.chatgpt.com) are supported"
}

Code Examples

curl -X POST https://usesora.pro/api/v1/videos/remove-watermark \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://sora.chatgpt.com/share/abc123xyz"
  }'

Complete Workflow Example

Here's how to use the Sora 2 API to generate a video and wait for it to finish:

import requests
import time

API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://usesora.pro/api/v1'

def generate_and_wait(prompt, mode='text-to-video', duration=10, quality='HD'):
    """Generate a video and wait for completion."""

    # Step 1: Generate video
    print("Starting video generation...")
    generate_url = f'{BASE_URL}/videos/generate'
    headers = {
        'Authorization': f'Bearer {API_KEY}',
        'Content-Type': 'application/json'
    }

    payload = {
        'prompt': prompt,
        'mode': mode,
        'model': 'sora-2',
        'duration': duration,
        'ratio': '16:9',
        'quality': quality
    }

    response = requests.post(generate_url, headers=headers, json=payload)
    data = response.json()

    if not data.get('success'):
        raise Exception(f"Generation failed: {data.get('error')}")

    task_id = data['data']['task_id']
    print(f"Video generation started. Task ID: {task_id}")

    # Step 2: Poll for completion
    status_url = f'{BASE_URL}/videos/status/{task_id}'

    while True:
        response = requests.get(status_url, headers=headers)
        data = response.json()

        if not data.get('success'):
            raise Exception(f"Status check failed: {data.get('error')}")

        result = data['data']
        status = result['status']
        progress = result.get('progress', 0)

        print(f"Status: {status}, Progress: {progress}%")

        if status == 'completed':
            video_url = result['video_url']
            print(f"\n✓ Video ready: {video_url}")
            return video_url
        elif status == 'failed':
            error = result.get('error', 'Unknown error')
            raise Exception(f"Video generation failed: {error}")

        time.sleep(5)  # Poll every 5 seconds

# Usage
if __name__ == '__main__':
    try:
        video_url = generate_and_wait(
            prompt="A serene lake surrounded by autumn trees at sunset",
            duration=10,
            quality='HD'
        )
        print(f"Download your video: {video_url}")
    except Exception as e:
        print(f"Error: {e}")

Credits & Pricing

Credit Consumption

Credits are consumed based on video duration and model pricing:

Required Credits = Model Price Per Second × Video Duration

Current Pricing

ModelPrice Per Second10s Video15s Video
Sora 22 credits20 credits30 credits

Example Calculations

  • SD 10s video: 2 credits/sec × 10 sec = 20 credits
  • HD 10s video: 2 credits/sec × 10 sec = 20 credits
  • HD 15s video (Premium only): 2 credits/sec × 15 sec = 30 credits

Note: Video quality (SD/HD) and aspect ratio do not affect credit consumption. Only duration determines the credits required.


Error Codes

The API uses standard HTTP status codes:

Status CodeDescription
200Success
400Bad Request - Invalid parameters or missing required fields
401Unauthorized - Invalid or missing API Key
402Payment Required - Insufficient credits
403Forbidden - Premium subscription required or unauthorized access
404Not Found - Resource not found
500Internal Server Error - Server-side error

Error Response Format

All error responses follow this format:

{
  "success": false,
  "error": "Error message describing what went wrong"
}

Rate Limits

Premium subscribers have no rate limits on API requests. However, we recommend:

  • Status polling: Poll every 5-10 seconds when checking video status
  • Concurrent requests: Limit concurrent generation requests to avoid credit exhaustion
  • Retry logic: Implement exponential backoff for failed requests

Best Practices

1. Secure Your API Key

// ✓ Good - Server-side only
const API_KEY = process.env.SORA_API_KEY;

// ✗ Bad - Never expose in client-side code
const API_KEY = 'sk-live-abc123...';

2. Implement Proper Error Handling

try:
    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()  # Raise exception for 4xx/5xx
    data = response.json()

    if not data.get('success'):
        # Handle API-level errors
        print(f"API Error: {data.get('error')}")
except requests.exceptions.RequestException as e:
    # Handle network errors
    print(f"Network Error: {e}")

3. Use Reasonable Polling Intervals

// ✓ Good - 5 second interval
await new Promise(resolve => setTimeout(resolve, 5000));

// ✗ Bad - Too frequent
await new Promise(resolve => setTimeout(resolve, 500));

4. Monitor Credit Usage

# Check credits before generating
response = requests.get(
    f'{BASE_URL}/user/credits',
    headers={'Authorization': f'Bearer {API_KEY}'}
)

if response.json()['credits'] < 20:
    print("Warning: Low credits, please top up")

5. Implement Retry Logic

import time
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

session = requests.Session()
retry = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('https://', adapter)

Support

For API support and questions:

Premium subscribers receive priority support with faster response times.


Changelog

Version 1.0 (Current)

  • Initial API release
  • Text-to-video generation
  • Image-to-video generation
  • Video status tracking
  • Watermark removal

Coming Soon

  • Webhooks for video completion notifications
  • Batch generation endpoint
  • Video editing capabilities
  • Custom model fine-tuning