Video
This quickstart walks you through generating your first video with SIRAYA Model Router.
Video generation
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"
}'
- https://llm.siraya.ai/v1/videos/generations is the base URL
<API_KEY>is your API Key generated in API page.modelis the model name, such asveo-3.1-generate-001, available model list can be access in Model page.promptis the prompt.async(boolean, optional, defaultfalse) — whenfalse, the request waits for generation to finish and returns the finished videourl. Whentrue, the request returns immediately with a videoidyou poll for status (recommended for longer videos, to avoid request timeouts).callbackUrl(string, optional) — only used whenasyncistrue; must be anhttp(s)URL. The full URL the router willPOSTto once generation completes (or fails), so you don't have to poll.
Example response
{
"created":1779869107,
"data":[
{
"url":"https://resources.siraya.ai/v1/videos/video_n6Sn-1aIT3z8x-QF3xxD0wiUTjl6s31ITzZT46hwKyO76u6tQqyIG2pJpuH2fwVp8xDMHUsL-Xcb6Z23Zwsx3CyCodxCuEhffwrnlVa2FW__anjjNthFJJHGTSoTvTX3x-so9lSXeqaKTSjgoNgcEpEAzsJqUXN-TCavtB4MBY9F3spP3qKZa354Bw4ntid5PnuvoPGDe_A9OWwAXe_k8mshQhrVp52KSlleDAOAHdqG-k44_6kROl0Q11IsneT_Qq6SU5Bw/content"
}
],
"error":{}
}
Asynchronous generation
Video generation can take a while. Set async: true to return immediately with a video
id instead of waiting — then either poll for status or receive a callback.
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",
"async": true,
"callbackUrl": "https://your-app.com/webhooks/siraya-video"
}'
Example response — the job is accepted; status is processing and no url yet:
{
"id": "video_n6Sn-1aIT3z8x-QF3xxD0wiUTjl6s31...",
"object": "video",
"status": "processing",
"model": "veo-3.1-generate-001",
"seconds": 8,
"usage": { "completion_tokens": 0, "total_tokens": 0 }
}
Keep the returned id — you use it to poll status and download the result.
1. Poll the status
Call the status endpoint with the id until status is completed (or failed):
{
"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 }
}
statusis one ofprocessing,completed, orfailed.output_urlis returned by some models only (not by Veo); when it is absent, download from the/contentendpoint below.- When
failed, anerrorobject ({"code": "...", "message": "..."}) is included instead ofoutput_url. - Poll every few seconds; back off on
429.
2. Download the video
Once status is completed, download the raw video bytes (Content-Type: video/mp4):
curl https://llm.siraya.ai/v1/videos/<video_id>/content \
-H "Authorization: Bearer <API_KEY>" \
-o output.mp4
When the status call returns an output_url, you can fetch that directly instead.
Callback (instead of polling)
If you passed 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 (not finished within about 16 minutes). On
failed and timeout, data is empty and error.message carries the reason. The id is
also 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.
In synchronous mode (no async), a failed or timed-out job returns HTTP 400 with
{"created": ..., "data": {}, "error": {"message": "..."}}.