Video Generation Guide
SIRAYA Model Router provides one unified, asynchronous API for all video models. Every model uses the same POST /v1/videos/generations endpoint and the same submit → poll → download lifecycle — what changes per model is only which parameters apply (see Per-model parameter support).
The mode is determined by the parameters you send:
- Text-to-video — send a
prompt. - Image-to-video — add
frame_images(first/last frame) orimage_url. - Reference-guided — add
input_references(image / video / audio).
https://llm.siraya.ai/v1/videos/generations
Header
Bearer <API_KEY>).
Body
veo3-fast, sora-2).
1280x720. Auto-resolves to resolution + aspect_ratio; interchangeable with them.
480p, 720p, 1080p. Interchangeable with size.
16:9, 9:16, 1:1, 4:3, 3:4, 21:9.
frame_images.
false, the request waits for generation to finish and returns the completed video URL. When true, it returns immediately with a video id you poll for status — recommended for longer videos to avoid request timeouts. See Asynchronous generation.
async is true. A URL the router will POST to once generation completes (or fails), so you don't have to poll.
import requests
url = "https://llm.siraya.ai/v1/videos/generations"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer <API_KEY>"
}
data = {
"model": "veo3.1",
"prompt": "A cute baby sea otter playing in the water",
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
Example Response
Frame and reference inputs
frame_images
Pin the first and/or last frame of the video (image-to-video). Each item:
| Field | Type | Description |
|---|---|---|
image_url |
string | URL or base64 data URL of the frame image. |
frame_type |
string | first_frame or last_frame. |
Last-frame control support varies by model — see Per-model parameter support.
input_references
Soft-guidance references. Support varies by model (see the matrix). Each item:
| Field | Type | Description |
|---|---|---|
type |
string | image, video, or audio. |
url |
string | URL or base64 data URL. |
role |
string | Optional role hint, e.g. reference_image, style, asset. |
Asynchronous generation
Video generation can take a while. By default the request is synchronous — it waits for the render to finish and returns the completed video URL. For longer videos, set async: true to return immediately with a video id, then either poll for status or receive a callback. This avoids request timeouts.
Submit an async job
curl https://llm.siraya.ai/v1/videos/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <API_KEY>" \
-d '{
"model": "veo3.1",
"prompt": "A cute baby sea otter playing in the water",
"async": true,
"callbackUrl": "https://your-app.com/webhooks/siraya-video"
}'
The job is accepted immediately. status is processing and no URL is returned yet — keep the id to poll status and download the result:
{
"id": "video_n6Sn-1aIT3z8x-QF3xxD0wiUTjl6s31...",
"object": "video",
"status": "processing",
"created_at": 1779869107,
"model": "veo3.1"
}
Poll status
https://llm.siraya.ai/v1/videos/{video_id}
Call the status endpoint with the id until status is completed (or failed):
{
"id": "video_n6Sn-1aIT3z8x-QF3xxD0wiUTjl6s31...",
"object": "video",
"status": "completed",
"created_at": 1779869107,
"completed_at": 1779869320,
"model": "veo3.1",
"output_url": "https://resources.siraya.ai/v1/videos/.../content"
}
statusis one ofprocessing,completed, orfailed.- When
failed, anerrorobject ({"code": "...", "message": "..."}) is included instead ofoutput_url. - Poll every few seconds and back off on
429.
Download the video
https://llm.siraya.ai/v1/videos/{video_id}/content
Once status is completed, download the raw video bytes (Content-Type: video/mp4). You can also fetch the output_url returned by the status call directly.
curl https://llm.siraya.ai/v1/videos/<video_id>/content \
-H "Authorization: Bearer <API_KEY>" \
-o output.mp4
Callback (instead of polling)
If you pass a callbackUrl, the router sends a POST to that URL when the job finishes, so you can skip polling. The request body is identical to the synchronous response — the finished video under data[].url:
{
"created": 1779869320,
"data": [
{ "url": "https://resources.siraya.ai/v1/videos/.../content" }
],
"error": {}
}
Your endpoint should respond 2xx to acknowledge receipt. If generation failed, the error object is populated and data is empty.
Video object (status response)
The status endpoint (GET /v1/videos/{video_id}) returns the full video object:
| Field | Type | Description |
|---|---|---|
id |
string | Opaque encoded video ID — pass as-is to the status / download endpoints. |
object |
string | Always video. |
status |
string | processing, completed, or failed. |
created_at |
integer | Unix timestamp of job creation. |
completed_at |
integer | Unix timestamp of completion (when done). |
seconds |
integer | Duration of the generated video. |
model |
string | Model used. |
output_url |
string | Download URL (present when status = completed). |
error |
object | { "code": "...", "message": "..." } (present when status = failed). |
usage |
object | { "completion_tokens": N, "total_tokens": N } (model-dependent). |
vendor_data |
object | Model-specific fields (e.g. seed, resolution, ratio, frames, last_frame_url). |
Per-model parameter support
All video models share the endpoint above, but accept different parameters. ✅ supported · — not supported.
| Parameter | Veo 3.1 | Seedance 1.x | SIRAYA Seedance 2.0 |
|---|---|---|---|
seconds |
✅ | ✅ | ✅ |
aspect_ratio |
✅ | ✅ | ✅ |
resolution |
✅ | ✅ | ✅ |
size |
✅ | ✅ | ✅ |
generate_audio |
✅ | ✅ (1.5 pro Audio only) | ✅ |
negative_prompt |
✅ | — | — |
seed |
✅ | ✅ | ✅ |
frame_images (first frame) |
✅ | ✅ | ✅ |
frame_images (last frame) |
✅ | ✅ | ✅ |
input_references |
✅ | — | ✅ |
extra_body |
✅ | ✅ | ✅ |
negative_promptis also supported by Sora models. Seedance models do not support it.
Check our Available Models List for all supported video engines.