Skip to content
API Reference

Video Generation Guide

SIRAYA Model Router provides one unified API for all video models. Every model uses the same POST /v1/videos/generations endpoint. By default the request waits for the render and returns the finished video URL; with async: true it returns a job id and you poll for status (or receive a callback) and download the result — 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) or image_url.
  • Reference-guided — add input_references (image / video / audio).

Talking-head avatar videos and lip-sync use their own endpoints (/v1/avatar/*) rather than /v1/videos/generations — see Avatar.

POST https://llm.siraya.ai/v1/videos/generations
Authorization string Required
Your API Key (e.g., Bearer <API_KEY>).

Body

model string Required
The ID of the video model (e.g., veo-3.1-generate-001, ByteDance-Seedance-1.5-pro).
prompt string Required
A descriptive text prompt for the video content.
seconds integer
The duration of the video in seconds (model-specific range — see the model pages). Most models use this field and ignore duration; Kling is the exception — it takes duration and refuses seconds with a 400. An out-of-range value is rejected at submit by some models (Veo, HappyHorse) but only fails after the job starts on others (Seedance), so validate it client-side.
seed integer
Random seed for reproducibility. The same seed produces the same video. Not used by MiniMax H3 — accepted but ignored.
size string
Pixel dimensions, e.g. 1280x720. A standard size resolves to resolution + aspect_ratio; if you send both, they must agree with size or the request returns a 400.
resolution string
Output resolution, for example 720p or 1080p. Supported values differ per model; see the Seedance, HappyHorse, MiniMax H3, Kling and Wan model tables and the other model pages. Values are case-sensitive: HappyHorse and Wan 2.7 use uppercase 720P/1080P; MiniMax H3 takes 480P, 768P and 2K; Kling takes lowercase 720p/1080p, plus 4k on kling-3.0 and kling-3.0-omni; Wan 3.0 takes lowercase 480p/720p/1080p, or 1080p/2k/4k on its -pro tiers.
aspect_ratio string
Aspect ratio: 16:9, 9:16, 1:1, 4:3, 3:4, 21:9. Supported values differ per model: Veo takes only 16:9 and 9:16; Seedance and Wan 3.0 also take adaptive; HappyHorse also takes 4:5, 5:4, 9:21; Kling takes only 16:9, 9:16 and 1:1. See the model pages.
generate_audio boolean
Generate an AI audio track. Supported by Veo, Seedance 1.5 pro, Seedance 2.x and Wan (see the matrix below); not supported by HappyHorse. Kling does not take this field — it uses its own audio parameter (see the Kling audio table).
frame_images array
First/last frame constraints for image-to-video — see frame_images.
image_url string
Shorthand for a single first-frame image (URL or base64). Deprecated — prefer frame_images.
input_references array
Soft-guidance references (image / video / audio) for reference-guided generation — see input_references. Support varies by model (see the matrix below).
negative_prompt string
Negative prompt describing content to exclude.
async boolean Default: false
When 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.
callbackUrl string
Only used when async is true. An http(s) URL the router will POST to once generation completes (or fails), so you don't have to poll.
extra_body object
Model-specific parameters passed directly to the provider.
curl https://llm.siraya.ai/v1/videos/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <API_KEY>" \
  -d '{
    "model": "veo-3.1-generate-001",
    "prompt": "A cute baby sea otter playing in the water"
  }'
import requests

url = "https://llm.siraya.ai/v1/videos/generations"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer <API_KEY>"
}
data = {
    "model": "veo-3.1-generate-001",
    "prompt": "A cute baby sea otter playing in the water",
}

response = requests.post(url, headers=headers, json=data)
print(response.json())

Example Response

{
    "created": 1760347750,
    "data": [
        {
            "url": "https://resources.siraya.ai/v1/videos/video_n6Sn-1aIT3z8x.../content"
        }
    ],
    "error": {}
}

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, reference_video, reference_audio. Veo also reads style. Where a model page documents specific role values, use those.

Some families key off role rather than type — HappyHorse and Wan, for instance, distinguish reference_image from the video being edited that way, and Wan uses it for driving_audio and first_clip too. Where a model page documents specific role values, use those.

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.

Synchronous mode: errors and timeout

In synchronous mode the router waits up to about 16 minutes for the render. If the job fails, or does not finish in that time, the request returns HTTP 400 with the error message and an empty data:

{
  "created": 1760347750,
  "data": {},
  "error": { "message": "Video processing timed out" }
}

A 200 at submit does not guarantee success in either mode: some models validate parameters (for example seconds or aspect_ratio combinations) or run content checks only after the job starts, so a request can end as failed — see the Seedance notes.

Submit an async job

curl https://llm.siraya.ai/v1/videos/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <API_KEY>" \
  -d '{
    "model": "veo-3.1-generate-001",
    "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",
  "model": "veo-3.1-generate-001",
  "seconds": 8,
  "usage": { "completion_tokens": 0, "total_tokens": 0 }
}

Poll status

GET https://llm.siraya.ai/v1/videos/{video_id}

Call the status endpoint with the id until status is completed (or failed):

curl https://llm.siraya.ai/v1/videos/<video_id> \
  -H "Authorization: Bearer <API_KEY>"
{
  "id": "video_n6Sn-1aIT3z8x-QF3xxD0wiUTjl6s31...",
  "object": "video",
  "status": "completed",
  "model": "ByteDance-Seedance-1.5-pro",
  "seconds": 5,
  "resolution": "720p",
  "ratio": "16:9",
  "output_url": "https://.../out.mp4?...",
  "usage": { "completion_tokens": 108900, "total_tokens": 108900 }
}
  • status is one of processing, completed, or failed.
  • output_url is returned by some models only (it is not returned for Veo). When it is absent, download the video from the /content endpoint below.
  • When failed, an error object ({"code": "...", "message": "..."}) is included instead of output_url.
  • Poll every few seconds and back off on 429.

Download the video

GET https://llm.siraya.ai/v1/videos/{video_id}/content

Once status is completed, download the raw video bytes (Content-Type: video/mp4). When the status call returns an output_url, you can fetch that directly instead.

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 body is the synchronous response — the finished video under data[].url — plus the job id and a status:

{
  "id": "video_n6Sn-1aIT3z8x-QF3xxD0wiUTjl6s31...",
  "created": 1779869320,
  "status": "completed",
  "data": [
    { "url": "https://resources.siraya.ai/v1/videos/.../content" }
  ],
  "error": {}
}

status is completed, failed, or timeout (the job did not finish within about 16 minutes). On failed and timeout, data is empty and error.message carries the reason. The same id is sent in the X-Video-Id request header.

Your endpoint should respond 2xx within 10 seconds. A failed delivery is retried up to 3 more times (4 attempts in total).

Delete a video

DELETE https://llm.siraya.ai/v1/videos/{video_id}

Deletes a completed task. Only the Wan 3.0 and Wan Spicy models support it — other models answer 405. A task that is still processing answers 409, and a failed task is refused too.

curl -X DELETE https://llm.siraya.ai/v1/videos/<video_id> \
  -H "Authorization: Bearer <API_KEY>"
{
  "id": "video_n6Sn-1aIT3z8x-QF3xxD0wiUTjl6s31...",
  "object": "video",
  "deleted": true,
  "deleted_at": "2026-10-21T08:15:02Z",
  "model": "wan3.0-video"
}

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.
seconds integer Duration of the generated video.
resolution string Output resolution, lowercase <height>p (e.g. 720p).
ratio string Output aspect ratio (e.g. 16:9).
model string Model used.
output_url string Download URL (present when status = completed, for models that return one — not Veo).
error object { "code": "...", "message": "..." } (present when status = failed).
usage object Always present: { "completion_tokens": N, "total_tokens": N } (zeros when the model reports no usage).
vendor_data object Model-specific fields (e.g. seed, frames, last_frame_url, and any timestamps the model reports).

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 SIRAYA Seedance 2.5 HappyHorse Kling Wan 2.7 Wan 3.0 Wan Spicy
seconds ✅ ✅ ✅ ✅ (up to 30s) ✅ (3–15s; not on video editing) — (uses duration, 3–15s; not on motion control) ✅ (2–15s) ✅ (2–30s or -1) ✅ (2.7: 2–15s; 2.2: 5 or 8)
aspect_ratio ✅ ✅ ✅ ✅ ✅ (text- and reference-to-video only) ✅ (16:9/9:16/1:1; required on omni without a frame) ✅ ✅ (incl. adaptive) —
resolution ✅ (720p/1080p/4k) ✅ ✅ (up to 4k; fast and mini 480p/720p) ✅ (480p/720p/1080p; no 4k) ✅ (uppercase 720P/1080P; 480P on 1.1) ✅ (lowercase 720p/1080p; 4k on 3.0 and 3.0-omni) ✅ (uppercase 720P/1080P) ✅ (lowercase; 2k/4k on -pro) ✅ (lowercase)
size ✅ ✅ ✅ ✅ — — (refused) — — —
generate_audio ✅ ✅ (1.5 pro Audio only) ✅ ✅ (11 languages) — — (uses audio) ✅ ✅ (defaults to true) ✅ (2.7 only)
negative_prompt ✅ — — — — — (refused) ✅ — ✅ (2.7 only)
seed ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
frame_images (first frame) ✅ ✅ ✅ ✅ ✅ — (use contents → first_frame) ✅ — (use first_frame) — (use image)
frame_images (last frame) ✅ ✅ ✅ ✅ — — (use contents → last_frame) ✅ — (use last_frame) — (use last_image, 2.2 only)
input_references ✅ — ✅ ✅ (up to 50 refs, incl. audio-only) ✅ (1–9 images; source video for editing) — (use contents: motion control, omni video) ✅ (incl. driving audio and clip continuation) — (use reference_*, file, link) —
output_format — — — ✅ (mp4/mov) — — (refused) — — —
extra_body ✅ ✅ ✅ ✅ — — — — —

HappyHorse and Wan 2.7 keep the shared vocabulary but add top-level fields of their own — watermark on both, plus audio_setting for video editing, and prompt_extend / audio_url on Wan 2.7 — and neither has an extra_body passthrough. Both choose the capability from the model code (-t2v, -i2v, -r2v, video editing) rather than from the materials you attach. Note the opposite watermark defaults: HappyHorse defaults to true, Wan 2.7 to false. See HappyHorse and Wan for the full parameter sets.

Wan 3.0 and Wan Spicy take each material as its own flat, top-level field — first_frame, last_frame, reference_images, reference_videos, reference_audios, file and link on Wan 3.0; image and last_image on Wan Spicy — instead of frame_images / input_references. They also accept the spellings duration and audio; when both spellings arrive, seconds / generate_audio win. They are the only video models that support deleting a task. See Wan and Wan Spicy.

Kling also keeps the endpoint but has its own vocabulary: it takes duration and audio (not seconds / generate_audio), and every material — first/last frame, motion reference, omni-video references — goes in a top-level contents array instead of frame_images / input_references. The shared spellings it does not use (seconds, generate_audio, size, negative_prompt, output_format, image_url, frame_images, input_references) are refused with a 400 that names the replacement, not silently ignored. The capability (text-to-video, image-to-video, motion control, omni video) is chosen from the model and the materials you attach. See Kling.

Check our Available Models List for all supported video engines.