kling-motion-control
Kling Motion Control — reference-driven motion transfer. Pass a reference image and a reference video; the API maps the motion onto your subject. Two tiers (v3, v2.6), std or pro, billed per second of source footage.
Kling Motion Control transfers the motion from a reference video onto a
subject taken from a reference image. One async endpoint, two version
tiers (kling-v3-motion-control, kling-v2-6-motion-control), std or
pro quality. Billing is per second of the source video's server-probed
length. 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-v3-motion-control",
"prompt": "Keep the subject consistent, follow the reference motion, cinematic lighting",
"image_url": "https://your-cdn.com/subject.png",
"video_url": "https://your-cdn.com/motion-8s.mp4",
"character_orientation": "image",
"mode": "std",
"keep_original_sound": "yes"
}'import requests
resp = requests.post(
"https://reapi.ai/api/v1/videos/generations",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"model": "kling-v3-motion-control",
"prompt": "Follow the reference motion, keep the subject consistent",
"image_url": "https://your-cdn.com/subject.png",
"video_url": "https://your-cdn.com/motion-8s.mp4",
"character_orientation": "image",
"mode": "std",
},
timeout=30,
)
print(resp.json())const r = 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-v3-motion-control",
prompt: "Follow the reference motion, keep the subject consistent",
image_url: "https://your-cdn.com/subject.png",
video_url: "https://your-cdn.com/motion-8s.mp4",
character_orientation: "image",
mode: "std",
}),
});
console.log(await r.json());package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]any{
"model": "kling-v3-motion-control",
"prompt": "Follow the reference motion, keep the subject consistent",
"image_url": "https://your-cdn.com/subject.png",
"video_url": "https://your-cdn.com/motion-8s.mp4",
"character_orientation": "image",
"mode": "std",
})
req, _ := http.NewRequest("POST",
"https://reapi.ai/api/v1/videos/generations", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}Submit response
{
"id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
"model": "kling-v3-motion-control",
"status": "processing",
"created_at": 1735000000
}Poll GET /api/v1/tasks/{id} (see the Tasks reference) until
status === "completed". The completed payload's output.video_urls holds the
generated MP4 URLs.
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 immediately with a task_id; the task
endpoint returns the same envelope until completion. Polling does not consume
credits.
Version tiers
Two model ids share the exact same request shape — pick one by the
model string you POST:
model id | Tier | Notes |
|---|---|---|
kling-v3-motion-control | v3 | Latest — higher motion fidelity & consistency |
kling-v2-6-motion-control | v2.6 | Budget tier, lower per-second rate |
Everything else in this page applies identically to both ids. See current per-second rates for each tier on the model page.
Request body
model — required
string. One of "kling-v3-motion-control" or "kling-v2-6-motion-control".
prompt — required
string. Refines the motion, camera, and style. The API rejects requests
without a prompt — more specific prompts yield more stable results.
image_url — required
string. Public HTTP(S) URL of the reference image — the subject whose
appearance and identity the output keeps.
No data: URIs. reApi rejects base64 inputs platform-wide. Upload to public
storage (your own CDN, S3, R2…) and pass the URL.
video_url — required
string. Public HTTP(S) URL of the reference video — the clip whose motion
is transferred onto the subject. MP4 / MOV recommended, ≤ 100MB.
The allowed source length depends on character_orientation (see below). The
billable second count is the source video's server-probed duration, not a
client estimate.
character_orientation — required
string. Controls whose facing the subject follows.
| Value | Behavior | Source video length |
|---|---|---|
"image" | Facing follows the reference image | 3 – 10 seconds |
"video" | Facing follows the reference video | 3 – 30 seconds |
mode — required
string. Quality / cost tier.
| Value | Behavior |
|---|---|
"std" | Standard — balances speed and quality |
"pro" | Pro — higher quality, usually slower; higher rate |
keep_original_sound — string, default "yes"
Whether to retain the reference video's original audio track.
| Value | Behavior |
|---|---|
"yes" | Keep the original audio (default) |
"no" | Drop the original audio |
watermark_info — object
Watermark control. Default disabled.
{ "watermark_info": { "enabled": false } }| Field | Type | Default | Behavior |
|---|---|---|---|
enabled | boolean | false | Add a watermark |
Response envelope
Submit and poll share the same shape — only status and output fill in over
time.
{
"id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
"model": "kling-v3-motion-control",
"status": "completed",
"created_at": 1735000000,
"output": {
"video_urls": ["https://cdn.reapi.ai/media/tasks/018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e/0.mp4"]
},
"error": null
}| Field | Type | Notes |
|---|---|---|
id | string | Task identifier — keep it for polling and audit |
model | string | Echo of the submitted model |
status | string | processing / completed / failed |
created_at | integer | Submission unix timestamp |
output | object | null | null until completion. output.video_urls holds MP4s |
error | object | null | Populated on failed — { code, message } |
Pricing
Per-second × mode. The billable second count is the source video's
server-probed length — reApi measures the uploaded clip server-side rather
than trusting a client value. kling-v3-motion-control and
kling-v2-6-motion-control have separate per-second rates, and pro costs
more than std.
Bill formula (1 credit = $0.001):
billable_seconds = ceil(server_probed_source_seconds)
bill_usd = per_second_usd(tier, mode) × billable_seconds
credits = ceil(bill_usd × 1000)See current per-second rates for each tier and mode on the
model page. Failed jobs refund
automatically. A probe failure returns 400 PRICING_UNAVAILABLE (code 30002)
with no charge.
The playground's draft estimate may show a default before the upload finishes — the authoritative number is computed at submit, after the server probes the file.
Validation errors
All cases below return HTTP 400. Pattern-match on code, not message —
message strings carry request-specific context and are not a stable contract.
| Trigger | Code | Message (illustrative) |
|---|---|---|
image_url missing | 20002 | kling-motion-control: image_url is required |
video_url missing | 20002 | kling-motion-control: video_url is required |
character_orientation missing / invalid | 20003 | kling-motion-control: invalid character_orientation |
mode missing / invalid | 20003 | kling-motion-control: invalid mode (allowed: std / pro) |
keep_original_sound invalid | 20003 | kling-motion-control: invalid keep_original_sound |
image_url / video_url carrying a data: URI | 20003 | kling-motion-control: image_url must be a public http(s) URL |
| Source video probe fails (network / format) | 30002 | Could not determine source video duration for billing: … |
| Source video length outside the orientation window | 80007 | Provider rejected the request as invalid |
The full envelope is { "error": { "code", "message", "request_id" } } — see
Errors catalog for the wire format and request_id
correlation tips.
Recipes
Minimum request (image orientation)
{
"model": "kling-v3-motion-control",
"prompt": "Follow the reference motion, keep the subject consistent",
"image_url": "https://your-cdn.com/subject.png",
"video_url": "https://your-cdn.com/motion-8s.mp4",
"character_orientation": "image",
"mode": "std"
}Video orientation, pro quality, up to 30s
{
"model": "kling-v3-motion-control",
"prompt": "Follow the reference performance and rhythm, keep motion continuous",
"image_url": "https://your-cdn.com/subject.png",
"video_url": "https://your-cdn.com/motion-20s.mp4",
"character_orientation": "video",
"mode": "pro",
"keep_original_sound": "no"
}Budget tier, watermark off
{
"model": "kling-v2-6-motion-control",
"image_url": "https://your-cdn.com/subject.png",
"video_url": "https://your-cdn.com/motion-6s.mp4",
"character_orientation": "image",
"mode": "std",
"watermark_info": { "enabled": false }
}Tips
- Match the clip to the orientation.
character_orientation: "image"caps the reference video at 10s; use"video"when you need up to 30s. - Cost tracks the source clip. A 5s reference video bills ~5 seconds; trim the input to control spend.
- Prompt the motion, not just the scene. Phrasing the action ("turns and waves, smooth and continuous") sharpens the transfer.
- Start on
std, escalate topro. Validate the motion on the cheaper mode, then re-run onprofor the final take. - Pick the tier by budget.
kling-v2-6-motion-controlis the cheaper run;kling-v3-motion-controlmaximizes fidelity and subject consistency.