curl --request POST \
--url https://api.bitstudio.ai/images/{id}/video \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "kling-v3-pro",
"prompt": "Slow camera push-in. The model holds a steady pose.",
"duration": 5,
"generate_audio": false
}
'import requests
url = "https://api.bitstudio.ai/images/{id}/video"
payload = {
"model": "kling-v3-pro",
"prompt": "Slow camera push-in. The model holds a steady pose.",
"duration": 5,
"generate_audio": False
}
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: 'kling-v3-pro',
prompt: 'Slow camera push-in. The model holds a steady pose.',
duration: 5,
generate_audio: false
})
};
fetch('https://api.bitstudio.ai/images/{id}/video', 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://api.bitstudio.ai/images/{id}/video",
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' => 'kling-v3-pro',
'prompt' => 'Slow camera push-in. The model holds a steady pose.',
'duration' => 5,
'generate_audio' => false
]),
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://api.bitstudio.ai/images/{id}/video"
payload := strings.NewReader("{\n \"model\": \"kling-v3-pro\",\n \"prompt\": \"Slow camera push-in. The model holds a steady pose.\",\n \"duration\": 5,\n \"generate_audio\": false\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://api.bitstudio.ai/images/{id}/video")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"kling-v3-pro\",\n \"prompt\": \"Slow camera push-in. The model holds a steady pose.\",\n \"duration\": 5,\n \"generate_audio\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bitstudio.ai/images/{id}/video")
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\": \"kling-v3-pro\",\n \"prompt\": \"Slow camera push-in. The model holds a steady pose.\",\n \"duration\": 5,\n \"generate_audio\": false\n}"
response = http.request(request)
puts response.read_body{
"id": "11111111-1111-4111-8111-111111111111",
"status": "pending",
"path": null,
"width_px": null,
"height_px": null,
"created_timestamp": "2026-09-06T12:00:00Z"
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"cta": true,
"next_action": "<string>",
"current_plan": "<string>",
"user_message": "<string>",
"extra_context": "<string>"
}Animate an image
Kling 3 returns a new pending video Image directly; poll its id. Kling 2.5 returns the parent Image with a linked version; poll that version’s source_image_id. HTTP 200 means accepted, not finished. Start/end frames must be at least 300 × 300 pixels, no larger than 10 MiB, with width/height between 0.4 and 2.5. When both frames are supplied, their dimensions must match.
curl --request POST \
--url https://api.bitstudio.ai/images/{id}/video \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "kling-v3-pro",
"prompt": "Slow camera push-in. The model holds a steady pose.",
"duration": 5,
"generate_audio": false
}
'import requests
url = "https://api.bitstudio.ai/images/{id}/video"
payload = {
"model": "kling-v3-pro",
"prompt": "Slow camera push-in. The model holds a steady pose.",
"duration": 5,
"generate_audio": False
}
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: 'kling-v3-pro',
prompt: 'Slow camera push-in. The model holds a steady pose.',
duration: 5,
generate_audio: false
})
};
fetch('https://api.bitstudio.ai/images/{id}/video', 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://api.bitstudio.ai/images/{id}/video",
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' => 'kling-v3-pro',
'prompt' => 'Slow camera push-in. The model holds a steady pose.',
'duration' => 5,
'generate_audio' => false
]),
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://api.bitstudio.ai/images/{id}/video"
payload := strings.NewReader("{\n \"model\": \"kling-v3-pro\",\n \"prompt\": \"Slow camera push-in. The model holds a steady pose.\",\n \"duration\": 5,\n \"generate_audio\": false\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://api.bitstudio.ai/images/{id}/video")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"kling-v3-pro\",\n \"prompt\": \"Slow camera push-in. The model holds a steady pose.\",\n \"duration\": 5,\n \"generate_audio\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bitstudio.ai/images/{id}/video")
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\": \"kling-v3-pro\",\n \"prompt\": \"Slow camera push-in. The model holds a steady pose.\",\n \"duration\": 5,\n \"generate_audio\": false\n}"
response = http.request(request)
puts response.read_body{
"id": "11111111-1111-4111-8111-111111111111",
"status": "pending",
"path": null,
"width_px": null,
"height_px": null,
"created_timestamp": "2026-09-06T12:00:00Z"
}{
"error": "<string>",
"code": "<string>",
"message": "<string>",
"cta": true,
"next_action": "<string>",
"current_plan": "<string>",
"user_message": "<string>",
"extra_context": "<string>"
}Authorizations
Create an API key in Studio → account menu → API Keys. Keep it on your server.
Path Parameters
Image or asset ID from a previous response. Resource ID.
Body
Scene and motion direction.
Kling 3 returns a standalone job. Kling 2.5 image-to-video returns the parent image with a linked version.
kling-2.5, kling-v3-pro, kling-v3-standard "kling-v3-pro"
Clip duration in seconds. Use 5 for the first request. Supported durations depend on the model.
5
Video output ratio.
16:9, 9:16, 1:1 Generated audio for models that support it.
Kling 3 multi-shot directions. The shot durations determine the total duration. Use a single prompt first.
Show child attributes
Show child attributes
Optional undesired visual characteristics.
Optional version of this image to use as the source. Omit to use the original image.
Optional end frame. Its dimensions must match the start frame. Mutually exclusive with last_frame_url.
Direct end-frame URL. The same media constraints apply.
Optional output quality; supported values depend on the video model.
Kling 3 subject references. Provide an asset or direct image references for each element.
Show child attributes
Show child attributes
Additional avatar directions for supported video models.
Additional outfit directions for supported video models.
Response
Kling 3 returns a new pending video Image directly; poll its id. Kling 2.5 returns the parent Image with a linked version; poll that version’s source_image_id. HTTP 200 means accepted, not finished. Start/end frames must be at least 300 × 300 pixels, no larger than 10 MiB, with width/height between 0.4 and 2.5. When both frames are supplied, their dimensions must match.
Resource ID.
Job state. Only completed has a finished result.
pending, generating, completed, failed, policy_blocked, nsfw_filtered Result URL. Can be null while the job is pending.
Whether the upload is a reusable asset reference.
Operation that created this job.
Human-readable failure detail.
Machine-readable failure category, when available.
input_rejected, provider_unavailable, queue_timeout, policy_blocked Linked reusable assets.
Resource ID.
Related versions. May be omitted or empty. Never infer a new version is completed from the parent status.
Show child attributes
Show child attributes