api
Video generation task API
Direct answerCreate with POST /v1/videos, poll GET /v1/videos/{task_id}, and fetch content only after completed. Submission success is not generation success.
Updated · Reviewed
Beginner: submit, finish, and download are separate
Video generation can take seconds or minutes. POST /v1/videos creates a task; persist its id or compatibility field task_id, then query GET /v1/videos/{task_id}. Read output only at status=completed. queued and in_progress are intermediate states, while failed is terminal. The gateway also exposes /v1/video/generations for compatible clients; select one contract and do not mix their response fields.
Minimal create and poll example
create=$(curl -sS "$BASE_URL/v1/videos" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"sora-2","prompt":"A paper-cut rabbit crossing a misty forest","seconds":"8","size":"1280x720"}')
task_id=$(printf '%s' "$create" | jq -r '.id // .task_id')
test -n "$task_id" && test "$task_id" != "null"
curl "$BASE_URL/v1/videos/$task_id" \
-H "Authorization: Bearer $API_KEY"
A status object may include progress, created_at, completed_at, expires_at, video_url, and error. HTTP 200 alone is not a success condition because the task can still contain failed.
State machine, deadlines, and retries
Model the expected path as queued → in_progress → completed|failed. Preserve and alert on an unknown status instead of silently treating it as success. Begin polling around two to five seconds, back off with jitter, and impose an overall business deadline. A network timeout does not prove create failed. Reconcile an application idempotency key, Request-ID, or previously stored task ID before resubmitting to prevent duplicate work and billing.
Status reads are naturally retryable. Create and remix operations need a verified idempotency contract. Do not automatically retry invalid parameters, authentication failures, or deterministic content rejection.
Inputs, downloads, and lifetime
Accept image inputs only through a channel-supported format and controlled HTTPS locations. Remote fetching needs SSRF protection, redirect limits, content-type checks, and byte, pixel, and duration bounds. After completion, use video_url or, where supported, GET /v1/videos/{task_id}/content. Stream the body with timeouts and a maximum length, verify its hash, and use an atomic temporary-file or object-storage write.
expires_at is a lifecycle signal, not permanent storage. Record task, owner, model, prompt version, media type, size, hash, retention date, and deletion status in your own storage catalog.
Production observability and billing
Measure submission success, queue delay, generation time, terminal success, failure codes, pre-expiry download rate, and model cost. Correlate internal task ID, upstream task ID, Request-ID, and user idempotency key without logging raw sensitive media. Reconcile duration, resolution, tier, count, and retries. Client disconnection does not necessarily cancel upstream work, so cancellation and billing semantics must be tested separately.
Expert: capacity, callbacks, and recovery
Isolate submission from polling with a queue and cap per-user and global in-flight work. Use leases so multiple workers do not poll the same task; make terminal writes idempotent. Verify callback signatures and replay protection when callbacks exist, but retain active polling as a recovery path. Exercise provider timeout, stuck tasks, expired links, storage failure, and duplicate callbacks before launch, and ensure final settlement or refund reconciles to the task terminal state.
Use cases
- Run text-to-video and image-to-video tasks
- Poll a terminal state and download output
- Govern long-running cost, concurrency, and expiry
API protocols
/v1/videos/v1/videos/{task_id}/v1/videos/{task_id}/content/v1/video/generations/v1/video/generations/{task_id}
FAQ
Does a successful POST mean the video is ready?
No. It only creates the task. Persist the ID and wait for completed. queued and in_progress are intermediate; failed is terminal.
How often should I poll?
Start at several seconds, back off with jitter, and honor server hints and the business deadline. A tight fixed loop amplifies load and throttling.
Why did the result link expire?
Provider or gateway links can be signed and bounded by expires_at. Stream completed output into controlled storage before expiry.
Related guides
Official sources
- OpenAI Video Generation Guide Official
- OpenAI Videos API Reference Official
兔子API