# Kling 3 Motion Control (video) > Kling 3 Motion Control transfers the movement of a reference video onto the character in a reference image, and it is best when you own a clip whose motion you want a different person to perform. Status: roasOS API v1.1. Catalog `model-catalog@2026-10-06.v5`, pricing `customer-pricing@2026-11-05.v15`. The endpoint `POST /v1/video/kling-3-motion` is live. `POST /v1/generations` stays for one minor version as a deprecated alias (see "Today"). ## Endpoint POST https://api.roasos.com/v1/video/kling-3-motion Auth: Authorization: Bearer roasos_sk_… (scope api:write). Idempotency-Key required. quote_only / quote_id / webhook_url as in https://docs.roasos.com/llms.txt. ## Good at The reference image supplies the character, the background and the other visible elements. The reference video supplies the body motion and, with `character_orientation: "video"`, the camera behaviour. Use it for dance, gesture and presenter moves that must match a source clip exactly. The `standard` tier is the cost-effective mode for portraits and simple animations; the `pro` tier is the choice for full-body motion and detailed clothing. Write the prompt about the subject, the wardrobe, the expression and the style, not about the camera, because the reference video already owns the camera. Keep the reference video short: it decides both the output length and the price. It is the only video model on roasOS that takes a reference video as its motion source, and the only one that requires a recorded media-rights attestation. It does not accept a text-only or image-only request, a last frame, or audio input. ## Pricing Unit: clip. Pricing keys: `kling-3-motion-pro`, `kling-3-motion-standard`. The catalog publishes no credit example for this model: the pricing table has no key for it, and roasOS never states a guessed price. ## Modes - `motion-control` Provider endpoints: `fal-ai/kling-video/v3/pro/motion-control` · `fal-ai/kling-video/v3/standard/motion-control`. ## Request fields | field | type | required | default | rule | |---|---|---|---|---| | `character_orientation` | enum | yes | `image` | `image`, `video` | | `extend_of_generation_id` | string | no | — | UUID | | `image_url` | string | no | — | https URL; ≤ 4,096 characters | | `keep_original_sound` | boolean | yes | — | — | | `media_rights` | object | yes | — | `{ accepted, statement_version }` | | `prompt` | string | no | — | ≥ 1 character; ≤ 2,500 characters | | `quote_id` | string | no | — | UUID | | `quote_only` | boolean | no | `false` | — | | `scene_id` | string | no | — | UUID | | `tier` | enum | no | `standard` | `standard`, `pro` | | `video_url` | string | yes | — | https URL; ≤ 4,096 characters | | `wait_timeout_seconds` | integer | no | `0` | 0–60 | | `webhook_url` | string | no | — | https URL; ≤ 4,096 characters | The schema is strict: a field that is not in this table returns `400 unsupported_option`. Field names are the roasOS role names, one name per role across every family. ## Media - `image_url` — first frame (or the single source image) - `scene_id` — first frame — a scene this workspace owns - `video_url` — the source video | role | items | max size | content types | duration | |---|---|---|---|---| | `image_url` | ≤ 1 | 10 MB | `image/jpeg`, `image/png`, `image/webp` | — | | `video_url` | ≤ 1 | 100 MB | `video/mp4`, `video/quicktime` | — | - Refused: `avatar_id`, `elements`, `product_id`, `product_images`, `references`, `reference_images`, `end_image_url`, `scene_image`, `video_urls`, `audio_urls`, `audio_url`, `voice_id`. A refused role returns `400 unsupported_option`. - Every URL must be an immutable object on `https://cdn.roasos.com/…` that your workspace owns; any other URL is `400 reference_media_not_workspace_owned`. Upload with `POST /v1/uploads` (direct POST of the bytes to `put_url`, or a `source_url` import), then use the returned CDN URL. ## Prompt - Limit: 2,500 characters. No roasOS wrapper; the prompt goes verbatim, or the field is omitted when empty. - No tags: `@Element1` exists at fal only with `elements`, which roasOS does not expose. - Craft: name the subject and the wardrobe ("woman in a red linen dress, hair tied back"), the expression ("calm, small smile"), and the style ("natural daylight, realistic skin"). Do not describe camera moves or the motion itself; the video owns both. Keep it short: the image and the video carry the information. ## Not exposed - `duration_seconds`: pinned to `measured from video_url`. - `aspect_ratio`: not accepted by this public endpoint. - `resolution`: pinned to `named by tier`. - `generate_audio`: not accepted by this public endpoint. - `negative_prompt`: not accepted by this public endpoint. - `seed`: not accepted by this public endpoint. - `references`: not accepted by this public endpoint. - `elements`: not accepted by this public endpoint. - `avatar_id`: not accepted by this public endpoint. - `product_id`: not accepted by this public endpoint. - `end_image_url`: not accepted by this public endpoint. ## Result Result kind `video`. Always present: `url`. ```json { "data": { "id": "gen_…", "kind": "video", "model": "kling-3-motion", "status": "completed", "result": {"url":"https://cdn.roasos.com/workspaces/ws_01/result"} } } ``` Files live on `https://cdn.roasos.com` and are immutable; a result URL can be a media input to the next call. Poll `GET /v1/jobs/{id}/status` → `{ id, status, updated_at }`, then `GET /v1/jobs/{id}/result` (`409 run_not_completed` until the job is `completed`, `failed` or `canceled`). Statuses: `queued → processing → completed | failed | canceled`. ## Example ```bash # 1. quote — nothing is spent curl -X POST https://api.roasos.com/v1/video/kling-3-motion \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-kling-3-motion-0001" \ -H "Content-Type: application/json" \ -d '{"quote_only":true,"character_orientation":"image","image_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/image_url.png","keep_original_sound":false,"media_rights":{"accepted":true,"statement_version":1},"video_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/video_url.mp4"}' # → 200 { "data": { "kind": "quote", "quote_id": "q_7Hk…", "credits": …, "expires_at": "…", "confirmation": { "model": "kling-3-motion" } } } # 2. run — the same body and the same Idempotency-Key, quote_id instead of quote_only curl -X POST https://api.roasos.com/v1/video/kling-3-motion \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-kling-3-motion-0001" \ -H "Content-Type: application/json" \ -d '{"quote_id":"q_7Hk…","character_orientation":"image","image_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/image_url.png","keep_original_sound":false,"media_rights":{"accepted":true,"statement_version":1},"video_url":"https://cdn.roasos.com/workspaces/ws_01/uploads/video_url.mp4"}' # → 201 { "data": { "id": "gen_…", "kind": "video", "model": "kling-3-motion", "status": "queued", "credits_reserved": …, "links": { "status": "/v1/jobs/gen_…/status", "result": "/v1/jobs/gen_…/result" } } } # 3. poll curl https://api.roasos.com/v1/jobs/gen_…/status -H "Authorization: Bearer roasos_sk_live_…" curl https://api.roasos.com/v1/jobs/gen_…/result -H "Authorization: Bearer roasos_sk_live_…" ``` ## Today Not available on the public API yet. `POST /v1/generations` returns `503 public_model_unavailable` for `model: "kling-3-motion"`, and the alias will stay refused because it cannot carry `media_rights`. The app reaches the model through its internal UGC route (`image`, `referenceVideo`, `characterOrientation`, `keepOriginalSound`, `quality`, `rightsAccepted`, `rightsStatementVersion`, `rightsPolicyVersion`); at v1.1 these become `image_url`, `video_url`, `character_orientation`, `keep_original_sound`, `tier`, `media_rights{}`. The agent does not offer this model. ## See also https://docs.roasos.com/models/video/kling-3-motion · https://api.roasos.com/v1/catalog/video/kling-3-motion · fal-ai/kling-video/v3/pro/motion-control · fal-ai/kling-video/v3/standard/motion-control