Kling 3.0 Omni Image to Video
curl --request POST \
--url https://whollyapi.com/api/v1/jobs/createTask \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"input": {
"prompt": "<string>",
"image_url": [
"<string>"
],
"duration": "<string>",
"resolution": "<string>",
"aspect_ratio": "<string>",
"customize_multi_shots": true,
"prefer_multi_shots": true,
"multi_prompt": [
{
"prompt": "<string>",
"duration": 123
}
],
"elements": [
{
"name": "<string>",
"description": "<string>",
"element_input_urls": [
"<string>"
],
"element_input_audio_urls": [
"<string>"
],
"start_time": 123,
"end_time": 123
}
]
}
}
'import requests
url = "https://whollyapi.com/api/v1/jobs/createTask"
payload = {
"model": "<string>",
"input": {
"prompt": "<string>",
"image_url": ["<string>"],
"duration": "<string>",
"resolution": "<string>",
"aspect_ratio": "<string>",
"customize_multi_shots": True,
"prefer_multi_shots": True,
"multi_prompt": [
{
"prompt": "<string>",
"duration": 123
}
],
"elements": [
{
"name": "<string>",
"description": "<string>",
"element_input_urls": ["<string>"],
"element_input_audio_urls": ["<string>"],
"start_time": 123,
"end_time": 123
}
]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
input: {
prompt: '<string>',
image_url: ['<string>'],
duration: '<string>',
resolution: '<string>',
aspect_ratio: '<string>',
customize_multi_shots: true,
prefer_multi_shots: true,
multi_prompt: [{prompt: '<string>', duration: 123}],
elements: [
{
name: '<string>',
description: '<string>',
element_input_urls: ['<string>'],
element_input_audio_urls: ['<string>'],
start_time: 123,
end_time: 123
}
]
}
})
};
fetch('https://whollyapi.com/api/v1/jobs/createTask', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://whollyapi.com/api/v1/jobs/createTask",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'input' => [
'prompt' => '<string>',
'image_url' => [
'<string>'
],
'duration' => '<string>',
'resolution' => '<string>',
'aspect_ratio' => '<string>',
'customize_multi_shots' => true,
'prefer_multi_shots' => true,
'multi_prompt' => [
[
'prompt' => '<string>',
'duration' => 123
]
],
'elements' => [
[
'name' => '<string>',
'description' => '<string>',
'element_input_urls' => [
'<string>'
],
'element_input_audio_urls' => [
'<string>'
],
'start_time' => 123,
'end_time' => 123
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://whollyapi.com/api/v1/jobs/createTask"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"input\": {\n \"prompt\": \"<string>\",\n \"image_url\": [\n \"<string>\"\n ],\n \"duration\": \"<string>\",\n \"resolution\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"customize_multi_shots\": true,\n \"prefer_multi_shots\": true,\n \"multi_prompt\": [\n {\n \"prompt\": \"<string>\",\n \"duration\": 123\n }\n ],\n \"elements\": [\n {\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"element_input_urls\": [\n \"<string>\"\n ],\n \"element_input_audio_urls\": [\n \"<string>\"\n ],\n \"start_time\": 123,\n \"end_time\": 123\n }\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://whollyapi.com/api/v1/jobs/createTask")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"input\": {\n \"prompt\": \"<string>\",\n \"image_url\": [\n \"<string>\"\n ],\n \"duration\": \"<string>\",\n \"resolution\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"customize_multi_shots\": true,\n \"prefer_multi_shots\": true,\n \"multi_prompt\": [\n {\n \"prompt\": \"<string>\",\n \"duration\": 123\n }\n ],\n \"elements\": [\n {\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"element_input_urls\": [\n \"<string>\"\n ],\n \"element_input_audio_urls\": [\n \"<string>\"\n ],\n \"start_time\": 123,\n \"end_time\": 123\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://whollyapi.com/api/v1/jobs/createTask")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"input\": {\n \"prompt\": \"<string>\",\n \"image_url\": [\n \"<string>\"\n ],\n \"duration\": \"<string>\",\n \"resolution\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"customize_multi_shots\": true,\n \"prefer_multi_shots\": true,\n \"multi_prompt\": [\n {\n \"prompt\": \"<string>\",\n \"duration\": 123\n }\n ],\n \"elements\": [\n {\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"element_input_urls\": [\n \"<string>\"\n ],\n \"element_input_audio_urls\": [\n \"<string>\"\n ],\n \"start_time\": 123,\n \"end_time\": 123\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"code": 123,
"msg": "<string>",
"data": {
"taskId": "<string>"
}
}Kling
Kling 3.0 Omni Image to Video
POST
/
api
/
v1
/
jobs
/
createTask
Kling 3.0 Omni Image to Video
curl --request POST \
--url https://whollyapi.com/api/v1/jobs/createTask \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"input": {
"prompt": "<string>",
"image_url": [
"<string>"
],
"duration": "<string>",
"resolution": "<string>",
"aspect_ratio": "<string>",
"customize_multi_shots": true,
"prefer_multi_shots": true,
"multi_prompt": [
{
"prompt": "<string>",
"duration": 123
}
],
"elements": [
{
"name": "<string>",
"description": "<string>",
"element_input_urls": [
"<string>"
],
"element_input_audio_urls": [
"<string>"
],
"start_time": 123,
"end_time": 123
}
]
}
}
'import requests
url = "https://whollyapi.com/api/v1/jobs/createTask"
payload = {
"model": "<string>",
"input": {
"prompt": "<string>",
"image_url": ["<string>"],
"duration": "<string>",
"resolution": "<string>",
"aspect_ratio": "<string>",
"customize_multi_shots": True,
"prefer_multi_shots": True,
"multi_prompt": [
{
"prompt": "<string>",
"duration": 123
}
],
"elements": [
{
"name": "<string>",
"description": "<string>",
"element_input_urls": ["<string>"],
"element_input_audio_urls": ["<string>"],
"start_time": 123,
"end_time": 123
}
]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
input: {
prompt: '<string>',
image_url: ['<string>'],
duration: '<string>',
resolution: '<string>',
aspect_ratio: '<string>',
customize_multi_shots: true,
prefer_multi_shots: true,
multi_prompt: [{prompt: '<string>', duration: 123}],
elements: [
{
name: '<string>',
description: '<string>',
element_input_urls: ['<string>'],
element_input_audio_urls: ['<string>'],
start_time: 123,
end_time: 123
}
]
}
})
};
fetch('https://whollyapi.com/api/v1/jobs/createTask', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://whollyapi.com/api/v1/jobs/createTask",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'input' => [
'prompt' => '<string>',
'image_url' => [
'<string>'
],
'duration' => '<string>',
'resolution' => '<string>',
'aspect_ratio' => '<string>',
'customize_multi_shots' => true,
'prefer_multi_shots' => true,
'multi_prompt' => [
[
'prompt' => '<string>',
'duration' => 123
]
],
'elements' => [
[
'name' => '<string>',
'description' => '<string>',
'element_input_urls' => [
'<string>'
],
'element_input_audio_urls' => [
'<string>'
],
'start_time' => 123,
'end_time' => 123
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://whollyapi.com/api/v1/jobs/createTask"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"input\": {\n \"prompt\": \"<string>\",\n \"image_url\": [\n \"<string>\"\n ],\n \"duration\": \"<string>\",\n \"resolution\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"customize_multi_shots\": true,\n \"prefer_multi_shots\": true,\n \"multi_prompt\": [\n {\n \"prompt\": \"<string>\",\n \"duration\": 123\n }\n ],\n \"elements\": [\n {\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"element_input_urls\": [\n \"<string>\"\n ],\n \"element_input_audio_urls\": [\n \"<string>\"\n ],\n \"start_time\": 123,\n \"end_time\": 123\n }\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://whollyapi.com/api/v1/jobs/createTask")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"input\": {\n \"prompt\": \"<string>\",\n \"image_url\": [\n \"<string>\"\n ],\n \"duration\": \"<string>\",\n \"resolution\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"customize_multi_shots\": true,\n \"prefer_multi_shots\": true,\n \"multi_prompt\": [\n {\n \"prompt\": \"<string>\",\n \"duration\": 123\n }\n ],\n \"elements\": [\n {\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"element_input_urls\": [\n \"<string>\"\n ],\n \"element_input_audio_urls\": [\n \"<string>\"\n ],\n \"start_time\": 123,\n \"end_time\": 123\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://whollyapi.com/api/v1/jobs/createTask")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"input\": {\n \"prompt\": \"<string>\",\n \"image_url\": [\n \"<string>\"\n ],\n \"duration\": \"<string>\",\n \"resolution\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"customize_multi_shots\": true,\n \"prefer_multi_shots\": true,\n \"multi_prompt\": [\n {\n \"prompt\": \"<string>\",\n \"duration\": 123\n }\n ],\n \"elements\": [\n {\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"element_input_urls\": [\n \"<string>\"\n ],\n \"element_input_audio_urls\": [\n \"<string>\"\n ],\n \"start_time\": 123,\n \"end_time\": 123\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"code": 123,
"msg": "<string>",
"data": {
"taskId": "<string>"
}
}Authentication
All API requests require a Bearer Token.Authorization: Bearer YOUR_API_KEY
Create a Video Generation Task
Submit an image-to-video generation task using the endpoint below.POST /api/v1/jobs/createTask
Request Body
Root Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Must be kling-3.0-omni/image-to-video. |
input | object | Yes | Generation input. Supports the input modes below. |
string
required
Must be
kling-3.0-omni/image-to-video.object
required
Input Parameters
Theinput object contains the parameters used to generate the video.string
required
The
prompt for generating a video. It must not be empty after leading and trailing whitespace is removed.Maximum length: 3,072 characters.string[]
required
First and last frame image URLs.Use the first image URL as the required first frame and the second image URL as the last frame of the video, with a smooth and natural transition between them.
- When the array contains 2 images:
image_urls[0]is the first frame.image_urls[1]is the last frame.
- When the array contains 1 image:
- The image is used as the first frame.
image/jpegimage/pngimage/jpg
50 MB Aspect ratio must be between 0.4 and 2.5.string
Use
duration to specify the total length of the video in seconds.Supported values:"3"to"15"
"5"string
Use
resolution to specify the output video resolution.Supported values:720p1080p4k
string
default:"16:9"
required
Specifies the aspect ratio of the generated video.Supported values:
16:99:161:1auto
16:9,9:16, and1:1are available only whencustomize_multi_shotsis enabled. Otherwise, useauto.
boolean
default:"false"
Set to
true to define custom shots using multi_prompt.boolean
default:"false"
Enables intelligent shot planning.
prefer_multi_shotsandcustomize_multi_shotsare mutually exclusive.
object[]
required
When
customize_multi_shots=true, this field is required.Used to describe the text and duration of each shot. Supports up to 6 shots. Each shot duration is 1–15 seconds.Array Item Properties
Each item inmulti_prompt contains the following required properties.string
required
Prompt text for this shot.Maximum length: 512 characters
number
required
Duration of this shot in seconds.
Range:
| Constraint | Value |
|---|---|
| Minimum | 1 |
| Maximum | 15 |
1–15 secondsobject[]
required
The
elements array defines one-time subject assets.Each subject is automatically identified as either a multi-image subject or a video character subject based on element_input_urls.Maximum subjects: 3Element Object
Each element in thekling_elements array supports the following properties.string
required
Element name used in the prompt with an
@ prefix.For example, if the element name is element_dog, reference it in the prompt as:@element_dog
string
required
Subject description
string[]
required
Image or video URLs used as the source material for the element.
- 2–4 URLs are required.
- Accepted image formats:
JPG,PNG. - Maximum file size:
10 MBper image.
string[]
Optional list of audio material URLs for characters.The audio duration must be between 5 and 30 seconds.
number
Start time for video character material capture, specified in milliseconds.This parameter is only effective when uploading videos through
element_input_urls.If no value is provided, it defaults to 0.number
End time for video character material capture, specified in milliseconds.This parameter is only effective when uploading videos through
element_input_urls.The following requirements apply:end_timemust be greater thanstart_time.- The difference between
end_timeandstart_timemust be between 3000 and 8000 milliseconds.
Complete Request Examples
Example 1: Single First Frame
{
"model": "kling-3.0-omni/image-to-video",
"input": {
"prompt": "A happy golden retriever running across a grassy field",
"image_urls": [
"https://example.com/first-frame.jpg"
],
"customize_multi_shots": true,
"audio": false,
"resolution": "720p",
"aspect_ratio": "16:9",
"duration": 5,
"elements": []
}
}
Example 2: First and Last Frames
{
"model": "kling-3.0-omni/image-to-video",
"input": {
"prompt": "A happy golden retriever running across a grassy field",
"image_urls": [
"https://example.com/first-frame.jpg",
"https://example.com/last-frame.jpg"
],
"customize_multi_shots": false,
"audio": false,
"resolution": "720p",
"aspect_ratio": "auto",
"duration": 5,
"elements": []
}
}
Response
Success Response
number
Response status code.
string
Response message. Contains the error description when the request fails.Example:
successobject
required
The task data object containing task id.
string
required
The unique identifier for this task.Example:
task_123456Query Task Status
After submitting a task, you can check task progress and retrieve generation results through the unified task-details endpoint.Get Task Details
Check task status, monitor generation progress, and retrieve results.
Error Response
{
"code": 500,
"msg": "Server Error - An unexpected error occurred while processing the request",
"data": null
}
Response Codes
| Code | Meaning |
|---|---|
200 | Success — the request was successfully processed. |
401 | Unauthorized — authentication credentials are missing or invalid. |
402 | Insufficient Credits — the account does not have enough credits. |
404 | Not Found — the requested resource or interface does not exist. |
408 | Upstream service issue — no result has been returned for over 10 minutes. |
422 | Validation Error — request parameters failed validation. |
429 | Rate Limited — request frequency limit has been exceeded. |
433 | Request Limit — sub-key usage exceeded the limit. |
455 | Service Unavailable — system is undergoing maintenance. |
500 | Server Error — an unexpected error occurred while processing the request. |
501 | Generation Failed — content generation failed. |
505 | Feature Disabled — the requested feature is disabled. |
