Kling 3.0 Omni
kling-3.0-omni supports text-to-video, first-frame and first/last-frame generation, image and video references, and video editing.
See Billing for the credit rates for each scenario.
Create a task
Send a JSON request to POST https://api.aivideoapi.ai/omni-video/kling-3.0-omni with your platform API key as a Bearer token.
The examples below use placeholder media and callback URLs under example.com. Replace them with your own HTTP(S) URLs before sending a request. Media URLs must allow the external video generation service to download the file without login. Callback URLs must be reachable from the platform API server's runtime environment. HTTP(S) URLs must not contain a username or password. Use a different options.external_task_id for each new task.
Text-to-video
curl -X POST 'https://api.aivideoapi.ai/omni-video/kling-3.0-omni' \
-H 'Authorization: Bearer YOUR_PLATFORM_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"contents": [
{"type": "prompt", "text": "A kitten running through a moonlit garden, smooth tracking shot, with soft footsteps and rustling leaves"}
],
"settings": {
"resolution": "720p",
"aspect_ratio": "16:9",
"duration": 5,
"audio": "native",
"multi_shot": false
},
"options": {
"external_task_id": "omni-text-001",
"watermark_info": {"enabled": true}
}
}'
The remaining creation examples are complete JSON bodies for the same endpoint and authentication headers. Prompt items use type="prompt" and text; each task accepts at most one prompt item. Media items use type, url, and an optional id. Refer to that media in your prompt with @id; media IDs must be unique within the task. Images accept HTTP(S) URLs or PNG/JPEG Base64, including data URLs. Videos use HTTP(S) URLs for MP4/MOV files. Media URLs must meet the download requirements above.
First frame
Use one first_frame to animate an image. The output follows the image's aspect ratio.
{
"contents": [
{"type": "prompt", "text": "The kitten in @start turns toward the camera, with a gentle breeze moving its fur"},
{"type": "first_frame", "url": "https://media.example.com/kitten-start.jpg", "id": "start"}
],
"settings": {"resolution": "720p", "duration": 5, "audio": "off", "multi_shot": false},
"options": {"external_task_id": "omni-first-001"}
}
First and last frames
Provide one first_frame and one last_frame to guide the beginning and end of the video. A last_frame requires a first_frame.
{
"contents": [
{"type": "prompt", "text": "A smooth transition from the closed flower in @start to the fully opened flower in @end"},
{"type": "first_frame", "url": "https://media.example.com/flower-start.jpg", "id": "start"},
{"type": "last_frame", "url": "https://media.example.com/flower-end.jpg", "id": "end"}
],
"settings": {"resolution": "1080p", "duration": 5, "audio": "off", "multi_shot": false},
"options": {"external_task_id": "omni-frames-001"}
}
Image references
Use 1–7 refer_image items to guide subjects, appearance, or settings. Reference images cannot be combined with first or last frames.
{
"contents": [
{"type": "prompt", "text": "The character in @hero walks through the garden in @scene, maintaining the character's appearance"},
{"type": "refer_image", "url": "https://media.example.com/character.jpg", "id": "hero"},
{"type": "refer_image", "url": "https://media.example.com/garden.jpg", "id": "scene"}
],
"settings": {"resolution": "720p", "aspect_ratio": "16:9", "duration": 5, "audio": "off", "multi_shot": false},
"options": {"external_task_id": "omni-images-001"}
}
Video reference
Use one feature_video to guide motion or camera movement. You may add up to four refer_image items, as below, or one first_frame. Output duration must be 3–10 seconds and audio must be off. Explicit shot prompts are unsupported in this mode.
{
"contents": [
{"type": "prompt", "text": "The character in @hero follows the movement and camera motion in @motion"},
{"type": "feature_video", "url": "https://media.example.com/motion-reference.mp4", "id": "motion"},
{"type": "refer_image", "url": "https://media.example.com/character.jpg", "id": "hero"}
],
"settings": {"resolution": "720p", "aspect_ratio": "16:9", "duration": 5, "audio": "off", "multi_shot": false},
"options": {"external_task_id": "omni-video-reference-001"}
}
Video editing
Use one base_video, optionally with up to four refer_image items. Set multi_shot=false explicitly. Audio accepts off to remove audio or original to retain the input audio. The input must be 3–15.5 seconds long; output duration and aspect ratio follow the input, so omit duration and aspect_ratio in this mode.
{
"contents": [
{"type": "prompt", "text": "In @source, replace the character's jacket with the jacket shown in @jacket, preserving the scene and motion"},
{"type": "base_video", "url": "https://media.example.com/source-video.mp4", "id": "source"},
{"type": "refer_image", "url": "https://media.example.com/jacket.jpg", "id": "jacket"}
],
"settings": {"resolution": "1080p", "audio": "original", "multi_shot": false},
"options": {"external_task_id": "omni-edit-001"}
}
Explicit multi-shot generation
Set multi_shot=true and format the prompt as 镜头 n, seconds, description;. Keep the literal 镜头 marker and use ASCII commas and semicolons, even when the descriptions are in English. Number shots consecutively from 1, with at most six shots. Each duration must be a positive integer and all shot durations must add up to settings.duration.
{
"contents": [
{"type": "prompt", "text": "镜头 1, 2, Wide shot of a moonlit garden;镜头 2, 3, Close-up of a kitten looking toward the moon;"}
],
"settings": {"resolution": "720p", "aspect_ratio": "16:9", "duration": 5, "audio": "off", "multi_shot": true},
"options": {"external_task_id": "omni-shots-001"}
}
For automatic shot planning, use an ordinary prompt with multi_shot=true. Explicit shots cannot be used with feature_video, and editing requires multi_shot=false.
Settings and options
| Field | Accepted values and behavior |
|---|---|
settings.resolution | 720p (default), 1080p, or 4k |
settings.duration | Integer from 3–15 seconds; default 5. With feature_video, 3–10 seconds. Editing follows the input duration; omit this field for editing. |
settings.aspect_ratio | 16:9 (default), 9:16, or 1:1. First-frame generation and editing follow the input aspect ratio. |
settings.audio | off (default) or native for generation without video input. feature_video requires off. base_video accepts off or original. |
settings.multi_shot | Boolean, default true. Editing requires explicit false. |
options.external_task_id | Optional client task ID, unique within your account. Reusing the ID with the same parameters returns the existing task without another charge; different parameters produce an error. |
options.callback_url | Optional HTTP(S) URL reachable from the platform API server's runtime environment, without a username or password. Receives a POST when the task succeeds or fails. See Callbacks. |
options.watermark_info.enabled | Boolean, default false. Set to true to also receive a watermarked copy. |
Only one video input is allowed: either feature_video or base_video. base_video cannot be combined with first or last frames; feature_video cannot be combined with a last frame. Element IDs and element library management are outside this endpoint's supported capabilities.
The platform does not impose image byte-size or prompt-length checks and does not compress or shorten input. Oversized input may still be rejected during generation, with a sanitized task error.
Creation response
A successful request returns code=0 and a task summary in data. Creation is asynchronous: receiving this response means the task was accepted, and you must query the task or receive a callback for the result. All task timestamps are Unix milliseconds. Example:
{
"code": 0,
"message": "SUCCEED",
"request_id": "539b0fc0-e162-4676-8a75-59b91acff891",
"data": {
"id": "ee831186-1034-4e58-8019-07b638d98f60",
"status": "submitted",
"create_time": 1788998400000,
"update_time": 1788998400000,
"external_id": "omni-text-001"
}
}
external_id is included only when an external task ID was supplied. The creation summary contains no outputs, billing, or task-level message; those appear in task queries and callbacks. Reusing an external task ID may return an existing task in a later status.
Query tasks
Use GET https://api.aivideoapi.ai/tasks. Specify exactly one of task_ids or external_task_ids; either parameter accepts a comma-separated list.
Query with the data.id returned by creation:
curl --get 'https://api.aivideoapi.ai/tasks' \
-H 'Authorization: Bearer YOUR_PLATFORM_API_KEY' \
--data-urlencode 'task_ids=ee831186-1034-4e58-8019-07b638d98f60'
Or query by your external task IDs:
curl --get 'https://api.aivideoapi.ai/tasks' \
-H 'Authorization: Bearer YOUR_PLATFORM_API_KEY' \
--data-urlencode 'external_task_ids=omni-text-001,omni-first-001'
The response data is always an array, including when querying one task. Unknown tasks and tasks belonging to other accounts are omitted; no matching tasks returns data: []. Duplicate identifiers are returned once.
Task in progress
submitted means the task is waiting to run or has been submitted. processing means generation, result recording, or credit settlement is in progress. Both statuses return an empty task-level message, outputs, and billing.
{
"code": 0,
"message": "SUCCEED",
"request_id": "9101dd71-a4f3-48c4-b735-7baf1af32184",
"data": [
{
"id": "ee831186-1034-4e58-8019-07b638d98f60",
"status": "processing",
"create_time": 1788998400000,
"update_time": 1788998430000,
"external_id": "omni-text-001",
"message": "",
"outputs": [],
"billing": []
}
]
}
Successful task
The platform returns succeeded after recording generation success and completing credit settlement. outputs contains the resulting video. duration is a string in seconds. watermark_url is optional and appears when a watermarked copy is available.
Both url and the optional watermark_url are returned unchanged, including any signature query parameters. The platform does not copy result videos into its storage or replace their domains. Download and save the files promptly; availability depends on the actual URLs returned. Retaining task and credit records does not make media URLs permanently available.
The output URLs below are illustrative placeholders; use the exact URLs returned for your task. The billing amount matches the text-to-video example above: 720p, audio="native", 5 seconds, no video input, and the default account multiplier of 1.
{
"code": 0,
"message": "SUCCEED",
"request_id": "17e3534f-187c-4d48-bac5-390ab781d84c",
"data": [
{
"id": "ee831186-1034-4e58-8019-07b638d98f60",
"status": "succeeded",
"create_time": 1788998400000,
"update_time": 1788998520000,
"external_id": "omni-text-001",
"message": "",
"outputs": [
{
"type": "video",
"id": "ee831186-1034-4e58-8019-07b638d98f60",
"url": "https://media.example.com/results/omni-text-001.mp4?signature=example-video-signature",
"duration": "5",
"watermark_url": "https://media.example.com/results/omni-text-001-watermarked.mp4?signature=example-watermark-signature"
}
],
"billing": [{"charge_type": "unit", "amount": "173.08", "package_type": "video"}]
}
]
}
Failed task
The outer code=0 means the query succeeded. Check each task's status to determine whether generation succeeded. A failed task provides a safe explanation in its own message, with empty outputs and billing.
{
"code": 0,
"message": "SUCCEED",
"request_id": "d9d45514-4991-49c5-800d-6ac506f69c35",
"data": [
{
"id": "bc67a124-d19e-4428-a5ee-e2867221bd0a",
"status": "failed",
"create_time": 1788998400000,
"update_time": 1788998460000,
"external_id": "omni-failed-001",
"message": "The supplied contents or settings could not be processed. Check the text, media and generation settings.",
"outputs": [],
"billing": []
}
]
}
Callbacks
Set options.callback_url when creating a task. Use an HTTP(S) URL reachable from the platform API server's runtime environment, without a username or password. It must accept JSON POST requests directly; redirects are not followed. Example creation body:
{
"contents": [{"type": "prompt", "text": "A kitten running through a moonlit garden"}],
"settings": {"resolution": "720p", "duration": 5, "audio": "off", "multi_shot": false},
"options": {
"external_task_id": "omni-callback-001",
"callback_url": "https://app.example.com/webhooks/video",
"watermark_info": {"enabled": true}
}
}
Callback body
Callbacks are sent for terminal statuses succeeded and failed. The body is one task object with the same fields as an item in the GET query's data array. It has no outer code, request_id, or data wrapper.
Example success body for the callback request above (720p, audio="off", 5 seconds, no video input, and the default account multiplier of 1):
{
"id": "86f7dd26-3d85-4afc-89ab-30311e961d08",
"status": "succeeded",
"create_time": 1788998400000,
"update_time": 1788998520000,
"external_id": "omni-callback-001",
"message": "",
"outputs": [
{
"type": "video",
"id": "86f7dd26-3d85-4afc-89ab-30311e961d08",
"url": "https://media.example.com/results/omni-callback-001.mp4?signature=example-video-signature",
"duration": "5",
"watermark_url": "https://media.example.com/results/omni-callback-001-watermarked.mp4?signature=example-watermark-signature"
}
],
"billing": [{"charge_type": "unit", "amount": "115.38", "package_type": "video"}]
}
Example failure body:
{
"id": "86f7dd26-3d85-4afc-89ab-30311e961d08",
"status": "failed",
"create_time": 1788998400000,
"update_time": 1788998460000,
"external_id": "omni-callback-001",
"message": "Video generation could not be completed.",
"outputs": [],
"billing": []
}
These show alternative outcomes for the example request. As in GET responses, external_id is optional, duration and billing[].amount are strings, and timestamps are Unix milliseconds.
Signature verification
Configuring an independent Webhook Secret enables these headers. The secret is separate from your platform API key; it is not a field in the creation request.
| Header | Value |
|---|---|
Content-Type | application/json |
webhook-id | Event ID; retained across delivery retries |
webhook-timestamp | Unix seconds for this delivery attempt |
webhook-signature | v1, followed by a Base64 HMAC-SHA256 signature |
To verify a signed delivery:
- Preserve the exact raw request body before parsing JSON. Reformatting or serializing parsed JSON again changes the signed bytes.
- Remove the
whsec_prefix from your Webhook Secret and Base64-decode the remainder to obtain the signing key. - Join
webhook-id,webhook-timestamp, and the raw body with periods:eventId.timestamp.rawBody. - Compute HMAC-SHA256 with the decoded key and Base64-encode the digest. Compare it with the value after
v1,using a constant-time comparison. - Validate timestamp freshness using your receiver's replay window and synchronized clock, then deduplicate the event using
webhook-id.
The timestamp and signature are regenerated on retries; the event ID stays the same. Without a configured secret, all three webhook-* headers are omitted. For unsigned callbacks, use the task ID to retrieve the authoritative result through authenticated GET /tasks before applying business changes.
Acknowledgement, retries, and receiver handling
Return an HTTP 2xx response within 10 seconds to acknowledge delivery. The response body is ignored. A timeout, network error, or non-2xx response counts as failure; redirects are not followed.
| Attempt | Schedule |
|---|---|
| 1 | After the task reaches succeeded or failed |
| 2 | Scheduled 3 minutes after the first failed attempt |
| 3 | Scheduled 10 minutes after the second failed attempt |
There are at most three attempts. Retry times are scheduled delays; actual delivery may be later. GET queries remain available after retries are exhausted.
A receiver should verify the signature when configured, check that the task belongs to its records, and durably save or enqueue the event before returning 200 or 204. Process downloads and other slow work asynchronously. Apply each event once, using a persistent unique event ID for signed callbacks and idempotent task-status updates for all callbacks. A duplicate that was already accepted should receive a 2xx acknowledgement. If saving fails, return a non-2xx response so delivery can retry.
Callback delivery failure does not change a successful task into a failed task and does not trigger a refund. Reconcile through GET /tasks when your receiver misses an event; avoid creating a replacement task solely because a callback is late.
Billing
Unit rates are displayed to one decimal place. Settlement uses the configured rates before display rounding.
| Video input | Audio mode | 720p (credits/s) | 1080p (credits/s) | 4k (credits/s) |
|---|---|---|---|---|
| No video input | off | 23.1 | 30.8 | 115.4 |
| No video input | native | 34.6 | 46.2 | 115.4 |
feature_video or base_video | off | 34.6 | 46.2 | 115.4 |
base_video | original | 34.6 | 46.2 | 115.4 |
- No video input includes text-to-video, first-frame and first/last-frame generation, and image references.
feature_videosupports onlyoff;originalis available only withbase_video. - Charges use
round(round(rate × seconds, 2) × userMultiplier, 2): the applicable credits-per-second rate × billable output duration, rounded to two decimal places, then multiplied by your account multiplier (default1) and rounded to two decimal places again. The table uses the default multiplier. - Editing estimates use the input video's duration rounded to the nearest whole second. Video-reference estimates use only the output duration; reference-video duration is not added.
- Credits are precharged and reconciled against actual successful usage. Each task retains the rate and account multiplier from its creation.
- A successful task's final
billingis authoritative:amountis the actual platform-credit charge as a decimal string, withcharge_type="unit"andpackage_type="video". - Only confirmed failures are refunded. An unknown submission outcome does not trigger an automatic refund. Output transfer or callback failures after successful generation do not trigger automatic refunds. Cancellation is unsupported.
For example, 5 seconds at 720p with no video input and audio="off" costs 115.38 credits using the configured rate and the default account multiplier of 1.