curl https://api.apipod.ai/v1/videos/generations \
-H "Authorization: Bearer $APIPOD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": false
}'import os
import requests
payload = {
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": False
}
response = requests.post(
"https://api.apipod.ai/v1/videos/generations",
headers={
"Authorization": f"Bearer {os.environ['APIPOD_API_KEY']}",
"Content-Type": "application/json",
},
json=payload,
timeout=60,
)
response.raise_for_status()
print(response.json())package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
)
func main() {
body := []byte(`{
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": false
}`)
req, err := http.NewRequest(http.MethodPost, "https://api.apipod.ai/v1/videos/generations", bytes.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("APIPOD_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(resp.Status, string(out))
}use reqwest::Client;
use serde_json::json;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let payload = json!({
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": false
});
let response = Client::new()
.post("https://api.apipod.ai/v1/videos/generations")
.bearer_auth(env::var("APIPOD_API_KEY")?)
.json(&payload)
.send()
.await?
.error_for_status()?;
println!("{}", response.text().await?);
Ok(())
}const response = await fetch("https://api.apipod.ai/v1/videos/generations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.APIPOD_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": false
}),
});
if (!response.ok) {
throw new Error(`APIPod request failed: ${response.status} ${await response.text()}`);
}
console.log(await response.json());{
"code": 200,
"message": "success",
"data": {
"task_id": "vid_task_01JEXAMPLE"
}
}Kling 3.0 Image to Video
Kling 3.0 I2V is APIPod’s first/last-frame image-to-video mode for Kling 3.0, Kuaishou’s video model with multi-shot storytelling and optional native audio.
curl https://api.apipod.ai/v1/videos/generations \
-H "Authorization: Bearer $APIPOD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": false
}'import os
import requests
payload = {
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": False
}
response = requests.post(
"https://api.apipod.ai/v1/videos/generations",
headers={
"Authorization": f"Bearer {os.environ['APIPOD_API_KEY']}",
"Content-Type": "application/json",
},
json=payload,
timeout=60,
)
response.raise_for_status()
print(response.json())package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
)
func main() {
body := []byte(`{
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": false
}`)
req, err := http.NewRequest(http.MethodPost, "https://api.apipod.ai/v1/videos/generations", bytes.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("APIPOD_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(resp.Status, string(out))
}use reqwest::Client;
use serde_json::json;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let payload = json!({
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": false
});
let response = Client::new()
.post("https://api.apipod.ai/v1/videos/generations")
.bearer_auth(env::var("APIPOD_API_KEY")?)
.json(&payload)
.send()
.await?
.error_for_status()?;
println!("{}", response.text().await?);
Ok(())
}const response = await fetch("https://api.apipod.ai/v1/videos/generations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.APIPOD_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"model": "kling-3.0-i2v",
"prompt": "The camera slowly pushes in as the dancer spins and lands in the final pose.",
"image_urls": [
"https://cdn.example.com/first-frame.jpg",
"https://cdn.example.com/last-frame.jpg"
],
"duration": 5,
"resolution": "1080p",
"generate_audio": false
}),
});
if (!response.ok) {
throw new Error(`APIPod request failed: ${response.status} ${await response.text()}`);
}
console.log(await response.json());{
"code": 200,
"message": "success",
"data": {
"task_id": "vid_task_01JEXAMPLE"
}
}Usage notes
- First / last frame:
image_urlsis required and takes 1-2 images. Withmulti_shotoff, 2 images are the first frame (image_urls[0]) and last frame (image_urls[1]), and 1 image is the first frame. Withmulti_shoton, only a first frame is supported. The output aspect ratio follows the first frame. - Multi-shot: set
multi_shottotrueand describe up to 5 shots inmulti_prompt({prompt, duration}, 1-12 seconds and up to 500 characters each). The total shot duration must not exceedduration; whendurationis omitted it defaults to the sum of the shots, andpromptmay be omitted. - Audio:
generate_audiodefaults tofalsefor single-shot requests andtruefor multi-shot requests. - Prompt: required for single-shot requests; in multi-shot mode put each shot’s description in
multi_promptinstead. - Not supported:
kling_elements,aspect_ratio(the output follows the first frame),negative_prompt(write exclusions into the prompt), top-levelaudio_urls, andvideo_url.
Billing
Billed per second of output video. The per-second rate has five tiers: 720p or 1080p, each with or without native audio, plus 4K (same rate with or without audio). Current prices are shown on the model page.Task flow
The create call returnsdata.task_id. Poll Query video task until status is completed (outputs in data.result) or failed, or pass callback_url to be notified when the task reaches a terminal state.Authorizations
Use your APIPod API key as a Bearer token in the Authorization header.
Body
Public APIPod model ID.
"kling-3.0-i2v"First/last frame images. With multi_shot off, 2 images are the first and last frame (index 0 and 1) and 1 image is the first frame; with multi_shot on, only a first frame is supported. first_frame_image / last_frame_image are accepted as aliases. The aspect ratio follows the first frame.
1 - 2 elementsText prompt describing the motion, up to 2,500 characters. Required unless multi_prompt is provided.
2500Output duration in seconds (3-15). Defaults to 5; in multi-shot mode it defaults to the sum of the shot durations when omitted.
3 <= x <= 15Output resolution (up to 4K). Defaults to 720p. The per-second rate depends on the resolution and, for 720p and 1080p, on native audio.
720p, 1080p, 4k Generate native audio (alias audio). Defaults to false for single-shot requests and true for multi-shot requests.
Enable multi-shot generation (alias multi_shots). Use together with multi_prompt to define each shot.
Shot list for multi-shot generation, up to 5 shots. Each shot is {prompt, duration} with a prompt of up to 500 characters and a duration of 1-12 seconds; the total must not exceed duration.
5Show child attributes
Show child attributes
HTTPS URL that receives the task's terminal state.
Was this page helpful?