Kling
Kling is a video generation model series covering four distinct capabilities — text-to-video, image-to-video, motion control, and omni video. You never name a capability directly: the mode is decided automatically from the model you call and the materials you attach (see How the mode is chosen).
https://llm.siraya.ai/v1/videos/generations
https://llm.siraya.ai/v1/videos/{video_id}
Synchronous by default, asynchronous on request
By default the request waits for the render and returns the finished video URL. Set
async: true to get an id back immediately and poll GET /v1/videos/{video_id} until
status is completed or failed — recommended for motion-control and omni-video tasks,
which take longer. Pass a callbackUrl to be notified instead of polling. See
Asynchronous generation.
Supported Models
| Model ID | Description |
|---|---|
kling-2.5-turbo |
Fast text-to-video and image-to-video, 720p/1080p |
kling-2.6 |
Text-to-video, image-to-video, and motion control, 720p/1080p |
kling-3.0 |
Highest-fidelity tier — text-to-video, image-to-video, and motion control, up to 4k |
kling-3.0-turbo |
Faster 3.0 tier; the only model that ships native audio by default |
kling-3.0-omni |
Omni video — multi-material reference and video-editing style tasks, up to 4k |
kling-o1 |
Omni video, 720p/1080p, silent output only |
Capabilities by model
✅ supported · — not supported.
| Model | Text→video | Image→video | Motion control | Omni video | Resolutions | Native audio |
|---|---|---|---|---|---|---|
kling-2.5-turbo |
✅ | ✅ | — | — | 720p, 1080p | native, off |
kling-2.6 |
✅ | ✅ | ✅ | — | 720p, 1080p | native (1080p only), off |
kling-3.0 |
✅ | ✅ | ✅ | — | 720p, 1080p, 4k | native, off |
kling-3.0-turbo |
✅ | ✅ | — | — | 720p, 1080p | native (default), off |
kling-3.0-omni |
— | — | — | ✅ | 720p, 1080p, 4k | native, off |
kling-o1 |
— | — | — | ✅ | 720p, 1080p | off only |
kling-2.6refusesaudio: "native"specifically at 720p — use 1080p, or"off".kling-o1refusesaudio: "native"at every resolution. See Audio support.
How the mode is chosen
| Your request contains… | Runs as |
|---|---|
| a prompt only | text_to_video |
a first_frame (and optionally a last_frame) |
image_to_video |
an image entry and a video entry, on a model that supports motion control |
motion_control |
any request to kling-3.0-omni or kling-o1 |
omni_video |
The mode the request actually ran as is reported back in vendor_data.mode.
Header
Bearer <API_KEY>).
Body
All Kling parameters are sent flat, at the top level of the request body — there is no
settings or options wrapper.
kling-3.0, kling-2.6).
prompt entry inside contents instead.
3–15 (model-dependent). Not accepted on motion control, and
ignored when a base_video is being edited — the output length follows the source material
instead. See Behavior worth knowing.
16:9, 9:16, or 1:1. Accepted but silently ignored once a material sets the frame (image-to-video,
motion control, and omni video with a first_frame) — see Behavior worth knowing.
native (model-generated audio track) or off. Defaults to off on every model except
kling-3.0-turbo, which defaults to native. Per-model restrictions apply — see Audio support.
image or video — which material anchors the character's orientation. Only meaningful on
motion-control requests, where it is required.
true, multi-shot syntax in the prompt is parsed as a shot list — e.g.
"shot 1, 3s, a door opens; shot 2, 2s, a close-up of the handle".
{ "enabled": true | false }. When true, each entry in vendor_data.outputs gains a
watermark_url alongside url. Sent flat at the top level, even though it lives under options
in Kling's own API.
elements array for extra subject/element references
alongside the character image. This platform does not support elements yet — a motion-control
request must be built from the image + video materials in contents only. See
Motion control.
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 motion-control and omni-video tasks, which take longer. 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": "kling-3.0",
"prompt": "A paper boat drifting on a calm river",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9"
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
Example Response
{
"data": [
{
"url": "https://resources.siraya.ai/video/generated%2Fsiraya_123.mp4",
"revised_prompt": ""
}
],
"created": 1760347750
}
With "async": true, the job is accepted immediately instead:
{
"id": "video_8fK2mQxR7pLnVwZ3tYbC...",
"object": "video",
"status": "processing",
"model": "kling-3.0"
}
Poll GET /v1/videos/{video_id} with that id until status is completed — see
Poll for status.
contents — the materials array
Anything beyond plain text goes in contents, as a list of typed entries. Which entry types a
model accepts depends on the mode it is serving:
| Entry type | Carries | Where it's valid |
|---|---|---|
prompt |
text |
everywhere |
first_frame |
url |
image-to-video, omni video |
last_frame |
url |
image-to-video, omni video |
image |
url |
motion control (the character) |
video |
url |
motion control (the motion reference) |
refer_image |
url |
omni video |
feature_video |
url |
omni video |
base_video |
url |
omni video (video-editing style tasks) |
Adding a first_frame is all it takes to switch a request to image-to-video:
{
"model": "kling-2.6",
"contents": [
{ "type": "prompt", "text": "The scene comes alive" },
{ "type": "first_frame", "url": "https://your-domain.com/still.jpg" }
],
"duration": 5,
"resolution": "720p"
}
Motion control
Motion control transfers the motion of a reference video onto a character image. It is available
on kling-2.6 and kling-3.0 only.
A motion-control request needs three things: an image entry (the character), a video entry
(the motion reference), and character_orientation.
{
"model": "kling-3.0",
"prompt": "The character performs the reference motion",
"contents": [
{ "type": "image", "url": "https://your-domain.com/character.jpg" },
{ "type": "video", "url": "https://your-domain.com/motion.mp4" }
],
"character_orientation": "image",
"resolution": "1080p"
}
elements is not supported yet
Kling's motion control natively accepts an elements array — extra subject/element
references layered on top of the character image. That parameter is not available on this
platform yet. Build motion-control requests from the image + video materials in
contents only; do not send elements. Support is planned — this page will be updated when
it lands.
Both materials are required
A motion-control request must include both an image entry and a video entry. Sending
the motion reference alone would silently fall back to image-to-video or text-to-video, with
the reference motion simply ignored — so this platform rejects that combination outright
rather than billing you for a result you didn't ask for.
duration is not accepted on motion control. The output length follows the motion-reference
video.
Omni video
Every request to kling-3.0-omni or kling-o1 runs as omni_video, regardless of which
materials it carries. Omni video accepts the widest set of materials — first_frame, last_frame,
refer_image, feature_video, and base_video (for video-editing style tasks).
{
"model": "kling-3.0-omni",
"prompt": "Keep the subject, restyle the background as a winter street",
"contents": [
{ "type": "base_video", "url": "https://your-domain.com/original.mp4" },
{ "type": "refer_image", "url": "https://your-domain.com/style.jpg" }
],
"resolution": "1080p"
}
aspect_ratiotakes effect only when the request carries nofirst_frame. Arefer_imagealone does not set the frame, so you still need to specify the ratio.- A
base_videobeing edited sets the output length —durationis ignored.
Audio support
| Model | Default when unset | Notes |
|---|---|---|
kling-2.5-turbo |
off |
— |
kling-2.6 |
off |
native is refused specifically at 720p — use 1080p |
kling-3.0 |
off |
— |
kling-3.0-turbo |
native |
The one model that ships sound by default |
kling-3.0-omni |
off |
— |
kling-o1 |
off |
native is refused at every resolution — off is the only usable value |
Poll for status
https://llm.siraya.ai/v1/videos/{video_id}
When you submit with async: true, call the status endpoint with the returned id until
status reads completed or failed. A typical generation finishes in well under a minute;
motion-control and omni-video tasks with heavier materials take longer. Poll every few seconds and
back off on 429. Passing a callbackUrl at submit time removes the need to poll at all.
{
"id": "video_8fK2mQxR7pLnVwZ3tYbC...",
"object": "video",
"status": "completed",
"seconds": 5,
"resolution": "720p",
"ratio": "16:9",
"model": "kling-3.0",
"output_url": "https://.../out.mp4?Expires=...&Signature=...",
"usage": { "completion_tokens": 0, "total_tokens": 0 },
"vendor_data": {
"mode": "text_to_video",
"requested_audio": "native",
"outputs": [
{
"type": "video",
"id": "925017418714451989",
"url": "https://.../out.mp4?Expires=...&Signature=...",
"duration": "5.041"
}
]
}
}
Response object
| Field | Type | Present | Meaning |
|---|---|---|---|
id |
string | always | Opaque — pass it straight to GET /v1/videos/{video_id}; don't parse it |
object |
string | always | Always video |
status |
string | always | processing · completed · failed |
error |
object | on failure | { code, message } |
seconds |
integer | completed | Duration, rounded to the nearest second |
resolution, ratio |
string | completed, may be absent | Echo what the request asked for — see Behavior worth knowing |
output_url |
string | completed | Signed and expiring — don't cache it as a stable link |
usage |
object | always | Always { 0, 0 } — Kling has no token concept |
vendor_data |
object | always | Kling-specific fields — see vendor_data |
vendor_data
Facts specific to Kling that don't apply to every video model on this platform live here, rather than cluttering the fields every model shares.
| Field | Values | Meaning |
|---|---|---|
mode |
text_to_video · image_to_video · motion_control · omni_video |
Which capability the request actually ran as |
requested_audio |
native · off |
Echoes what you asked for, or the model's default if you didn't set audio |
outputs |
array | The produced artifact(s), with Kling's own field names. outputs[0].duration carries the unrounded duration (e.g. "5.041"), and watermark_url appears here when watermark_info.enabled was true |
Behavior worth knowing
Resolution and aspect ratio are what you asked for, not always what came out. On
image-to-video and motion control, the reference material decides the frame — an aspect_ratio
you send is accepted but silently has no effect, and resolution is echoed from the request
rather than measured off the result. On omni video, aspect_ratio only takes effect when the
request carries no first_frame.
Motion control and base_video ignore duration. Neither accepts a requested duration — the
produced length follows the source material instead (the motion-reference video, or the
base_video being edited). Expect seconds in the response to reflect that material's real
length, not a number you controlled.
Motion control cannot use elements yet. See the Motion control note above.
Errors
A request-time refusal is final — it means the parameters can't work together, not that the service is unavailable. Retrying the same body won't help.
{
"error": {
"code": "invalid_request_error",
"message": "audio mode 'native' is not supported by the current model",
"type": "invalid_request_error"
}
}
| Status | Meaning |
|---|---|
400 |
An unsupported parameter combination — resolution/duration/audio conflicts, a missing required field, or a rejected parameter such as elements |
404 |
Unrecognized model code |
200 with status: "processing" |
Accepted — keep polling |