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

FieldAccepted values and behavior
settings.resolution720p (default), 1080p, or 4k
settings.durationInteger from 3–15 seconds; default 5. With feature_video, 3–10 seconds. Editing follows the input duration; omit this field for editing.
settings.aspect_ratio16:9 (default), 9:16, or 1:1. First-frame generation and editing follow the input aspect ratio.
settings.audiooff (default) or native for generation without video input. feature_video requires off. base_video accepts off or original.
settings.multi_shotBoolean, default true. Editing requires explicit false.
options.external_task_idOptional client task ID, unique within the same account and model. Reusing the ID with the same parameters returns the existing task without another charge; different parameters produce an error.
options.callback_urlOptional HTTP(S) URL reachable from the platform API server's runtime environment, without a username or password. Receives state or terminal notifications depending on the task’s callback mode. See Callbacks.
options.watermark_info.enabledBoolean, 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. A first frame cannot be combined with reference images. Video-reference output is limited to 3–10 seconds and cannot use explicit shots. Unsupported combinations are rejected rather than silently dropping media or changing the requested capability. 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.

Service image limits are JPEG/JPG/PNG without transparency, dimensions of 300–8000 pixels, aspect ratio 1:2.5–2.5:1, and up to 10 MB. Ordinary prompts should stay within 2500 characters and shot descriptions within 512 characters to avoid shortening during generation. The entire JSON request body is limited to 4.5 MB by the current deployment, including Base64 overhead; use URLs for large images. See request body limits.

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: []. Each task is returned once even when its ID is repeated.

The shared query includes standard 3.0 official-protocol, Omni, and Turbo tasks for the current account. External IDs are deduplicated within each model; cross-model matches are all returned. Keep external IDs globally unique in your integration to avoid ambiguity. Queries only read saved platform records and do not poll the generation service.

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": []
    }
  ]
}

Filter and paginate

Send POST /tasks. By default, it queries the previous 30 days, ending now, with up to 100 tasks per page. limit accepts integers from 1 to 500. start_time and end_time accept Unix milliseconds; digit-only millisecond timestamp strings remain supported.

{
  "start_time": 1789603200000,
  "end_time": 1789689600000,
  "limit": 100,
  "filters": [
    {"key": "status", "values": ["succeeded"]},
    {"key": "product_type", "values": ["video"]}
  ]
}

status accepts submitted, processing, succeeded, and failed. product_type supports the official video, image, and try_on values, but this endpoint currently has only standard 3.0 official-protocol, Omni, and Turbo video tasks; selecting only other product types returns no tasks.

Example last page:

{
  "code": 0,
  "message": "SUCCEED",
  "request_id": "3d6a01c0-a624-4934-9361-15d09a4c1586",
  "data": {
    "result": [{
      "id": "ee831186-1034-4e58-8019-07b638d98f60",
      "status": "succeeded",
      "create_time": 1789603200000,
      "update_time": 1789603320000,
      "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", "duration": "5"}],
      "billing": [{"charge_type": "unit", "amount": "173.08", "package_type": "video"}]
    }],
    "count": 1,
    "next_cursor": "",
    "has_more": false
  }
}

When has_more=true, pass the returned next_cursor unchanged:

{"cursor": "REPLACE_WITH_NEXT_CURSOR", "limit": 100}

The cursor preserves the time window, filters, and model scope; do not reconstruct it. Tasks are ordered newest first, using task ID to break equal creation times. Existing v1 cursors continue querying only Omni; v2 cursors retain Omni + Turbo. New v3 cursors include standard 3.0 official-protocol, Omni, and Turbo tasks. count is the number of tasks in the current page.

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

For tasks created after the platform enables state callbacks, each observed transition to submitted, processing, or succeeded/failed produces an event. Intermediate states that were not observed are not fabricated. Existing tasks and tasks created before activation keep terminal-only callbacks. An idempotent retry of an existing task never upgrades its callback mode or creates missing events. The platform controls this mode; there is no additional request field. 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.

Each event preserves the task at that transition. Success events are created only after credit settlement. A submitted event for a task in state-callback mode looks like this:

{
  "id": "86f7dd26-3d85-4afc-89ab-30311e961d08",
  "status": "submitted",
  "create_time": 1788998400000,
  "update_time": 1788998400000,
  "external_id": "omni-callback-001",
  "message": "",
  "outputs": [],
  "billing": []
}

A processing event uses the same shape with the new status and update time. 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.

HeaderValue
Content-Typeapplication/json
webhook-idEvent ID; retained across delivery retries
webhook-timestampUnix seconds for this delivery attempt
webhook-signaturev1, followed by a Base64 HMAC-SHA256 signature

To verify a signed delivery:

  1. Preserve the exact raw request body before parsing JSON. Reformatting or serializing parsed JSON again changes the signed bytes.
  2. Remove the whsec_ prefix from your Webhook Secret and Base64-decode the remainder to obtain the signing key.
  3. Join webhook-id, webhook-timestamp, and the raw body with periods: eventId.timestamp.rawBody.
  4. Compute HMAC-SHA256 with the decoded key and Base64-encode the digest. Compare it with the value after v1, using a constant-time comparison.
  5. 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. Omni always uses the Webhook Secret captured when the task was created, including new state-callback tasks. Updating or removing the account secret affects only future tasks. Keep the historical verification key available until existing tasks finish delivery; this endpoint does not use the standard/Turbo seven-day rotation mechanism. 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.

import { Webhook } from "standardwebhooks";

const rawBody = await request.text();
const task = new Webhook(process.env.OMNI_WEBHOOK_SECRET).verify(rawBody, {
  "webhook-id": request.headers.get("webhook-id"),
  "webhook-timestamp": request.headers.get("webhook-timestamp"),
  "webhook-signature": request.headers.get("webhook-signature"),
});
// Persist by event ID before acknowledging; retain keys for older tasks.

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.

AttemptSchedule
1When the event is ready for delivery
2Scheduled 3 minutes after the first failed attempt
3Scheduled 10 minutes after the second failed attempt

There are at most three attempts per event. State-callback events are delivered in task order. Retries of earlier events may delay later notifications, but never block generation or settlement. Event IDs and bodies remain unchanged across retries. 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 inputAudio mode720p (credits/s)1080p (credits/s)4k (credits/s)
No video inputoff23.130.8115.4
No video inputnative34.646.2115.4
feature_video or base_videooff34.646.2115.4
base_videooriginal34.646.2115.4
  • No video input includes text-to-video, first-frame and first/last-frame generation, and image references. feature_video supports only off; original is available only with base_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 (default 1) 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 billing is authoritative: amount is the actual platform-credit charge as a decimal string, with charge_type="unit" and package_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.