Sora 2 Text to Video API
openai/sora-2/text-to-videoSora 2 (Text to Video) generates 720p HD videos with synchronized stereo audio from text prompts, supporting fixed durations from 4 to 20 seconds in 16:9 or 9:16 aspect ratios. It adheres to real-world physics and camera trajectories while delivering coherent motion dynamics and ambient soundscapes.
openai/sora-2/text-to-video
Choose another model to keep creating

Seedance 2.5
ByteDance Seed's Seedance 2.5 video model with separate text-to-video, start/end-frame image-to-video, and multimodal reference-to-video API workflows at 480p, 720p, or 1080p for 4 to 30 seconds.
From
$0.140
per output second

MiniMax H3
MiniMax H3 on Vidgo API with separate text-to-video, start/end-frame image-to-video, and multimodal reference-to-video workflows at fixed 2K output.
From
$0.105
per second

Seedance 2.0
ByteDance Seedance 2.0 Standard and Fast video generation with text, ordered start/end frames, or multimodal image, video, and audio references.
From
$0.100
per output second

Hailuo 2.3
MiniMax's Hailuo 2.3 video model for realistic human motion, expressive characters, and text-to-video or first-frame guided generation at 768p and 1080p.
From
$0.175
per video

Kling 3.0
Kuaishou's most advanced video model with native 4K/60fps output, multi-shot storyboarding, multilingual audio, and character consistency for up to 3 people.
From
$0.135
per second
Discontinued: this model no longer accepts generation requests. The API documentation below is retained for reference only.
REST API
Quick Start
Authenticate, submit generation request, and poll task status for 720p video result.
Step 1: Set up authentication
Include Authorization: Bearer VIDGO_API_KEY in all HTTP request headers.
- Endpoint
- POST
https://api.vidgo.ai/api/generate/submit - Authentication
- Authorization: Bearer VIDGO_API_KEY
Step 2: Submit generation task
Send POST request to /api/generate/submit with model openai/sora-2/text-to-video and input payload.
REQUEST_BODY=$(cat <<'JSON'
{
"model": "openai/sora-2/text-to-video",
"input": {
"prompt": "An astronaut riding a horse across the surface of Mars, red dust blowing in the wind, dramatic sunset on the horizon, cinematic wide shot, slow motion, detailed space suit reflections, epic atmosphere, volumetric lighting, smooth camera tracking. Audio: howling Martian wind, horse hooves crunching gravel, rhythmic radio breathing.",
"duration": 4,
"aspect_ratio": "16:9"
}
}
JSON
)
RESPONSE=$(curl --silent --show-error --fail-with-body \
--request POST \
--url "https://api.vidgo.ai/api/generate/submit" \
--header "Authorization: Bearer $VIDGO_API_KEY" \
--header "Content-Type: application/json" \
--data "$REQUEST_BODY")
CODE=$(printf '%s' "$RESPONSE" | jq -r '.code // empty')
if [ "$CODE" != "0" ] && [ "$CODE" != "200" ]; then
printf 'API error: %s
' "$RESPONSE" >&2
exit 1
fi
printf '%s
' "$RESPONSE"Step 3: Poll for video result
Poll with task_id while status is not_started or running, and stop at finished or failed. On success, read data.files[].file_url; on failure, read data.error_message.
Track status
GET https://api.vidgo.ai/api/generate/status/{task_id}Poll with task_id while status is not_started or running, and stop at finished or failed. On success, read data.files[].file_url; on failure, read data.error_message.
not_startedrunningfinishedfailed{
"code": 200,
"data": {
"task_id": "task-sora2-t2v-849120",
"status": "running",
"created_time": "2026-09-17T10:00:00Z"
}
}{
"code": 200,
"data": {
"task_id": "task-unified-...",
"status": "finished",
"files": [
{
"file_url": "https://storage.vidgo.ai/generated/video.mp4",
"file_type": "video"
}
],
"created_time": "2026-08-22T10:00:00Z",
"progress": 100,
"error_message": null
}
}Complete script example
Expand for a complete script with HTTP and business-code checks, task_id validation, polling, terminal-state handling, and a 600-second polling timeout.
set -euo pipefail
: "${VIDGO_API_KEY:?Set VIDGO_API_KEY in your environment}"
REQUEST_BODY=$(cat <<'JSON'
{
"model": "openai/sora-2/text-to-video",
"input": {
"prompt": "An astronaut riding a horse across the surface of Mars, red dust blowing in the wind, dramatic sunset on the horizon, cinematic wide shot, slow motion, detailed space suit reflections, epic atmosphere, volumetric lighting, smooth camera tracking. Audio: howling Martian wind, horse hooves crunching gravel, rhythmic radio breathing.",
"duration": 4,
"aspect_ratio": "16:9"
}
}
JSON
)
SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
--request POST \
--url "https://api.vidgo.ai/api/generate/submit" \
--header "Authorization: Bearer $VIDGO_API_KEY" \
--header "Content-Type: application/json" \
--data "$REQUEST_BODY")
TASK_ID=$(printf '%s' "$SUBMIT_RESPONSE" | jq -r '.data.task_id // .task_id // empty')
BUSINESS_CODE=$(printf '%s' "$SUBMIT_RESPONSE" | jq -r '.code // empty')
if [ "$BUSINESS_CODE" != "0" ] && [ "$BUSINESS_CODE" != "200" ]; then
printf 'Submit failed:
%s
' "$SUBMIT_RESPONSE" >&2
exit 1
fi
if [ -z "$TASK_ID" ]; then
printf 'Submit response did not include task_id:
%s
' "$SUBMIT_RESPONSE" >&2
exit 1
fi
START_TIME=$(date +%s)
POLL_DELAY=2
while true; do
if [ $(( $(date +%s) - START_TIME )) -ge 600 ]; then
printf 'Timed out after 600 seconds
' >&2
exit 1
fi
STATUS_RESPONSE=$(curl --silent --show-error --fail-with-body \
--url "https://api.vidgo.ai/api/generate/status/$TASK_ID" \
--header "Authorization: Bearer $VIDGO_API_KEY")
STATUS=$(printf '%s' "$STATUS_RESPONSE" | jq -r '.data.status // .status // empty')
BUSINESS_CODE=$(printf '%s' "$STATUS_RESPONSE" | jq -r '.code // empty')
if [ "$BUSINESS_CODE" != "0" ] && [ "$BUSINESS_CODE" != "200" ]; then
printf 'Status request failed:
%s
' "$STATUS_RESPONSE" >&2
exit 1
fi
case "$STATUS" in
finished)
printf '%s' "$STATUS_RESPONSE" | jq -r '(.data.files // .files // [])[]?.file_url'
break
;;
failed)
printf '%s' "$STATUS_RESPONSE" | jq -r '.data.error_message // .error_message // "Generation failed"' >&2
exit 1
;;
not_started|running)
sleep "$POLL_DELAY"
if [ "$POLL_DELAY" -lt 10 ]; then POLL_DELAY=$((POLL_DELAY + 1)); fi
;;
*)
printf 'Unexpected task status: %s
' "$STATUS" >&2
exit 1
;;
esac
doneInput parameters
Parameters passed within the input object to /api/generate/submit:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| prompt | string | Yes | — | At least 1 character after trimming. |
| duration | integer | No | 4 | 4, 8, 12, 16, or 20, in seconds. |
| aspect_ratio | string | No | 16:9 | 16:9 or 9:16. |
Response Fields
Task creation payload and query status response details:
| Field | Type | Description |
|---|---|---|
| code | integer | Application result code; successful responses return 200. |
| message | string | Human-readable status or error message. |
| data.task_id | string | Unique asynchronous task identifier. |
| data.status | string | Current lifecycle: not_started, running, finished, or failed. |
| data.created_time | string | Task creation timestamp in ISO 8601 format. |
| data.files[] | array | Output files generated upon completion. |
| data.files[].file_url | string | Public URL for downloading or playing the generated video. |
| data.error_message | string | null | Detailed error explanation when task status is failed. |
Task Lifecycle
Poll status until reaching finished or failed:
not_startedTask accepted and waiting in compute dispatch queue.
runningDiffusion model is generating video frames and audio track.
finishedGeneration completed; read video URL from data.files[0].file_url.
failedTask stopped due to parameter error or safety filter; inspect data.error_message.
Polling and Errors
- AuthenticationVerify Bearer API key in request header if 401 is received.
- ValidationCheck prompt length and duration enum choices on 400 response.
- Polling intervalPoll with a 2-second base interval, extending gradually for longer jobs.
- Webhook callbackProvide callback_url at request top level to receive asynchronous POST notifications.
Endpoint limits
| Specification | Value | Details |
|---|---|---|
| Input mode | Text only | A prompt defines the scene, action, camera, and sound. |
| Output | MP4 video with native audio | Asynchronous video generation with downloadable MP4 URL upon completion. |
| Duration | 4 / 8 / 12 / 16 / 20 seconds | Default is 4 seconds. |
| Aspect ratio | 16:9 / 9:16 | Default is 16:9 (1280x720). |
| Resolution | 720p | Standard Official output is 720p. |
| Billing basis | Per video duration tier | 4s=48, 8s=96, 12s=144, 16s=192, 20s=240 credits. |
Related Models
Sora 2 Text to Video API frequently asked questions
What is the Sora 2 Text to Video API?
Sora 2 Text to Video is an OpenAI model for video generation from text. It generates 720p resolution videos with synchronized action and ambient audio from natural language prompts, supporting multi-axis camera control and flexible framing. Built on OpenAI's multimodal diffusion architecture, it strictly adheres to real-world physics and temporal continuity while delivering expressive visual detail. You can call it programmatically or try it from the playground above.
Does Sora 2 Text to Video generate synchronized audio?
Yes. The model synthesizes native synchronized stereo audio directly during video generation without external audio models. When you include acoustic descriptions such as ambient wind, footsteps, engine hums, or dialogue cues in your prompt, the output MP4 embeds synchronized audio that matches visual actions.
What is the maximum duration for a single Sora 2 Text to Video generation?
A single call supports generating clips up to 20 seconds, with exact options of 4, 8, 12, 16, or 20 seconds (the playground defaults to 4 seconds). These fixed duration tiers allow developers and creative teams to calculate exact budgets before launching tasks.
What is the output resolution of Sora 2 Text to Video?
Sora 2 Standard outputs 720p resolution, rendering 1280x720 in landscape (16:9) and 720x1280 in portrait (9:16). This resolution provides an optimal balance between visual fidelity and generation speed for daily prototyping and social video workflows.
How can I direct camera trajectories in Sora 2 Text to Video?
We recommend using established cinematographic phrasing in separate clauses, such as slow dolly forward, low-angle tracking shot, or orbital camera movement. Pairing motion direction with specific lighting cues helps the model execute precise camera choreography.
Is Sora 2 Text to Video suitable for 9:16 vertical videos?
Yes. By specifying aspect_ratio as 9:16, the model formats outputs into 720x1280 portrait orientation. Focusing your prompt on vertical composition and character placement ensures optimal framing for mobile and short-video feeds.
When should I choose the Sora 2 Pro endpoint?
Choose Sora 2 Pro Text to Video when your project demands 1080p full HD master delivery, richer lighting complexity, or enhanced textural realism. Pro offers 720p, 1024p, and 1080p resolution tiers tailored for commercial film and broadcast assets.















