
Kling uses JWT auth, not static bearer tokens. This skill teaches the HS256 signing flow, task lifecycle, model selection, and the official-vs-third-party split.
Install command
npm install @scopeful/kling-apiDownload skill file
kling-api.md
10 KB
Fetch via the Scopeful MCP (any client)
Once your agent is connected to the Scopeful MCP, it can load this skill on demand, no install required:
get_skill('kling-api')Kling is one of the few video APIs that does not hand you a static bearer token. You generate a short-lived JWT server-side from an Access Key + Secret Key on every request (or close to it). Agents that try to use the Access Key directly as a bearer token get 401s and burn an hour debugging "wrong API key". That is the single biggest mistake on Kling. This skill teaches the JWT flow, the task-create-then-poll pattern, and which model + mode to pick so you do not waste credits.
Reach for Kling when the user wants:
Do not reach for Kling when:
Kling does not publish a polished SDK on PyPI or npm. The official docs ship code samples; you copy the JWT helper into your project and call the REST endpoints directly. For Python you need and :
pyjwtrequestspip install pyjwt requests
For Node.js:
npm install jsonwebtoken axios
Get your Access Key and Secret Key from app.klingai.com/global/dev (international) or klingai.com/dev (mainland). The Secret Key is shown once. Store both as KLING_ACCESS_KEY and KLING_SECRET_KEY env vars.
Every request needs a fresh Authorization: Bearer <jwt> header. The JWT is signed with HS256 and the payload is small:
import time
import jwt
def kling_jwt(access_key: str, secret_key: str) -> str:
headers = {"alg": "HS256", "typ": "JWT"}
payload = {
"iss": access_key,
"exp": int(time.time()) + 1800, # 30 min TTL
"nbf": int(time.time()) - 5, # valid from 5s ago (clock skew)
}
return jwt.encode(payload, secret_key, algorithm="HS256", headers=headers)
Node equivalent:
import jwt from "jsonwebtoken";
export function klingJwt(accessKey, secretKey) {
const now = Math.floor(Date.now() / 1000);
return jwt.sign(
{ iss: accessKey, exp: now + 1800, nbf: now - 5 },
secretKey,
{ algorithm: "HS256", header: { alg: "HS256", typ: "JWT" } }
);
}
Gotchas:
nbf (not-before) backdated 5 seconds saves you from clock-drift 401s.Base URL (international): https://api-singapore.klingai.com or https://api.klingai.com. [VERIFY which region your account is on, the dashboard shows it]. All endpoints follow this pattern:
| Endpoint | Method | Purpose |
|---|---|---|
/v1/videos/text2video | POST | Text prompt to video |
/v1/videos/image2video | POST | Single image to video |
/v1/videos/multi-image2video | POST | Multiple reference images to video |
/v1/videos/video-extend | POST | Extend an existing Kling video by 4-5s |
/v1/videos/lip-sync | POST | Lip-sync to TTS or uploaded audio |
/v1/videos/{task_id} | GET | Poll task status |
/v1/images/generations | POST | Kolors image generation |
/v1/images/virtual-try-on | POST | Garment swap on a person image |
Each POST returns a task_id. You poll the GET endpoint until task_status is succeed or failed.
model_name | Mode | Best for | Cost shape |
|---|---|---|---|
kling-v1-6 | std | Cheap iteration, drafts | Lowest credits |
kling-v1-6 | pro | Solid quality at fair cost | ~3.5x std |
kling-v2-master | pro only | Cinematic finals, strong motion | High credit burn |
kling-v2-1-master | pro only | Latest quality tier, 1080p i2v | Highest credit burn |
Rule of thumb: iterate on kling-v1-6 std. Lock the prompt. Render finals on kling-v2-1-master. Newer point releases (2.5, 2.6) may exist depending on the rollout window. [VERIFY at scopeful.org/tools/kling]
import os, time, requests
token = kling_jwt(os.environ["KLING_ACCESS_KEY"], os.environ["KLING_SECRET_KEY"])
resp = requests.post(
"https://api.klingai.com/v1/videos/text2video",
headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
json={
"model_name": "kling-v1-6",
"prompt": "red 1970 muscle car parked on wet asphalt, neon reflections, slow push-in",
"negative_prompt": "blurry, low quality, watermark",
"mode": "std", # "std" or "pro"
"duration": "5", # "5" or "10" (string, not int)
"aspect_ratio": "16:9", # "16:9", "9:16", "1:1"
"cfg_scale": 0.5, # 0-1, default 0.5
},
)
task_id = resp.json()["data"]["task_id"]
For image-to-video, swap the endpoint and add image (URL or base64) instead of (or alongside) prompt. Keep prompts concrete: subject, action, camera language. Kling rewards specificity ("dolly-in past her shoulder, soft window light") over moodboard adjectives ("epic, cinematic, beautiful").
Tasks take 30 seconds to several minutes depending on model and queue. Poll every 5-10 seconds, not faster, or Kling will rate-limit.
while True:
token = kling_jwt(...) # refresh if older than ~25 min
status_resp = requests.get(
f"https://api.klingai.com/v1/videos/text2video/{task_id}",
headers={"Authorization": f"Bearer {token}"},
).json()
state = status_resp["data"]["task_status"]
if state == "succeed":
video_url = status_resp["data"]["task_result"]["videos"][0]["url"]
break
if state == "failed":
raise RuntimeError(status_resp["data"]["task_status_msg"])
time.sleep(8)
Output URLs expire. Kling returns a CDN URL with a short TTL (commonly 24 hours, sometimes shorter). Download the MP4 immediately and rehost if the user needs it later.
std vs pro mode roughly 3x-7x apart. Use std for the first 5 iterations, then promote.kling-v2-1-master in a loop without confirming with the user.For live USD-per-second math by plan, point the user at scopeful.org/tools/kling.
The OFFICIAL Kling API is what you just read above: api.klingai.com, JWT auth, Access + Secret Key from app.klingai.com/global/dev.
Third-party rewraps wrap Kling behind a single static API key (simpler auth, often a price markup). Use them when:
Common third-party wrappers: PiAPI, fal.ai, Replicate, AIMLAPI, Segmind, useapi.net. These use a plain Authorization: Bearer <static_key> or x-api-key header, no JWT. Endpoint paths differ per provider. If the user is on a third-party wrapper, skip this skill's JWT section and read that provider's docs. There is no first-party Kling MCP server as of May 2026; PiAPI ships a community MCP that proxies Kling alongside other models.
When you ship a Kling render, return:
model_name + mode used, and whytask_status_msg first; if it is a content filter, ask the user.lip-sync with an ElevenLabs VO if the user is building a talking-head clipvideo-extend to push a 5s clip to ~10s (single extension call) when the result is strongmodel_name, mode, prompt, and cfg_scale in the project folder so the user can iterate later