Kling 3.0 Official Protocol

The standard Kling 3.0 official protocol creates 3–15 second videos from text, a first frame, or first and last frames, at 720p, 1080p, or 4K, with optional generated audio.

To migrate a client using the official Kling 3.0 protocol, set base_url to https://api.aivideoapi.ai and replace its API key with your platform API key. Keep the endpoint paths and request/response field names below. Input limits and credit billing follow this page.

Method and pathPurpose
POST /text-to-video/kling-3.0Text-to-video
POST /image-to-video/kling-3.0First-frame or first/last-frame image-to-video
GET /tasksQuery by task IDs or external IDs
POST /tasksFilter and paginate tasks

All endpoints use Authorization: Bearer YOUR_PLATFORM_API_KEY; JSON requests use Content-Type: application/json. This protocol uses the paths above directly, without adding /v1.

The platform model and Price Group identifier is kling-3.0-official. Do not send a model field; the public path remains kling-3.0. Existing unified API clients can keep using the original Kling 3.0 documentation.

Create a task

Text-to-video

A minimal request defaults to 720p, 5 seconds, 16:9, audio off, intelligent shot planning enabled, and watermark disabled. Set audio="native" to generate audio.

curl -X POST 'https://api.aivideoapi.ai/text-to-video/kling-3.0' \
  -H 'Authorization: Bearer YOUR_PLATFORM_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"prompt":"A kitten runs through a moonlit garden, with rustling leaves and soft footsteps."}'

For vertical 1080p output, a callback, and a watermarked copy:

{
  "prompt": "A girl watches the passing landscape from a train window, with the gentle sound of the train.",
  "settings": {"resolution": "1080p", "duration": 5, "aspect_ratio": "9:16"},
  "options": {
    "external_task_id": "standard-text-001",
    "callback_url": "https://app.example.com/webhooks/video",
    "watermark_info": {"enabled": true}
  }
}

The remaining creation examples are complete JSON bodies. Use the matching text or image endpoint. Replace example media and callback URLs with your own reachable URLs.

First-frame image-to-video

Send exactly one first_frame and optionally one prompt to POST /image-to-video/kling-3.0. Output aspect ratio follows the image; omit settings.aspect_ratio.

{
  "contents": [
    {"type": "prompt", "text": "The kitten looks toward the camera as a breeze moves its fur, with birdsong in the distance."},
    {"type": "first_frame", "url": "https://media.example.com/kitten.jpg"}
  ],
  "settings": {"resolution": "720p", "duration": 5},
  "options": {"external_task_id": "standard-image-001"}
}

A first frame without a prompt is also accepted:

{
  "contents": [{"type": "first_frame", "url": "https://media.example.com/kitten.jpg"}]
}

First and last frames

Supply one first frame and one last frame to constrain the beginning and end of the video.

{
  "contents": [
    {"type": "prompt", "text": "The camera moves forward steadily as the kitten stands and walks into the garden."},
    {"type": "first_frame", "url": "https://media.example.com/start.jpg"},
    {"type": "last_frame", "url": "https://media.example.com/end.jpg"}
  ],
  "settings": {"resolution": "1080p", "duration": 5, "audio": "off", "multi_shot": false},
  "options": {"external_task_id": "standard-frames-001"}
}

4K with audio

{
  "prompt": "A city sunrise timelapse with soft music and a stable horizon.",
  "settings": {"resolution": "4k", "duration": 10, "aspect_ratio": "16:9", "audio": "native", "multi_shot": false},
  "options": {"external_task_id": "standard-4k-001"}
}

Base64 first frame

Both first-frame and last-frame contents[].url accept PNG/JPEG Base64, with or without a data URL prefix. Replace the placeholder below with your full image data. The bytes are preserved during temporary upload; the platform does not resize or compress the image. Prefer a URL for large files.

{
  "contents": [
    {"type": "prompt", "text": "A slow camera push toward the subject, with soft ambient sound."},
    {"type": "first_frame", "url": "data:image/jpeg;base64,REPLACE_WITH_FULL_IMAGE_BASE64"}
  ],
  "settings": {"resolution": "1080p", "duration": 8},
  "options": {"external_task_id": "standard-base64-001"}
}

Explicit shots

Use the literal format 镜头 n, seconds, description;, with ASCII commas and semicolons, including for English descriptions. Number 1–6 shots consecutively from 1. Each duration must be an integer of at least 1 second, and the total must equal settings.duration. Keep each shot description within 512 characters.

settings.multi_shot defaults to true: ordinary prompts use intelligent shot planning, and the recognized format uses explicit shots. When set to false, the original prompt remains unchanged and generation uses a single shot even if the prompt contains shot syntax.

{
  "prompt": "镜头 1, 2, Wide shot of a moonlit garden with rustling leaves;镜头 2, 3, Close-up of a kitten looking toward the moon with soft footsteps;",
  "settings": {"resolution": "720p", "duration": 5, "aspect_ratio": "16:9"},
  "options": {"external_task_id": "standard-shots-001"}
}

The same shot format works in an image task's prompt item:

{
  "contents": [
    {"type": "prompt", "text": "镜头 1, 2, The kitten turns toward the camera;镜头 2, 3, The kitten walks away through the garden;"},
    {"type": "first_frame", "url": "https://media.example.com/kitten.jpg"}
  ],
  "settings": {"resolution": "1080p", "duration": 5},
  "options": {"external_task_id": "standard-image-shots-001", "watermark_info": {"enabled": true}}
}

Parameters and input limits

FieldAccepted values and behavior
promptRequired text for text-to-video; write both positive and negative descriptions here
contentsRequired for image-to-video: one first_frame, optionally one last_frame, and at most one prompt
contents[].typefirst_frame / last_frame with url, or prompt with text
settings.resolution720p (default), 1080p, or 4k
settings.audiooff (default) or native; original is unsupported
settings.multi_shotBoolean, default true; set to false for a single shot
settings.durationInteger from 3 to 15 seconds; default 5
settings.aspect_ratioText-to-video only: 16:9 (default), 9:16, or 1:1
options.external_task_idOptional client ID; see idempotency below
options.callback_urlOptional HTTP(S) endpoint for state-change notifications
options.watermark_info.enabledBoolean, default false; enables an additional watermarked copy

This endpoint does not support a last frame without a first frame, reference images/videos, video editing, element IDs or element management, or a separate negative prompt field. Write both positive and negative descriptions in the official prompt field.

Use JPEG/JPG/PNG images without transparency, with both dimensions between 300 and 8000 pixels, aspect ratio between 1:2.5 and 2.5:1, and file size no greater than 10 MB. Keep ordinary prompts within 2500 characters. These service limits are narrower than the official standard-model image limit of 50 MB and text-to-video prompt limit of 3072 characters.

The platform does not add image-size or prompt-length checks, compress images, or truncate text. Inputs are submitted unchanged apart from protocol conversion; generation can reject inputs outside the limits, and returns a cleaned error. Explicit shot descriptions should stay within 512 characters to avoid shortening during generation.

The current deployment limits the entire JSON request body to 4.5 MB, including Base64 overhead. Oversized requests can be rejected before the API runs. Use HTTP(S) URLs for larger images. See request body limits.

Media URLs must allow file download without login. Callback URLs must be reachable from the API server and accept POST directly. Both must use HTTP(S) without a username or password. Callback redirects are not followed.

Idempotency and creation response

Within the same account and model, retrying the same options.external_task_id with identical parameters returns the existing task without another charge. Different parameters, including changing text-to-video to image-to-video, produce a conflict. Use a new ID for a new task. IDs are scoped by model; use globally unique IDs across your integration to avoid ambiguity in queries. An omitted or empty external ID does not provide idempotency.

Successful creation returns an asynchronous task summary:

{
  "code": 0,
  "message": "SUCCEED",
  "request_id": "81bb383c-bf77-41dc-b123-dc5f0688a064",
  "data": {
    "id": "29bd04f8-3c15-4374-a364-4b484782d235",
    "status": "submitted",
    "create_time": 1789603200000,
    "update_time": 1789603200000,
    "external_id": "standard-text-001"
  }
}

external_id appears only when supplied. Timestamps are Unix milliseconds. Creation does not include outputs, billing, or task-level message. An idempotent retry can return a later status.

Query by ID

Use GET /tasks and specify exactly one of task_ids or external_task_ids. Each accepts comma-separated IDs.

curl --get 'https://api.aivideoapi.ai/tasks' \
  -H 'Authorization: Bearer YOUR_PLATFORM_API_KEY' \
  --data-urlencode 'task_ids=29bd04f8-3c15-4374-a364-4b484782d235'
curl --get 'https://api.aivideoapi.ai/tasks' \
  -H 'Authorization: Bearer YOUR_PLATFORM_API_KEY' \
  --data-urlencode 'external_task_ids=standard-text-001,standard-image-001'

The shared endpoint returns your matching standard 3.0 official-protocol, Omni, and Turbo tasks. When models share an external ID, all matching tasks are returned. Missing tasks and other users' tasks are omitted; no matches returns data: []. A task is returned once even if its ID is repeated. Queries read saved platform records; they do not trigger generation or polling.

Processing response

{
  "code": 0,
  "message": "SUCCEED",
  "request_id": "d482570f-e19c-4d82-af57-4959ef8bf837",
  "data": [{
    "id": "29bd04f8-3c15-4374-a364-4b484782d235",
    "status": "processing",
    "create_time": 1789603200000,
    "update_time": 1789603230000,
    "external_id": "standard-text-001",
    "message": "",
    "outputs": [],
    "billing": []
  }]
}

submitted means accepted or waiting; processing covers generation, recording the result, and final credit settlement. Both have empty outputs and billing.

Success response

This example corresponds to the 1080p, 5-second text task above, with an account multiplier of 1.

{
  "code": 0,
  "message": "SUCCEED",
  "request_id": "9ebfc933-3d04-424b-9f11-707d0c701ce1",
  "data": [{
    "id": "29bd04f8-3c15-4374-a364-4b484782d235",
    "status": "succeeded",
    "create_time": 1789603200000,
    "update_time": 1789603320000,
    "external_id": "standard-text-001",
    "message": "",
    "outputs": [{
      "type": "video",
      "id": "29bd04f8-3c15-4374-a364-4b484782d235",
      "url": "https://media.example.com/results/standard-text-001.mp4?signature=example",
      "watermark_url": "https://media.example.com/results/standard-text-001-watermarked.mp4?signature=example",
      "duration": "5"
    }],
    "billing": [{"charge_type": "unit", "amount": "153.85", "package_type": "video"}]
  }]
}

Use the exact url and optional watermark_url, including all signature parameters. The platform passes these addresses through without replacing the domain or copying the files. Download promptly; URLs can expire. Task and billing retention does not extend media availability, and the platform does not guarantee at least 30 days of download availability. duration and billing[].amount are decimal strings.

Failure response

The outer code=0 means the query succeeded; inspect the task's status for its outcome.

{
  "code": 0,
  "message": "SUCCEED",
  "request_id": "42685723-917a-4ea7-82ef-cdf7c03aeaa9",
  "data": [{
    "id": "7689f980-0f92-4d31-bc7b-bc848d051d70",
    "status": "failed",
    "create_time": 1789603200000,
    "update_time": 1789603260000,
    "external_id": "standard-failed-001",
    "message": "Video generation could not be completed.",
    "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": "29bd04f8-3c15-4374-a364-4b484782d235",
      "status": "succeeded",
      "create_time": 1789603200000,
      "update_time": 1789603320000,
      "external_id": "standard-text-001",
      "message": "",
      "outputs": [{"type": "video", "id": "29bd04f8-3c15-4374-a364-4b484782d235", "url": "https://media.example.com/results/standard-text-001.mp4?signature=example", "duration": "5"}],
      "billing": [{"charge_type": "unit", "amount": "153.85", "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 at creation. Standard 3.0 sends one event for each observed state change: submitted, processing, and succeeded or failed. Intermediate states that were never observed are not fabricated. Duplicate queries or idempotent creation retries do not create additional events.

The body is a single task object, with the same fields as one query result. There is no code, request_id, or data wrapper. Each event preserves the task snapshot at that transition. A success event is created only after final credit settlement.

Submitted callback example:

{
  "id": "29bd04f8-3c15-4374-a364-4b484782d235",
  "status": "submitted",
  "create_time": 1789603200000,
  "update_time": 1789603200000,
  "external_id": "standard-text-001",
  "message": "",
  "outputs": [],
  "billing": []
}

A processing event uses the same shape, with its status and update time changed. Success example:

{
  "id": "29bd04f8-3c15-4374-a364-4b484782d235",
  "status": "succeeded",
  "create_time": 1789603200000,
  "update_time": 1789603320000,
  "external_id": "standard-text-001",
  "message": "",
  "outputs": [{
    "type": "video",
    "id": "29bd04f8-3c15-4374-a364-4b484782d235",
    "url": "https://media.example.com/results/standard-text-001.mp4?signature=example",
    "watermark_url": "https://media.example.com/results/standard-text-001-watermarked.mp4?signature=example",
    "duration": "5"
  }],
  "billing": [{"charge_type": "unit", "amount": "153.85", "package_type": "video"}]
}

A failed callback has status="failed", an explanatory message, and empty outputs and billing, as in the failure query object above.

Signing and verification

Ask your account administrator to configure an independent standard 3.0 Webhook Secret, separate from the platform API key. It is not a creation-request field. Signing uses the current secret when each delivery is attempted. Regular rotation signs with both the new key and the preceding key for seven days; emergency revocation removes the old key immediately. Removing the configuration disables signing, including for pending events.

HeaderValue
webhook-idStable event ID across retries; each state change has its own ID
webhook-timestampUnix seconds for this delivery attempt
webhook-signatureOne or more space-separated v1,BASE64_SIGNATURE values

Use Standard Webhooks verification on the raw request body. For example, with the standardwebhooks JavaScript package:

import { Webhook } from "standardwebhooks";

const rawBody = await request.text();
const verifiedTask = new Webhook(process.env.STANDARD_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 this event idempotently before acknowledging it.

For a custom verifier, remove the whsec_ prefix and Base64-decode the secret. Sign webhook-id.webhook-timestamp.rawBody with HMAC-SHA256, then Base64-encode the digest. Accept a constant-time match against any supported v1 signature, check a recent timestamp window (typically five minutes), and deduplicate by event ID. Never reserialize parsed JSON for verification.

Without a configured secret, the three webhook-* headers are omitted. For unsigned deliveries, confirm the current task through authenticated GET /tasks before applying business changes. Make status updates idempotent and avoid regressing a newer terminal state.

Delivery and retries

Return HTTP 2xx within 10 seconds after durably saving or enqueueing the event. Process video downloads asynchronously. Timeout, network error, non-2xx, and redirects count as failed deliveries.

  • Attempt 1: when the event becomes available for delivery.
  • Attempt 2: scheduled 3 minutes after the first failure.
  • Attempt 3: scheduled 10 minutes after the second failure.

Each event receives at most three attempts. Per-task events are delivered in order; an older event's retries can delay later callbacks, but do not delay generation or settlement. Retries keep the event ID and body, with a fresh timestamp and signature. Actual delivery may occur later than the scheduled time. After attempts are exhausted, query the task to reconcile your records.

Callback failure never changes successful generation to failure and never causes a refund or another generation request.

Billing

  • 720p: 23.1 credits/second without audio; 34.6 credits/second with audio.
  • 1080p: 30.8 credits/second without audio; 46.2 credits/second with audio.
  • 4K: 115.4 credits/second with or without audio.
  • Text, first-frame, and first/last-frame generation use the same rates. These base rates assume an account multiplier of 1. Displayed unit rates use one decimal place; settlement uses the configured rate before display rounding.
  • Credits are precharged for the requested duration and settled against actual successful usage: round(round(rate × seconds, 2) × accountMultiplier, 2). Every task retains its original rate and multiplier.
  • At the default multiplier, a 5-second silent video costs 115.38 credits at 720p, 153.85 at 1080p, or 576.92 at 4K. Do not calculate the total from the one-decimal display rate.
  • billing[].amount is the actual platform-credit charge as a decimal string, with charge_type="unit" and package_type="video".
  • Confirmed failure refunds the precharge once. Unknown submission or task status does not trigger resubmission or automatic refund. Errors after generation success, including settlement retries and callback failures, cannot trigger failure refunds. Cancellation is unsupported.

Migrate an official client

Replace https://api-beijing.klingai.com with https://api.aivideoapi.ai and use your platform API key. Keep the official paths, prompt / contents, settings, options, and response parsing. Do not add /v1 or put the internal model identifier in the URL.

Before migrating, review the input limits, unsupported elements, credit charges, and independent callback secret on this page. The unified API's model="kling-3.0" is separate, with separate rates and account multipliers. Its request body is not the official-protocol request body.