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
- Upgrade to Premium (required for API access)
- Visit https://usesora.pro/api-keys
- Click Generate New API Key
- 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
Header | Value | Required |
---|---|---|
Authorization | Bearer YOUR_API_KEY | Yes |
Content-Type | application/json | Yes |
Request Body
Parameter | Type | Required | Description |
---|---|---|---|
prompt | string | Yes | Text description of the video to generate (max 1000 characters) |
mode | string | Yes | Generation mode: "text-to-video" or "image-to-video" |
model | string | Yes | AI model identifier. Currently: "sora-2" |
reference_image | string | Conditional | Image URL (required when mode is "image-to-video" ) |
duration | number | No | Video duration in seconds: 10 or 15 (default: 10 ) |
ratio | string | No | Aspect ratio: "16:9" , "9:16" , or "1:1" (default: "16:9" ) |
quality | string | No | Video 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 progressuuid
(string): Video record UUID in the databasestatus
(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
Parameter | Type | Required | Description |
---|---|---|---|
task_id | string | Yes | The task ID returned from the generate endpoint |
Headers
Header | Value | Required |
---|---|---|
Authorization | Bearer YOUR_API_KEY | Yes |
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 identifieruuid
(string): Video record UUIDstatus
(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
Status | Description |
---|---|
processing | Video is being generated |
completed | Video generation completed successfully |
failed | Video 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
Header | Value | Required |
---|---|---|
Authorization | Bearer YOUR_API_KEY | Yes |
Content-Type | application/json | Yes |
Request Body
Parameter | Type | Required | Description |
---|---|---|---|
video_url | string | Yes | Official 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
Model | Price Per Second | 10s Video | 15s Video |
---|---|---|---|
Sora 2 | 2 credits | 20 credits | 30 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 Code | Description |
---|---|
200 | Success |
400 | Bad Request - Invalid parameters or missing required fields |
401 | Unauthorized - Invalid or missing API Key |
402 | Payment Required - Insufficient credits |
403 | Forbidden - Premium subscription required or unauthorized access |
404 | Not Found - Resource not found |
500 | Internal 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:
- Documentation: https://usesora.pro/docs
- Email: support@usesora.pro
- Discord: Join our community
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