Endpoint: https://api.laozhang.ai/v1/chat/completionsWith Watermark Endpoint: https://api.laozhang.ai/v1/chat/completions?watermark=trueMethod: POSTAuthentication: Bearer Token (API Key)Content Type: application/json
10/18 New Feature: Watermark Option By default, generated videos have no watermark . To generate videos with Sora native watermark, add the parameter ?watermark=true to the URL.
Authentication
Include your API key in the request header:
Authorization: Bearer YOUR_API_KEY
Basic Structure
{
"model" : "sora_video2" ,
"messages" : [
{
"role" : "user" ,
"content" : [ ... ]
}
],
"stream" : false
}
Request Parameters
Parameter Type Required Description modelstring ✓ Model name, see Supported Models messagesarray ✓ Message array streamboolean ✗ Whether to enable streaming output, default false
Messages Array
Each message object contains:
Field Type Required Description rolestring ✓ Fixed as "user" contentarray ✓ Content array, containing text or images
Content Array
Supports two types of content:
Text Content
{
"type" : "text" ,
"text" : "Video description text"
}
Field Type Required Description typestring ✓ Fixed as "text" textstring ✓ Video generation prompt
Image Content (Optional)
{
"type" : "image_url" ,
"image_url" : {
"url" : "https://example.com/image.png"
}
}
Field Type Required Description typestring ✓ Fixed as "image_url" image_url.urlstring ✓ Image URL or Base64
Image Restrictions
Maximum 1 image
Supports URL or Base64 format
Recommended resolution not exceeding 2048×2048
Real person photos not supported
Supported Models
Model Name Resolution Duration Price sora_video2704×1280 (Portrait) 10s $0.15 sora_video2-landscape1280×704 (Landscape) 10s $0.15 sora_video2-15s704×1280 (Portrait) 15s $0.15 sora_video2-landscape-15s1280×704 (Landscape) 15s $0.15
Price Update 15-second models are now available at $0.15/call, same price as 10-second models!
HD Model HD model sora-2-pro (HD 1080P, $0.8/call) is only available via Async API due to longer generation time (~10 minutes). 👉 View Async API Documentation
Non-streaming Response
{
"id" : "foaicmpl-xxx" ,
"object" : "chat.completion" ,
"created" : 1759759480 ,
"model" : "sora_video2" ,
"choices" : [
{
"index" : 0 ,
"message" : {
"role" : "assistant" ,
"content" : "```json \n { \n \" prompt \" : \" ... \" , \n \" mode \" : \" Portrait Mode \"\n } \n ``` \n\n > ✅ Video generated successfully, [click here](https://sora.gptkey.asia/assets/sora/xxx.mp4) to view video~~~ \n\n "
},
"finish_reason" : "stop"
}
],
"usage" : {
"prompt_tokens" : 17 ,
"completion_tokens" : 244 ,
"total_tokens" : 261
}
}
Response Field Description
Field Type Description idstring Request unique identifier objectstring Object type createdinteger Creation timestamp modelstring Model used choices[].message.contentstring Content containing video link choices[].finish_reasonstring Completion reason, "stop" indicates success usageobject Token usage statistics
Streaming Response (SSE)
When "stream": true is enabled, returns Server-Sent Events format:
data: {"id":"foaicmpl-xxx","object":"chat.completion.chunk","created":1759759480,"model":"sora_video2","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"foaicmpl-xxx","object":"chat.completion.chunk","created":1759759480,"model":"sora_video2","choices":[{"index":0,"delta":{"content":"```json\n{\n \"prompt\": \"...\"\n}\n```\n\n"},"finish_reason":null}]}
data: {"id":"foaicmpl-xxx","object":"chat.completion.chunk","created":1759759480,"model":"sora_video2","choices":[{"index":0,"delta":{"content":"> ⌛️ Task is in queue, please wait patiently...\n\n"},"finish_reason":null}]}
data: {"id":"foaicmpl-xxx","object":"chat.completion.chunk","created":1759759480,"model":"sora_video2","choices":[{"index":0,"delta":{"content":"> 🏃 Progress: 36.0%\n\n"},"finish_reason":null}]}
data: {"id":"foaicmpl-xxx","object":"chat.completion.chunk","created":1759759480,"model":"sora_video2","choices":[{"index":0,"delta":{"content":"> ✅ Video generated successfully, [click here](https://sora.gptkey.asia/assets/sora/xxx.mp4) to view video~~~\n\n"},"finish_reason":null}]}
data: {"id":"foaicmpl-xxx","object":"chat.completion.chunk","created":1759759480,"model":"sora_video2","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":17,"completion_tokens":244,"total_tokens":261}}
data: [DONE]
Streaming Response Fields
Field Type Description choices[].delta.rolestring Role, only included in first message choices[].delta.contentstring Incremental content (progress or video link) choices[].finish_reasonstring When "stop", indicates completion usageobject Last message contains usage statistics
Complete Examples
Text-to-Video
curl -X POST "https://api.laozhang.ai/v1/chat/completions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "sora_video2",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "A cute cat playing with a ball in a sunny garden"
}
]
}
]
}'
import openai
client = openai.OpenAI(
api_key = "YOUR_API_KEY" ,
base_url = "https://api.laozhang.ai/v1"
)
response = client.chat.completions.create(
model = "sora_video2" ,
messages = [
{
"role" : "user" ,
"content" : [
{
"type" : "text" ,
"text" : "A cute cat playing with a ball in a sunny garden"
}
]
}
]
)
print (response.choices[ 0 ].message.content)
const OpenAI = require ( 'openai' );
const client = new OpenAI ({
apiKey: 'YOUR_API_KEY' ,
baseURL: 'https://api.laozhang.ai/v1'
});
const response = await client . chat . completions . create ({
model: 'sora_video2' ,
messages: [
{
role: 'user' ,
content: [
{
type: 'text' ,
text: 'A cute cat playing with a ball in a sunny garden'
}
]
}
]
});
console . log ( response . choices [ 0 ]. message . content );
Image-to-Video (URL)
curl -X POST "https://api.laozhang.ai/v1/chat/completions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "sora_video2",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Generate video: Make this figurine jump out from the desk and become a living person~"
},
{
"type": "image_url",
"image_url": {
"url": "https://filesystem.site/cdn/download/20250407/OhFd8JofOAJCsNOCsM1Y794qnkNO3L.png"
}
}
]
}
]
}'
import openai
client = openai.OpenAI(
api_key = "YOUR_API_KEY" ,
base_url = "https://api.laozhang.ai/v1"
)
response = client.chat.completions.create(
model = "sora_video2" ,
messages = [
{
"role" : "user" ,
"content" : [
{
"type" : "text" ,
"text" : "Generate video: Make this figurine jump out from the desk and become a living person~"
},
{
"type" : "image_url" ,
"image_url" : {
"url" : "https://filesystem.site/cdn/download/20250407/OhFd8JofOAJCsNOCsM1Y794qnkNO3L.png"
}
}
]
}
]
)
print (response.choices[ 0 ].message.content)
Image-to-Video (Base64)
import openai
import base64
client = openai.OpenAI(
api_key = "YOUR_API_KEY" ,
base_url = "https://api.laozhang.ai/v1"
)
# Read local image
def encode_image ( image_path ):
with open (image_path, "rb" ) as image_file:
return base64.b64encode(image_file.read()).decode( 'utf-8' )
base64_image = encode_image( "/path/to/image.png" )
response = client.chat.completions.create(
model = "sora_video2" ,
messages = [
{
"role" : "user" ,
"content" : [
{
"type" : "text" ,
"text" : "Make this scene come alive"
},
{
"type" : "image_url" ,
"image_url" : {
"url" : f "data:image/png;base64, { base64_image } "
}
}
]
}
]
)
print (response.choices[ 0 ].message.content)
Streaming Output
import openai
client = openai.OpenAI(
api_key = "YOUR_API_KEY" ,
base_url = "https://api.laozhang.ai/v1"
)
stream = client.chat.completions.create(
model = "sora_video2" ,
messages = [
{
"role" : "user" ,
"content" : [
{
"type" : "text" ,
"text" : "A cute cat playing with a ball in a sunny garden"
}
]
}
],
stream = True
)
for chunk in stream:
if chunk.choices[ 0 ].delta.content:
print (chunk.choices[ 0 ].delta.content, end = '' , flush = True )
const OpenAI = require ( 'openai' );
const client = new OpenAI ({
apiKey: 'YOUR_API_KEY' ,
baseURL: 'https://api.laozhang.ai/v1'
});
const stream = await client . chat . completions . create ({
model: 'sora_video2' ,
messages: [
{
role: 'user' ,
content: [
{
type: 'text' ,
text: 'A cute cat playing with a ball in a sunny garden'
}
]
}
],
stream: true
});
for await ( const chunk of stream ) {
if ( chunk . choices [ 0 ]?. delta ?. content ) {
process . stdout . write ( chunk . choices [ 0 ]. delta . content );
}
}
Error Codes
HTTP Status Code Error Type Description 400 Bad Request Invalid request parameters 401 Unauthorized Invalid or missing API Key 402 Payment Required Insufficient balance 429 Too Many Requests Too many requests 500 Internal Server Error Internal server error 503 Service Unavailable Service temporarily unavailable
{
"error" : {
"message" : "Error description" ,
"type" : "invalid_request_error" ,
"code" : "invalid_api_key"
}
}
Rate Limits
Currently no strict rate limits, but recommended:
Control concurrency when batch generating (recommended 2-3)
Avoid large number of requests in short time
Set reasonable retry intervals
Best Practices
Video generation takes 2-4 minutes, recommend setting timeout to 5-10 minutes . import httpx
import openai
client = openai.OpenAI(
api_key = "YOUR_API_KEY" ,
base_url = "https://api.laozhang.ai/v1" ,
http_client = httpx.Client( timeout = 300.0 ) # 5 minutes
)
Add retry logic to handle temporary errors: import time
max_retries = 3
for i in range (max_retries):
try :
response = client.chat.completions.create( ... )
break
except Exception as e:
if i < max_retries - 1 :
print ( f "Error, retrying in 30 seconds..." )
time.sleep( 30 )
else :
raise
Download immediately after generation (valid for 1 day): import requests
import re
# Extract link
video_url = re.search( r 'https:// [ ^ \s \) ] + \. mp4' , content).group( 0 )
# Download
response = requests.get(video_url, stream = True )
with open ( 'video.mp4' , 'wb' ) as f:
for chunk in response.iter_content( chunk_size = 8192 ):
f.write(chunk)
Streaming Output Monitoring
Use streaming output to view progress in real-time: stream = client.chat.completions.create(
model = "sora_video2" ,
messages = [ ... ],
stream = True
)
for chunk in stream:
if chunk.choices[ 0 ].delta.content:
content = chunk.choices[ 0 ].delta.content
print (content, end = '' , flush = True )
SDK Support
Official SDK
Python: openai >= 1.0.0
Node.js: openai >= 4.0.0
Third-party SDK
Any SDK compatible with OpenAI API format can be used, just modify base_url.
Technical Specifications
Specification Value Video Encoding H.264 Audio Encoding AAC Frame Rate 24 fps Format MP4 Watermark None Audio Supported Max File Size ~50MB (depends on duration and quality)
Next Steps
Quick Start View quick start guide
Usage Examples View more code examples
Model Pricing Learn about model comparison and pricing
FAQ View frequently asked questions