Skip to navigation

Kling V4

Generate 3–30 second videos at 720p or 1080p with generated audio, from text, frames in time order, or reference images, videos, voices and named elements; billed per second.

  • Asynchronous: the create call returns a task ID; the video arrives when the task succeeds.
  • Four ways in: text only, frames (images in time order), reference images, videos and voices, and up to seven named elements. Frames cannot be combined with references or elements.
  • Name every input in the prompt: @image_1, @video_1, @voice_1, @ plus an element name, @first_frame, @keyframe_1 and @last_frame. Every @ must name an input of the same request.
  • Audio is always generated. keep_original_sound keeps the reference videos’ own sound instead.
  • duration runs from 3 to 30 seconds (5 by default) at 720p (the default) or 1080p. Billed per second at the resolution you choose; a failed task costs nothing.
POST/v1/videos/tasksTry it

Opens this model in the API Explorer. Enter your BeatAPI API key to create a task: the call is real and is billed to your own balance.

Model IDs

Two Kling generation models share this endpoint. The values below come straight from the gateway contract; only Kling V4 takes reference inputs, more than two frames and up to seven elements.

Model IDduration (s)resolutionMax framesMax reference imagesMax elementsChoose it when
kling-v43–30720p, 1080p10107You need up to 30 seconds, reference images, videos or voices, middle frames, or more than three elements.
kling-v33–15std, pro2—3You need multi-shot storyboards, a video without sound, or a lower price per second.

Endpoint and authentication

POST https://api.beatapi.io/v1/videos/tasks

Authorization string Required

Your BeatAPI API key, sent as Bearer <BEATAPI_API_KEY>. Create keys in the Dashboard. Keep keys on your server; never ship them in a browser or mobile app.

Send the body as JSON with Content-Type: application/json. Idempotency-Key is optional: send a unique value (at most 255 characters) per logical request and reuse it only to retry that exact body. Within 24 hours a retry with the same key and body returns the first response again with Idempotent-Replayed: true; the same key with a different body returns 409 idempotency_conflict. Responses other than 2xx are not stored, so a retry after a 400 or 402 runs again.

How a request works

1

Create the task

POST the parameters below to the endpoint. A 201 means the task was accepted and its price reserved from your balance; the work runs in the background. Save data.id.

2

Wait for it to finish

Call GET /v1/tasks/{task_id} and wait data.poll_after_seconds between calls (5 s for images, 8 s for videos) until status is succeeded or failed. Or register a webhook for task.succeeded and task.failed; keep polling as the fallback, because a task stopped by the processing timeout sends no event.

3

Save the result

On succeeded, download every data.output.media[].url and store the files you need; BeatAPI does not promise how long result URLs stay available. On failed, read data.error_code and data.error_message: the reserved amount was returned to your balance, and data.retryable says whether sending the same request again can succeed.

Input modes

ModeRequired inputsNotes
Text to videomodel, promptSend no media. Without aspect_ratio the video is 16:9.
First framemodel, prompt, images (1 link)The video starts from the image and takes its shape.
First and last framemodel, prompt, images (2 links)images[0] is the first frame, images[1] the last.
Framesmodel, prompt, images (3 to 10 links)First frame, middle frames and last frame in time order; at most one image more than the seconds of the video.
References and elementsmodel, prompt, and any of reference_images, reference_videos, reference_audios, elementsAny mix within the limits below. Cannot be combined with images. Name each input in the prompt.

Request parameters

model string Required

The model to run.

Value: kling-v4

If the value is wrong

  • Missing: "model" is required
  • An image model sent to this endpoint: "model" nano-banana-2 is served by POST /v1/images/tasks, not this endpoint

prompt string Required

What happens in the video: subject, action, camera movement, style and sound, with each input named by its @ mention.

Length: 1–5000 characters

  • Length is counted in characters (a CJK character counts as one).
  • Mentions: reference_images are @image_1, @image_2 …, reference_videos are @video_1 …, reference_audios are @voice_1 …, and an element is @ followed by its name. Frames are @first_frame, @keyframe_1, @keyframe_2 … and @last_frame.
  • Every @ must name an input of the same request. A numbered or frame mention with nothing behind it, such as @image_3 with two reference images or @last_frame with one image, is refused when the task is created.

If the value is wrong

  • Missing: "prompt" is required
  • Empty or longer than the limit: "prompt" has an unsupported length
  • A mention of an input the request does not send: the prompt names @image_3, which this request does not send

images string[] Optional

Frames in time order: one link is the first frame, two are the first and last frame, and more add middle frames between them.

Items: 1–10
Each item is a public https:// URL. For a local file, upload it first with POST /v1/files and pass the returned data.url.

  • With three or more links, images[0] is the first frame and the last link the last frame; the links in between are middle frames, so images[1] is @keyframe_1, images[2] is @keyframe_2, and so on.
  • A video takes at most one image more than its seconds (duration + 1, counting 5 seconds when duration is left out), and never more than 10.
  • Frames cannot be sent with reference_images, reference_videos, reference_audios, elements or aspect_ratio: the video takes the shape of the first frame.

If the value is wrong

  • More than 10 links: "images" accepts at most 10 items
  • More links than duration + 1 (here 7 links for a 5-second video): Kling V4 takes at most 6 images for a 5-second video
  • Combined with any reference_* field: Cannot combine "images" with reference inputs in one task
  • Combined with elements: Kling V4 cannot combine elements with images
  • Combined with aspect_ratio: Kling V4 takes the first frame's shape; do not send aspect_ratio with images
  • Not an https:// link: "images[0]" must be a public HTTPS URL

reference_images string[] Optional

Pictures that guide the content, characters, products or style of the video. Name them in the prompt as @image_1, @image_2 … in list order.

Items: 1–10
Each item is a public https:// URL. For a local file, upload it first with POST /v1/files and pass the returned data.url.

  • Cannot be combined with images.
  • Count toward the limit of 15 reference inputs and elements together.

If the value is wrong

  • More than the maximum: "reference_images" accepts at most 10 items
  • More than 15 reference inputs and elements together: Kling V4 takes at most 15 reference inputs and elements together

reference_videos string[] Optional

Videos to take motion, camera work or content from. Name them in the prompt as @video_1, @video_2 … in list order.

Items: 1–5
Each item is a public https:// URL. For a local file, upload it first with POST /v1/files and pass the returned data.url.

  • Each clip runs 2 to 30 seconds, and all clips together at most 30 seconds. The gateway measures each clip before creating the task and refuses one outside these limits, naming it.
  • Reference videos and video elements together are at most 5, and count toward the limit of 15 reference inputs and elements.
  • The finished video has generated audio unless you send keep_original_sound: true, which keeps the reference videos’ own sound.

If the value is wrong

  • More than the maximum: "reference_videos" accepts at most 5 items
  • A clip shorter than 2 or longer than 30 seconds: reference_videos[0] is 35 seconds long; this model takes reference video of 2 to 30 seconds.
  • Clips that run longer than 30 seconds together: The reference videos run 36 seconds in total; this model takes at most 30.
  • More than 5 reference videos and video elements together: Kling V4 takes at most 5 reference videos and video elements together

reference_audios string[] Optional

Voices for the video. Name them in the prompt as @voice_1, @voice_2 … in list order.

Items: 1–3
Each item is a public https:// URL. For a local file, upload it first with POST /v1/files and pass the returned data.url.

  • Cannot be combined with images.
  • Count toward the limit of 15 reference inputs and elements together.

If the value is wrong

  • More than the maximum: "reference_audios" accepts at most 3 items

elements object[] Optional

Up to seven named subjects, such as a character, an animal, a prop, a costume, a scene or an effect, each defined once and named in the prompt as @ followed by its name.

Items: ≤ 7

  • An array of at most seven objects. Each object accepts these keys and no others:
  • elements[].name (string, required): 1 to 20 letters, digits, underscores or Chinese characters, unique within the request ignoring case. It cannot be image_N, video_N, voice_N, keyframe_N, object_N, audio_N, first_frame or last_frame.
  • elements[].element_input_urls (array of strings): 2 to 4 public HTTPS links to pictures of the element; the first is its main view.
  • elements[].element_input_video_urls (array of strings): exactly one public HTTPS link to a 3 to 8 second single-shot video of a character. Send this or element_input_urls, not both.
  • elements[].element_input_audio_urls (array of strings, optional): exactly one public HTTPS audio link, the voice of a character element.
  • elements[].tag (string, optional): what the element is. A video element, or an element with a voice, must be a character: leave tag out or send character.
  • elements[].description (string, optional): what the element is, at most 100 characters.
  • Video elements are at most 3, and at most 5 together with reference_videos. Every element counts toward the limit of 15 reference inputs and elements.
  • Elements cannot be sent with images.

If the value is wrong

  • More than seven elements: "elements" accepts at most 7 items
  • An element that is not an object: "elements[0]" must be an object
  • An element without name: "name" is required in "elements[0]"
  • A name that is empty or longer than 20: "elements[0].name" has an unsupported length
  • A name with other characters, or a reserved name: elements[0].name "image_1" is not a name Kling V4 accepts
  • The same name twice, ignoring case: elements[1].name "Hero" is used twice
  • Both pictures and a video, or neither: elements[0] takes either element_input_urls or element_input_video_urls
  • Fewer than two pictures: "elements[0].element_input_urls" requires at least 2 item
  • More than four pictures: "elements[0].element_input_urls" accepts at most 4 items
  • A video element whose tag is not character: elements[0] is a video element, which is always a character
  • A voice on an element whose tag is not character: elements[0] has a voice, which only a character element takes
  • A tag not in the list: "elements[0].tag" must be one of: [character animal prop costume scene effect others]
  • A description longer than 100 characters: "elements[0].description" has an unsupported length
  • A key that an element does not accept: field "start_time" is not supported in "elements[0]"
  • More than three video elements: Kling V4 takes at most 3 video elements
  • Combined with images: Kling V4 cannot combine elements with images

duration integer OptionalDefault: 5

Length of the video in seconds, a whole number. It is what you are billed for.

Default: 5
Range: 3–30

  • If you leave it out, 5 is used and billed.
  • With frames it also caps the number of images: at most duration + 1, and never more than 10.

If the value is wrong

  • Outside the range, not a whole number, or sent as a string: "duration" is outside its supported range

aspect_ratio string OptionalDefault: 16:9

Shape of the video as width:height.

Allowed values: 16:9, 9:16, 1:1, 21:9
Default: 16:9

  • If you leave it out, 16:9 is used.
  • Do not send it with images: the video takes the shape of the first frame.

If the value is wrong

  • A value not in the list: "aspect_ratio" must be one of: [16:9 9:16 1:1 21:9]
  • Sent with images: Kling V4 takes the first frame's shape; do not send aspect_ratio with images

resolution string OptionalDefault: 720p

Output resolution. 1080p costs more per second than 720p.

Allowed values: 720p, 1080p
Default: 720p

  • If you leave it out, 720p is used and billed.
  • 4K is not available on this model.

If the value is wrong

  • A value not in the list (for example 4K or pro): "resolution" must be one of: [720p 1080p]

keep_original_sound boolean Optional

Keeps the reference videos’ own sound in the finished video instead of generated audio.

  • Only valid with reference_videos; sending it without them, even as false, is refused.
  • Without it the video comes with generated audio. There is no field that turns audio off.

If the value is wrong

  • Not true or false: "keep_original_sound" must be a boolean
  • Sent without reference_videos: "keep_original_sound" needs reference_videos

The gateway also checks these combinations before creating the task:

  • images cannot be combined with reference inputs
  • images are frames in time order: one is the first frame, two the first and last, more add middle frames between them; the prompt names them @first_frame, @keyframe_1, @keyframe_2 … and @last_frame
  • a video takes at most one image more than its seconds, and never more than 10
  • the prompt names reference_images as @image_1, @image_2 …, reference_videos as @video_1 …, reference_audios as @voice_1 … and elements as @ followed by their name; every @ in the prompt must name an input of the same request
  • reference videos run 2-30 seconds each and 30 seconds together; reference videos and video elements are at most 5 together, video elements at most 3; reference_images, reference_videos, reference_audios and elements are at most 15 together
  • an element is 2-4 images in element_input_urls, the first its main view, or one 3-8 second single-shot character video in element_input_video_urls; element_input_audio_urls gives a character element its voice
  • element names are 1-20 letters, digits, underscores or Chinese characters, unique ignoring case, and not image_N, video_N, voice_N, keyframe_N, object_N, audio_N, first_frame or last_frame
  • elements and aspect_ratio cannot be sent with images: the output takes the first frame’s shape; without images aspect_ratio defaults to 16:9
  • keep_original_sound keeps the reference videos’ own audio and needs reference_videos; otherwise the video comes with generated audio

Input media limits

The gateway reads every input before the task is created and refuses one outside these limits with a 400 bad_request that names the input. Nothing is charged.

MediaLimits checked before the task is created
Imageswidth and height 300–65536 px; aspect ratio (width ÷ height) 0.4–2.5
Videoseach 2–30 s; 30 s in total
  • The gateway measures images, reference_images and reference_videos before the task is created and refuses an input outside these limits with a message that names it by list and position, for example reference_videos[0] is 35 seconds long; this model takes reference video of 2 to 30 seconds. Nothing is charged.
  • Element links and reference_audios are only checked for being public HTTPS links before the task is created. An element video must run 3 to 8 seconds.
  • Have a local file? Upload it with POST /v1/files and pass the returned data.url.

Prompt mentions

Each kind of input has its own mention, numbered from 1 in list order:

MentionNamesAvailable when
@image_1, @image_2 …reference_imagesAt least that many reference images are sent
@video_1, @video_2 …reference_videosAt least that many reference videos are sent
@voice_1, @voice_2 …reference_audiosAt least that many reference audio links are sent
@ + element nameThe element with that nameThe element is in elements
@first_frameimages[0]At least one image is sent
@keyframe_1, @keyframe_2 …The middle frames, from images[1]Three or more images are sent
@last_frameThe last link in imagesTwo or more images are sent
  • A numbered or frame mention with nothing behind it is refused when the task is created, for example the prompt names @last_frame, which this request does not send.

Combination rules

These are checked when the task is created; a request that breaks one is refused with 400 bad_request and costs nothing.

RuleMessage
images with any reference_* fieldCannot combine "images" with reference inputs in one task
images with elementsKling V4 cannot combine elements with images
images with aspect_ratioKling V4 takes the first frame's shape; do not send aspect_ratio with images
More images than duration + 1 (here a 5-second video)Kling V4 takes at most 6 images for a 5-second video
keep_original_sound without reference_videos"keep_original_sound" needs reference_videos
More than 3 video elementsKling V4 takes at most 3 video elements
More than 5 reference videos and video elements togetherKling V4 takes at most 5 reference videos and video elements together
More than 15 reference images, videos, audio links and elements togetherKling V4 takes at most 15 reference inputs and elements together

Fields this model does not accept

Sending one of these is refused before anything is charged, instead of being ignored:

  • sound, generate_audio, seed, multi_shots, multi_prompt, quality, watermark, task_type, output_format → field "sound" is not supported by model kling-v4 (with the field you sent).
  • Any other unknown field → unknown field: <name>.

Request examples

curl --request POST \
--url https://api.beatapi.io/v1/videos/tasks \
--header "Authorization: Bearer $BEATAPI_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v4",
"prompt": "A dramatic product reveal of a glass water bottle, slow orbiting camera, soft studio reflections, a low ambient synth tone",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p"
}'

Text to video

A 5-second 16:9 clip at 720p with generated audio.

curl --request POST \
--url https://api.beatapi.io/v1/videos/tasks \
--header "Authorization: Bearer $BEATAPI_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v4",
"prompt": "A dramatic product reveal of a glass water bottle, slow orbiting camera, soft studio reflections, a low ambient synth tone",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p"
}'

First and last frame

The video moves from the first image to the second at 1080p and takes the shape of the first frame.

curl --request POST \
--url https://api.beatapi.io/v1/videos/tasks \
--header "Authorization: Bearer $BEATAPI_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v4",
"prompt": "The camera moves from the bottle in @first_frame to the singer on a neon stage in @last_frame in one continuous shot",
"images": [
"https://media.beatapi.io/samples/smart-bottle.png",
"https://media.beatapi.io/samples/neon-singer.png"
],
"duration": 5,
"resolution": "1080p"
}'

Reference images and a voice

Two reference images and one voice, each named in the prompt.

curl --request POST \
--url https://api.beatapi.io/v1/videos/tasks \
--header "Authorization: Bearer $BEATAPI_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v4",
"prompt": "The singer from @image_1 lifts the bottle from @image_2 toward the camera and says a short line in the voice of @voice_1",
"reference_images": [
"https://media.beatapi.io/samples/neon-singer.png",
"https://media.beatapi.io/samples/smart-bottle.png"
],
"reference_audios": [
"https://media.beatapi.io/samples/neon-singer-preview.mp3"
],
"duration": 8,
"aspect_ratio": "9:16",
"resolution": "720p"
}'

Reference video with its own sound

Replace the placeholder with a 2–30 second clip of your own; keep_original_sound keeps its sound instead of generated audio.

curl --request POST \
--url https://api.beatapi.io/v1/videos/tasks \
--header "Authorization: Bearer $BEATAPI_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v4",
"prompt": "Restyle @video_1 as a neon-lit night scene and keep its camera movement",
"reference_videos": [
"https://your-cdn.example.com/clips/source.mp4"
],
"keep_original_sound": true,
"duration": 10,
"resolution": "720p"
}'

Named elements

A character and a prop, each defined from two pictures (the first is the main view). Replace the placeholder links with pictures of your own.

curl --request POST \
--url https://api.beatapi.io/v1/videos/tasks \
--header "Authorization: Bearer $BEATAPI_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "kling-v4",
"prompt": "@singer walks across a neon stage holding @bottle and smiles at the camera",
"duration": 6,
"aspect_ratio": "16:9",
"resolution": "720p",
"elements": [
{
"name": "singer",
"tag": "character",
"description": "A performer in a silver jacket",
"element_input_urls": [
"https://your-cdn.example.com/elements/singer-front.png",
"https://your-cdn.example.com/elements/singer-side.png"
]
},
{
"name": "bottle",
"tag": "prop",
"element_input_urls": [
"https://your-cdn.example.com/elements/bottle-front.png",
"https://your-cdn.example.com/elements/bottle-back.png"
]
}
]
}'

Responses

Create a task (201)

The task object. output is null until the task succeeds. Fields marked “while running” disappear once the task finishes.

{
"data": {
"id": "task_7Qm2Xc9LpR4vT8sKa1Nf6YbH3eWdJ0uZ",
"object": "task",
"task_kind": "video",
"capability_id": "kling-v4",
"capability_version": 1,
"media_type": "video",
"model": "kling-v4",
"status": "queued",
"stage": "queued",
"created_at": 1791993600,
"updated_at": 1791993600,
"completed_at": null,
"poll_after_seconds": 8,
"output": null,
"usage": {
"credits_reserved": 1,
"credits_settled": 0,
"credits_refunded": 0,
"credits_charged": 1,
"billable_duration_seconds": 5
},
"request_id": "req_5f0c2a9e4b7d4e31",
"error_code": null,
"error_message": null
}
}
FieldTypeDescription
data.idstringTask ID: task_ followed by 32 letters and digits. Use it to poll and to match webhook events.
data.objectstringAlways task.
data.task_kindstringimage or video.
data.capability_idstringThe model ID you sent.
data.capability_versionintegerContract version of the model, currently 1.
data.media_typestringimage or video.
data.modelstringThe model ID you sent (same as capability_id).
data.statusstringqueued, processing, succeeded or failed. Only the last two are final.
data.stagestringRepeats status; kept for older clients.
data.created_atintegerWhen the task was created, Unix seconds.
data.updated_atintegerLast change, Unix seconds.
data.completed_atinteger | nullWhen the task finished, Unix seconds; null while it runs.
data.poll_after_secondsintegerWhile running: how long to wait before the next poll (5 for images, 8 for videos).
data.typical_secondsobjectWhile running, when enough recent tasks exist: p50 and p90 completion times in seconds over the last window, from samples tasks.
data.outputobject | nullThe result; null until status is succeeded. See the output fields below.
data.usage.credits_reservednumberUSD held from your balance when the task was created.
data.usage.credits_chargednumberUSD this task costs; 0 on a failed task.
data.usage.credits_settlednumberUSD finally taken; set when the task succeeds, otherwise 0.
data.usage.credits_refundednumberUSD returned to your balance; equals the reservation on a failed task once the refund is recorded.
data.usage.billable_duration_secondsintegerVideo only: the seconds the price is based on. Absent when the model reports no duration.
data.request_idstringRequest ID. Include it when you contact support.
data.error_codestring | nullFailure code; null unless the task failed.
data.error_messagestring | nullWhat went wrong and what to change; null unless the task failed.

Finished task

GET /v1/tasks/{task_id} returns HTTP 200 with status: "succeeded" and the result in data.output.

{
"data": {
"id": "task_7Qm2Xc9LpR4vT8sKa1Nf6YbH3eWdJ0uZ",
"object": "task",
"task_kind": "video",
"capability_id": "kling-v4",
"capability_version": 1,
"media_type": "video",
"model": "kling-v4",
"status": "succeeded",
"stage": "succeeded",
"created_at": 1791993600,
"updated_at": 1791993690,
"completed_at": 1791993690,
"output": {
"media": [
{
"type": "video",
"url": "https://media.beatapi.io/outputs/task_7Qm2Xc9LpR4vT8sKa1Nf6YbH3eWdJ0uZ/0.mp4",
"mime_type": "video/mp4"
}
],
"r2_url": "https://media.beatapi.io/outputs/task_7Qm2Xc9LpR4vT8sKa1Nf6YbH3eWdJ0uZ/0.mp4"
},
"usage": {
"credits_reserved": 1,
"credits_settled": 1,
"credits_refunded": 0,
"credits_charged": 1,
"billable_duration_seconds": 5
},
"request_id": "req_5f0c2a9e4b7d4e31",
"error_code": null,
"error_message": null
}
}

Output fields

FieldTypeDescription
output.mediaobject[]The generated files; one video for this model.
output.media[].typestringAlways video.
output.media[].urlstringHTTPS link to the stored video. Download and keep it; no retention period is promised.
output.media[].mime_typestringThe media type of the file, normally video/mp4.
output.r2_urlstringThe video URL again, for older clients. Read media instead.

Failed task

A failed task is still HTTP 200 on GET /v1/tasks/{task_id}: the failure is in the body. The reservation is returned in full, so nothing is charged.

{
"data": {
"id": "task_7Qm2Xc9LpR4vT8sKa1Nf6YbH3eWdJ0uZ",
"object": "task",
"task_kind": "video",
"capability_id": "kling-v4",
"capability_version": 1,
"media_type": "video",
"model": "kling-v4",
"status": "failed",
"stage": "failed",
"created_at": 1791993600,
"updated_at": 1791993690,
"completed_at": 1791993690,
"output": null,
"usage": {
"credits_reserved": 1,
"credits_settled": 0,
"credits_refunded": 1,
"credits_charged": 0,
"billable_duration_seconds": 5
},
"retryable": true,
"request_id": "req_5f0c2a9e4b7d4e31",
"error_code": "processing_failed",
"error_message": "The task failed during processing on our side. Retry; a failed task is refunded."
}
}
FieldTypeDescription
data.error_codestringOne of bad_request and content_policy_violation (change the request) or processing_unavailable, processing_timeout, processing_failed and result_transfer_failed (try again later). See Errors.
data.error_messagestringA sentence that names the problem and the fix.
data.retryablebooleanPresent only on a failed task: true when the same request can succeed if you send it again.
data.usageobjectOnce the refund is recorded (normally at the moment the task fails): credits_charged and credits_settled are 0, and credits_refunded equals credits_reserved.

Complete example

Create a task, wait for it with the server’s polling hint, and print the result URLs. Set BEATAPI_API_KEY in your environment and install requests.

import os
import time
import uuid
import requests
API = "https://api.beatapi.io"
HEADERS = {"Authorization": f"Bearer {os.environ['BEATAPI_API_KEY']}"}
def create_task(body: dict) -> dict:
# One Idempotency-Key per logical request: a retry with the same key cannot create a second task.
headers = {**HEADERS, "Idempotency-Key": str(uuid.uuid4())}
for attempt in range(3):
response = requests.post(f"{API}/v1/videos/tasks", headers=headers, json=body, timeout=60)
if response.status_code in (429, 503) and attempt < 2:
time.sleep(int(response.headers.get("Retry-After", 10)))
continue
break
try:
payload = response.json()
except ValueError: # an edge error page is not JSON
response.raise_for_status()
raise
if not response.ok:
error = payload["error"]
raise RuntimeError(f"{response.status_code} {error['code']}: {error['message']} (request_id={error.get('request_id')})")
return payload["data"]
def wait_for_task(task_id: str, timeout_seconds: int = 1800) -> dict:
deadline = time.monotonic() + timeout_seconds
while time.monotonic() < deadline:
response = requests.get(f"{API}/v1/tasks/{task_id}", headers=HEADERS, timeout=30)
if response.status_code == 429 or response.status_code >= 500:
time.sleep(int(response.headers.get("Retry-After", 10)))
continue
response.raise_for_status()
task = response.json()["data"]
if task["status"] in ("succeeded", "failed"):
return task
time.sleep(task.get("poll_after_seconds", 5))
raise TimeoutError(f"task {task_id} is still running; keep polling later")
task = create_task({
"model": "kling-v4",
"prompt": "A dramatic product reveal of a glass water bottle, slow orbiting camera, soft studio reflections, a low ambient synth tone",
"duration": 5,
"aspect_ratio": "16:9",
"resolution": "720p"
})
print("created", task["id"])
task = wait_for_task(task["id"])
if task["status"] == "failed":
raise SystemExit(f"{task['error_code']}: {task['error_message']}")
for item in task["output"]["media"]:
print(item["url"])

Billing

  • The price is per second of video at the resolution you choose: 0.20persecondat‘720p‘and0.20 per second at `720p` and 0.30 per second at 1080p. The list below shows 8-second clips.
  • The number of seconds is duration, or 5 when you leave it out. usage.billable_duration_seconds on the task shows it.
  • Every video comes with audio, generated or kept from the reference videos, at no separate charge.
  • The price is reserved when the task is created and settled when the video is ready. A failed task, including one refused by moderation after submission, is refunded in full.

Current list prices, the same as on Pricing. An account with a negotiated discount pays less; data.usage on the task always shows the amount actually charged.

OptionList price (USD)
8 sec · 720p$1.6
8 sec · 1080p$2.4

Common errors

Error or symptomCauseFix
400 the prompt names @image_3, which this request does not sendA mention names an input the request does not carry, such as a third reference image when two are sent.Match every @ to an input of the same request, numbered from 1 in list order.
400 Cannot combine "images" with reference inputs in one taskFrames in images were sent with reference_images, reference_videos or reference_audios.Use frames or references, not both. Pictures that should guide the video without being frames go in reference_images.
400 Kling V4 cannot combine elements with imageselements were sent with frames.Remove images, or remove elements.
400 Kling V4 takes the first frame's shape; do not send aspect_ratio with imagesaspect_ratio was sent with frames.Remove aspect_ratio, and crop the first frame to the shape you want.
400 Kling V4 takes at most 6 images for a 5-second videoMore frames than duration + 1.Send fewer frames, or a longer duration; 10 frames is the most in any case.
400 elements[0] takes either element_input_urls or element_input_video_urlsAn element has both pictures and a video, or neither.Give each element 2 to 4 pictures, or one character video.
400 "elements[0].element_input_urls" requires at least 2 itemAn element has only one picture.Send 2 to 4 pictures of the element, the main view first.
400 elements[0].name "image_1" is not a name Kling V4 acceptsThe name has characters other than letters, digits, underscores and Chinese characters, or is a reserved name such as image_1 or first_frame.Rename the element, for example singer or hero_bottle, and mention it by that name.
400 "keep_original_sound" needs reference_videoskeep_original_sound was sent without reference_videos.Remove it, or add the reference videos whose sound you want to keep.
400 reference_videos[0] is 35 seconds long; this model takes reference video of 2 to 30 seconds.A reference clip is shorter than 2 or longer than 30 seconds; all clips together may run at most 30.Trim the clip to the part you need.
400 field "sound" is not supported by model kling-v4Audio is always generated; there is no sound switch (generate_audio, seed and multi_shots are refused too).Remove the field. To keep a reference video’s own sound, send keep_original_sound: true.
400 "resolution" must be one of: [720p 1080p]4K or a tier name such as pro was sent.Send 720p or 1080p.
400 "duration" is outside its supported rangeNot a whole number from 3 to 30, or sent as a string.Send an integer such as 5.
Task failed with content_policy_violationThe prompt, an input or the result was refused by moderation.Change the prompt or the inputs. Retrying unchanged fails again; nothing is charged.
402 insufficient_creditsThe balance is below the reservation for this length and resolution.Top up, shorten duration, or use 720p.

HTTP errors at a glance

Errors before a task exists arrive as a non-2xx response, and nothing is charged. Branch on error.code or error.retryable; message names the problem. The full list and retry policy are on Errors.

{
"error": {
"code": "bad_request",
"message": "\"prompt\" is required",
"retryable": false,
"request_id": "req_5f0c2a9e4b7d4e31"
}
}
HTTP statuserror.codeWhat to do
400bad_request, content_policy_violationFix the request; the message names the field. Do not retry unchanged.
401missing_api_key, invalid_api_key (older clients may see unauthorized)Send a valid key as Authorization: Bearer <key>.
402insufficient_creditsTop up, or raise the key’s quota, then send it again.
403forbiddenThe key or account may not use this model (for example, free credit only covers some models). Do not retry unchanged.
404not_foundOn GET /v1/tasks/{task_id}: the task does not exist for this key’s account. Check the ID.
409idempotency_conflictUse a new Idempotency-Key, or wait for the first request with this key to finish.
429rate_limit_exceededWait Retry-After seconds (also error.retry_after_seconds), then retry.
500internal_errorRetry with backoff; contact support with request_id if it continues.
503processing_unavailable, processing_timeout, processing_failed, result_transfer_failedNothing was charged. Retry with exponential backoff.

Authentication

AuthorizationBearer

Send your API key as Authorization: Bearer <BEATAPI_API_KEY>.

Headers

Idempotency-KeystringOptional<=255 characters

Send the body as JSON with Content-Type: application/json. Idempotency-Key is optional: send a unique value (at most 255 characters) per logical request and reuse it only to retry that exact body. Within 24 hours a retry with the same key and body returns the first response again with Idempotent-Replayed: true; the same key with a different body returns 409 idempotency_conflict. Responses other than 2xx are not stored, so a retry after a 400 or 402 runs again.

Request

This endpoint expects an object.
modelenumRequired

The model to run.

Value: kling-v4

If the value is wrong

  • Missing: "model" is required
  • An image model sent to this endpoint: "model" nano-banana-2 is served by POST /v1/images/tasks, not this endpoint
Allowed values:
promptstringRequired1-5000 characters

What happens in the video: subject, action, camera movement, style and sound, with each input named by its @ mention.

Length: 1–5000 characters

  • Length is counted in characters (a CJK character counts as one).
  • Mentions: reference_images are @image_1, @image_2 …, reference_videos are @video_1 …, reference_audios are @voice_1 …, and an element is @ followed by its name. Frames are @first_frame, @keyframe_1, @keyframe_2 … and @last_frame.
  • Every @ must name an input of the same request. A numbered or frame mention with nothing behind it, such as @image_3 with two reference images or @last_frame with one image, is refused when the task is created.

If the value is wrong

  • Missing: "prompt" is required
  • Empty or longer than the limit: "prompt" has an unsupported length
  • A mention of an input the request does not send: the prompt names @image_3, which this request does not send
aspect_ratioenumOptionalDefaults to 16:9

Shape of the video as width:height.

Allowed values: 16:9, 9:16, 1:1, 21:9

Default: 16:9

  • If you leave it out, 16:9 is used.
  • Do not send it with images: the video takes the shape of the first frame.

If the value is wrong

  • A value not in the list: "aspect_ratio" must be one of: [16:9 9:16 1:1 21:9]
  • Sent with images: Kling V4 takes the first frame's shape; do not send aspect_ratio with images
Allowed values:
durationintegerOptional3-30Defaults to 5

Length of the video in seconds, a whole number. It is what you are billed for.

Default: 5

Range: 3–30

  • If you leave it out, 5 is used and billed.
  • With frames it also caps the number of images: at most duration + 1, and never more than 10.

If the value is wrong

  • Outside the range, not a whole number, or sent as a string: "duration" is outside its supported range
elementslist of objectsOptional

Up to seven named subjects, such as a character, an animal, a prop, a costume, a scene or an effect, each defined once and named in the prompt as @ followed by its name.

Items: ≤ 7

  • An array of at most seven objects. Each object accepts these keys and no others:
  • elements[].name (string, required): 1 to 20 letters, digits, underscores or Chinese characters, unique within the request ignoring case. It cannot be image_N, video_N, voice_N, keyframe_N, object_N, audio_N, first_frame or last_frame.
  • elements[].element_input_urls (array of strings): 2 to 4 public HTTPS links to pictures of the element; the first is its main view.
  • elements[].element_input_video_urls (array of strings): exactly one public HTTPS link to a 3 to 8 second single-shot video of a character. Send this or element_input_urls, not both.
  • elements[].element_input_audio_urls (array of strings, optional): exactly one public HTTPS audio link, the voice of a character element.
  • elements[].tag (string, optional): what the element is. A video element, or an element with a voice, must be a character: leave tag out or send character.
  • elements[].description (string, optional): what the element is, at most 100 characters.
  • Video elements are at most 3, and at most 5 together with reference_videos. Every element counts toward the limit of 15 reference inputs and elements.
  • Elements cannot be sent with images.

If the value is wrong

  • More than seven elements: "elements" accepts at most 7 items
  • An element that is not an object: "elements[0]" must be an object
  • An element without name: "name" is required in "elements[0]"
  • A name that is empty or longer than 20: "elements[0].name" has an unsupported length
  • A name with other characters, or a reserved name: elements[0].name "image_1" is not a name Kling V4 accepts
  • The same name twice, ignoring case: elements[1].name "Hero" is used twice
  • Both pictures and a video, or neither: elements[0] takes either element_input_urls or element_input_video_urls
  • Fewer than two pictures: "elements[0].element_input_urls" requires at least 2 item
  • More than four pictures: "elements[0].element_input_urls" accepts at most 4 items
  • A video element whose tag is not character: elements[0] is a video element, which is always a character
  • A voice on an element whose tag is not character: elements[0] has a voice, which only a character element takes
  • A tag not in the list: "elements[0].tag" must be one of: [character animal prop costume scene effect others]
  • A description longer than 100 characters: "elements[0].description" has an unsupported length
  • A key that an element does not accept: field "start_time" is not supported in "elements[0]"
  • More than three video elements: Kling V4 takes at most 3 video elements
  • Combined with images: Kling V4 cannot combine elements with images
imageslist of stringsOptional

Frames in time order: one link is the first frame, two are the first and last frame, and more add middle frames between them.

Items: 1–10

Each item is a public https:// URL. For a local file, upload it first with POST /v1/files and pass the returned data.url.

  • With three or more links, images[0] is the first frame and the last link the last frame; the links in between are middle frames, so images[1] is @keyframe_1, images[2] is @keyframe_2, and so on.
  • A video takes at most one image more than its seconds (duration + 1, counting 5 seconds when duration is left out), and never more than 10.
  • Frames cannot be sent with reference_images, reference_videos, reference_audios, elements or aspect_ratio: the video takes the shape of the first frame.

If the value is wrong

  • More than 10 links: "images" accepts at most 10 items
  • More links than duration + 1 (here 7 links for a 5-second video): Kling V4 takes at most 6 images for a 5-second video
  • Combined with any reference_* field: Cannot combine "images" with reference inputs in one task
  • Combined with elements: Kling V4 cannot combine elements with images
  • Combined with aspect_ratio: Kling V4 takes the first frame's shape; do not send aspect_ratio with images
  • Not an https:// link: "images[0]" must be a public HTTPS URL
keep_original_soundbooleanOptional

Keeps the reference videos’ own sound in the finished video instead of generated audio.

  • Only valid with reference_videos; sending it without them, even as false, is refused.
  • Without it the video comes with generated audio. There is no field that turns audio off.

If the value is wrong

  • Not true or false: "keep_original_sound" must be a boolean
  • Sent without reference_videos: "keep_original_sound" needs reference_videos
reference_audioslist of stringsOptional

Voices for the video. Name them in the prompt as @voice_1, @voice_2 … in list order.

Items: 1–3

Each item is a public https:// URL. For a local file, upload it first with POST /v1/files and pass the returned data.url.

  • Cannot be combined with images.
  • Count toward the limit of 15 reference inputs and elements together.

If the value is wrong

  • More than the maximum: "reference_audios" accepts at most 3 items
reference_imageslist of stringsOptional

Pictures that guide the content, characters, products or style of the video. Name them in the prompt as @image_1, @image_2 … in list order.

Items: 1–10

Each item is a public https:// URL. For a local file, upload it first with POST /v1/files and pass the returned data.url.

  • Cannot be combined with images.
  • Count toward the limit of 15 reference inputs and elements together.

If the value is wrong

  • More than the maximum: "reference_images" accepts at most 10 items
  • More than 15 reference inputs and elements together: Kling V4 takes at most 15 reference inputs and elements together
reference_videoslist of stringsOptional

Videos to take motion, camera work or content from. Name them in the prompt as @video_1, @video_2 … in list order.

Items: 1–5

Each item is a public https:// URL. For a local file, upload it first with POST /v1/files and pass the returned data.url.

  • Each clip runs 2 to 30 seconds, and all clips together at most 30 seconds. The gateway measures each clip before creating the task and refuses one outside these limits, naming it.
  • Reference videos and video elements together are at most 5, and count toward the limit of 15 reference inputs and elements.
  • The finished video has generated audio unless you send keep_original_sound: true, which keeps the reference videos’ own sound.

If the value is wrong

  • More than the maximum: "reference_videos" accepts at most 5 items
  • A clip shorter than 2 or longer than 30 seconds: reference_videos[0] is 35 seconds long; this model takes reference video of 2 to 30 seconds.
  • Clips that run longer than 30 seconds together: The reference videos run 36 seconds in total; this model takes at most 30.
  • More than 5 reference videos and video elements together: Kling V4 takes at most 5 reference videos and video elements together
resolutionenumOptionalDefaults to 720p

Output resolution. 1080p costs more per second than 720p.

Allowed values: 720p, 1080p

Default: 720p

  • If you leave it out, 720p is used and billed.
  • 4K is not available on this model.

If the value is wrong

  • A value not in the list (for example 4K or pro): "resolution" must be one of: [720p 1080p]
Allowed values:

Response

The task object. output is null until the task succeeds. Fields marked “while running” disappear once the task finishes.

Errors

400
Bad Request Error
401
Unauthorized Error
402
Payment Required Error
403
Forbidden Error
409
Conflict Error
429
Too Many Requests Error
500
Internal Server Error
503
Service Unavailable Error