kling-4-0
Kling 4.0 on reAPI — 3–30 second video with stereo sound from text, keyframes, or image, video and audio references, plus video edit and extend, at 720p or 1080p.
Kuaishou's Kling 4.0, live on reAPI. One model id, kling-4-0, covers five
jobs: text to video, image to video with up to 10 frames, reference-based
generation from images, videos and audio, video editing, and video
extension. Every clip is 3–30 seconds at 720p or 1080p with stereo
sound. The mode follows the media you send and omni_reference_task_type.
See current pricing on the model page.
Quick example
curl https://reapi.ai/api/v1/videos/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-4-0",
"prompt": "A paper lantern drifts down a quiet canal at dusk, warm light on the water, slow tracking shot, soft lapping water. No text, no logos.",
"resolution": "720p",
"duration": 5,
"aspect_ratio": "16:9"
}'import requests
response = requests.post(
"https://reapi.ai/api/v1/videos/generations",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"model": "kling-4-0",
"prompt": "A paper lantern drifts down a quiet canal at dusk, warm light on the water, slow tracking shot, soft lapping water. No text, no logos.",
"resolution": "720p",
"duration": 5,
"aspect_ratio": "16:9",
},
timeout=60,
)
response.raise_for_status()
task_id = response.json()["id"]const response = await fetch('https://reapi.ai/api/v1/videos/generations', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'kling-4-0',
prompt:
'A paper lantern drifts down a quiet canal at dusk, warm light on the water, slow tracking shot, soft lapping water. No text, no logos.',
resolution: '720p',
duration: 5,
aspect_ratio: '16:9',
}),
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const { id: taskId } = await response.json();package main
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
)
func main() {
body := strings.NewReader(`{
"model": "kling-4-0",
"prompt": "A paper lantern drifts down a quiet canal at dusk, warm light on the water, slow tracking shot, soft lapping water. No text, no logos.",
"resolution": "720p",
"duration": 5,
"aspect_ratio": "16:9"
}`)
req, err := http.NewRequest("POST", "https://reapi.ai/api/v1/videos/generations", body)
if err != nil { panic(err) }
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 60 * time.Second}
res, err := client.Do(req)
if err != nil { panic(err) }
defer res.Body.Close()
var task struct { ID string `json:"id"` }
if err := json.NewDecoder(res.Body).Decode(&task); err != nil { panic(err) }
fmt.Println(task.ID)
}Authentication
Every call needs a Bearer token. Generate keys at reapi.ai/settings/apikeys.
Authorization: Bearer YOUR_API_KEYEndpoint
POST /api/v1/videos/generations
GET /api/v1/tasks/{id}Submission is async. The POST returns a task id right away; poll the task
endpoint until status is completed or failed. Polling does not consume
credits.
Request body
| Field | Type | Default | Notes |
|---|---|---|---|
model | string | — | kling-4-0. Required. |
prompt | string | — | Describe subject, place, camera move, light and sound. Required, except for image to video from frames. Mention references as @Image1, @Video1, @Audio1 — see Referencing media. |
duration | integer | 5 | 3–30 seconds. Edit: leave it out and the output follows the input video. Extend: the length of the new part. |
resolution | string | 720p | 720p or 1080p. |
aspect_ratio | string | by mode | 16:9 / 9:16 / 1:1 / 21:9, or auto in reference mode only. Defaults: text 16:9, image the first frame's shape, reference auto, edit the input video's shape. Not accepted with extend. |
omni_reference_task_type | string | auto | auto / reference / edit / extend. auto picks the mode from your media; edit and extend must be named. |
first_frame_image | string | — | The first frame for image to video. Public HTTP(S) URL. |
last_frame_image | string | — | The last frame for image to video, or the target last frame for extend. |
image_with_roles | object[] | — | { "url", "role" } with role first_frame, last_frame, keyframe (or middle_frame), or reference_image. Exactly 1 first frame, up to 8 keyframes used in order, 10 frames in total. |
image_urls | string[] | — | Image to video: up to 2, the first then the last frame. Reference (with omni_reference_task_type: "reference") and edit: up to 10 reference images. |
video_urls | string[] | — | Reference videos: up to 5, 30 seconds used in total. For edit or extend, exactly 1 in place of video_url. |
video_url | string | — | The input video for edit or extend; needs omni_reference_task_type edit or extend. |
audio_urls | string[] | — | Reference audio: up to 3 clips of 5–30 seconds each. |
audio_setting | string | by mode | origin keeps the input video's audio, auto generates new audio. Edit keeps it by default; reference with videos regenerates it by default. Not accepted with extend. |
Every clip comes with stereo sound; there is no sound switch, and no mode,
negative_prompt, watermark or multi-shot field. Images, videos and audio
together are at most 15 reference files.
Checked by reAPI before anything is charged:
- every media field is a public HTTP(S) URL — base64 and
data:URIs are rejected resolutionis720por1080p, anddurationis a positive whole number- for an edit, and for a reference request with
video_urls, every input video can be measured (its length sets the bill — see Pricing)
Every other rule in the table — mode combinations, counts, lengths — is
checked by the model when the task starts. A request that breaks one ends as a
failed task with code 80007 and the exact reason, and is refunded in full.
Unknown fields are refused the same way rather than ignored.
Modes
| Mode | How to select it |
|---|---|
| Text to video | No media. |
| Image to video | A first frame, optionally a last frame and keyframes. |
| Reference | video_urls, audio_urls or reference_image roles, or omni_reference_task_type: "reference". |
| Edit | omni_reference_task_type: "edit" and one input video. |
| Extend | omni_reference_task_type: "extend" and one input video. |
Frames and reference media cannot be mixed in one request. Next to reference
videos or audio, image_urls count as reference images only with
omni_reference_task_type: "reference"; use reference_image roles
otherwise. A video_url without edit or extend is refused.
Keyframes
{
"model": "kling-4-0",
"prompt": "A girl walks from the window to the door, then looks back and smiles",
"image_with_roles": [
{"url": "https://example.com/1.png", "role": "first_frame"},
{"url": "https://example.com/2.png", "role": "keyframe"},
{"url": "https://example.com/3.png", "role": "last_frame"}
],
"duration": 10
}Edit
{
"model": "kling-4-0",
"prompt": "Change the scene to a snowy winter evening",
"omni_reference_task_type": "edit",
"video_url": "https://example.com/in.mp4"
}The input video must be at least 3 seconds; only its first 30 seconds are
used. Without duration, the output follows the input video.
Extend
{
"model": "kling-4-0",
"prompt": "The camera keeps moving forward as the sky grows darker",
"omni_reference_task_type": "extend",
"video_url": "https://example.com/in.mp4",
"duration": 5
}Extension continues from the input video's last frame and returns the
original plus the new part. Add last_frame_image to choose where it ends.
Referencing media in the prompt
Point the prompt at a specific reference with @Image1, @Video1 and
@Audio1, numbered from 1 in each list in the order the URLs appear.
{
"model": "kling-4-0",
"prompt": "The woman from @Image1 walks along the beach with the camera movement of @Video1",
"image_with_roles": [{"url": "https://example.com/woman.png", "role": "reference_image"}],
"video_urls": ["https://example.com/camera.mp4"],
"aspect_ratio": "auto",
"duration": 5
}Troubleshooting
| Failure | What it means | What to do |
|---|---|---|
Synchronous 400 (code 30002) | resolution or duration is not a priced value, or an input video's length could not be read | Use 720p / 1080p and a whole number of seconds; pass a public MP4 or MOV URL. Nothing was charged |
Task fails with code 80007 | A model rule was broken: mixed frames and references, a missing prompt, an edit video under 3 seconds, an unknown field, … | The message names the field. Fully refunded |
Task fails with code 80006 | The prompt or media was rejected by content review | Fully refunded. Revise the prompt or inputs |
402 on submit | Not enough credits for the reserve | Top up, or lower duration or resolution |
Task stays processing | Generation takes a few minutes, longer for long clips and edits | Keep polling; a task that can never finish is failed and refunded automatically |
No data: URIs. reAPI rejects base64 inputs platform-wide — every URL
field must be a public HTTP(S) URL. Upload to your own object storage and pass
the URL.
Response envelope
{
"id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
"model": "kling-4-0",
"status": "completed",
"created_at": 1789689600,
"output": {
"video_urls": ["https://cdn.reapi.ai/media/tasks/.../0.mp4"]
},
"error": null
}Poll GET /api/v1/tasks/{id} (see the Tasks reference)
until status === "completed", then read output.video_urls. A failed task
carries error.code and error.message; see the
errors catalog.
Pricing
Kling 4.0 bills per second of video, at a rate set by the resolution and by whether the request has input videos:
credits = ceil(per_second_rate × billable_seconds × 1000) 1 credit = $0.001| Mode | billable_seconds | Rate |
|---|---|---|
| Text, image, reference without videos | duration | standard |
| Extend | duration (the new part only) | standard |
Edit, reference with video_urls | output + max(output, input) | video input |
input is the total length of the input videos, measured by reAPI when the
request is accepted, rounded up to whole seconds and capped at 30. output is
duration; for an edit without duration it equals input. Editing a
5.2-second video into a 3-second result bills 3 + 6 = 9 seconds. Failed tasks
are refunded in full.
Live per-second rates for both rates are on the model page.