Create Video from Motion and Image

October 7, 2025 (October 20, 2026)

Table of contents

  1. Request Headers
  2. Request Body
  3. Responses
  4. Model
  5. Examples
  6. Try It

This endpoint applies motion from a reference video to a static image, creating an animated video where the character in the image performs the motion. Supports Kling v3.0 (default) and v2.6 motion control models. Optionally attach an element for improved character consistency.

https://api.useapi.net/v1/kling/videos/motion-create

Request Headers
Authorization: Bearer {API token}
Content-Type: application/json
# Alternatively you can use multipart/form-data
# Content-Type: multipart/form-data
Request Body
{
  "email": "[email protected]",
  "model_name": "kling-v3-0",
  "imageUrl": "https://example.com/person.jpg",
  "motionUrl": "https://example.com/dance-video.mp4",
  "prompt": "Person dancing energetically",
  "keepAudio": true,
  "motionDirection": "motion_direction",
  "mode": "std",
  "element_1": "u_123456789012345",
  "replyUrl": "https://your-callback-url.com/webhook",
  "replyRef": "your-reference-id"
}
  • email is optional. Leave it out and the job goes to one of your accounts that has a free job slot, picked at random. Each account runs at most its maxJobs jobs at once, and GET scheduler/available shows the free slots. If no account has a free slot, the response is 429.
    Pass email to run the job on that account (429 if it is busy). Uploaded files, elements, voices, avatars and earlier tasks belong to one account, so pass the email of the account they came from.
    With more than one account, reading the task with GET tasks/task_id needs its account’s email. The response’s task.userId is that account’s session.userId in GET accounts, and GET scheduler lists each running task with its email.

  • model_name is optional, must be kling-v3-0 or kling-v2-6. Selects the motion control model version. v3.0 provides upgraded motion capture with high facial consistency. Default: kling-v3-0

  • imageUrl is required, URL to the image containing the person. The person’s body and pose should be clearly visible. Must be uploaded via POST /assets first - use the url field from the response.

  • motionUrl is required, URL to the motion reference video (3-30 seconds). The video provides the motion that will be applied to the person in the image. Use GET /videos/motions to retrieve official Kling motions or your previously uploaded motions. To upload a new motion video, use POST /assets - use the resourceUrl field from the response.

  • prompt is optional, string up to 2500 characters. Text description to guide the video generation.

  • keepAudio is optional, boolean. When true, preserves the original audio from the motion video. Default: false

  • motionDirection is optional, must be motion_direction or image_direction.
    • motion_direction (default): The generated video follows the motion from the reference video
    • image_direction: The generated video follows the pose/direction from the source image
  • mode is optional, must be std or pro. Generation quality mode. Pro mode provides higher quality but costs more. Default: std

  • element_1 is optional, a saved element ID (e.g., u_123456789012345) for improved character consistency. Only supported with kling-v3-0. Create elements using POST /elements. The element’s cover image is included in the generation inputs.

  • maxJobs is optional, range from 1 to 50. Specifies the maximum number of concurrent jobs.

  • replyUrl is optional, a callback URL to receive generation progress and result. See GET /tasks/task_id for response model.

  • replyRef is optional, a reference identifier for the callback.

Notes:

  • The image must contain at least one clearly visible person with detectable pose
  • The endpoint validates the image before processing - returns error if no character detected
  • Video duration is automatically detected from the motion video
Responses
  • 200 OK

    {
      "task": {
        "id": 299640525521807,
        "userId": 23555898,
        "type": "m2v_motion_control",
        "scene": "NORMAL_CREATION",
        "status": 5,
        "status_name": "submitted",
        "status_final": false,
        "taskInfo": {
          "type": "m2v_motion_control",
          "inputs": [
            {
              "name": "video",
              "inputType": "URL",
              "url": "https://example.com/dance-video.mp4",
              "cover": ""
            },
            {
              "name": "image",
              "inputType": "URL",
              "url": "https://example.com/person.jpg"
            }
          ],
          "arguments": [
            { "name": "biz", "value": "klingai" },
            { "name": "prompt", "value": "Person dancing energetically" },
            { "name": "duration", "value": 5.76 },
            { "name": "imageCount", "value": 1 },
            { "name": "kling_version", "value": "3.0" },
            { "name": "keep_original_sound", "value": false },
            { "name": "motion_direction", "value": "motion_direction" },
            { "name": "model_mode", "value": "std" }
          ],
          "callbackPayloads": [
            { "name": "motionFrom", "value": "LOCAL" }
          ]
        },
        "createTime": 1767669665000,
        "updateTime": 1767669665000
      },
      "works": [],
      "status": 5,
      "status_name": "submitted",
      "status_final": false,
      "message": ""
    }
    
  • 400 Bad Request

    The parameters are invalid. When Kling refuses the submitted parameters, error carries Kling’s own message.

    Image validation failed - no detectable character in image:

    {
      "status": 1,
      "message": "MOTION.PIC_NOT_MATCHED"
    }
    

    Missing required parameter:

    {
      "error": "Parameter imageUrl is required"
    }
    

    Insufficient credits:

    {
      "error": {
        "type": "TASK.PointNotEnough",
        "detail": "Credit are insufficient, please top up and try again."
      }
    }
    
  • 401 Unauthorized

    {
      "error": "Unauthorized",
      "code": 401
    }
    
  • 500 Internal Server Error

    Kling uses a 500 response to indicate moderation and other issues with the input.

    {
      "error": "The content you uploaded appears to violate the community guidelines. (CM_EXT.POther)",
      "message": "Service busy (CM_EXT.POther)"
    }
    

When successful, the response includes a task ID which can be used to check the status using GET /tasks/task_id.

Model
{ // TypeScript, all fields are optional
    task: {
        id: number
        userId: number
        type: string // "m2v_motion_control"
        scene: string
        status: number
        status_name: 'submitted' | 'failed' | 'processing' | 'succeed'
        status_final: boolean
        taskInfo: {
            type: string
            inputs: Array<{
                name: string
                inputType: string
                url: string
                cover?: string
            }>
            arguments: Array<{
                name: string
                value: string | number | boolean
            }>
            callbackPayloads: Array<{
                name: string
                value: string
            }>
        }
        createTime: number
        updateTime: number
    }
    works: Array<any>
    status: number
    status_name: 'submitted' | 'failed' | 'processing' | 'succeed'
    status_final: boolean
    message: string
    error?: {
        type: string
        detail: string
    }
}
Examples
  • curl -X POST "https://api.useapi.net/v1/kling/videos/motion-create" \
       -H "Content-Type: application/json" \
       -H "Authorization: Bearer ..." \
       -d '{
         "email": "[email protected]",
         "model_name": "kling-v3-0",
         "imageUrl": "https://s15-kling.klingai.com/.../person.jpg",
         "motionUrl": "https://v15-kling.klingai.com/.../dance.mp4",
         "prompt": "Person dancing energetically",
         "keepAudio": true,
         "mode": "std",
         "element_1": "u_123456789012345"
       }'
    
  • const token = "API token";
    const email = "Previously configured account email";
    const apiUrl = "https://api.useapi.net/v1/kling/videos/motion-create";
    const response = await fetch(apiUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`,
      },
      body: JSON.stringify({
        email: email,
        model_name: "kling-v3-0",
        imageUrl: "https://s15-kling.klingai.com/.../person.jpg",
        motionUrl: "https://v15-kling.klingai.com/.../dance.mp4",
        prompt: "Person dancing energetically",
        keepAudio: true,
        mode: "std",
        element_1: "u_123456789012345"
      })
    });
    const result = await response.json();
    console.log("response", {response, result});
    
  • import requests
    token = "API token"
    email = "Previously configured account email"
    apiUrl = "https://api.useapi.net/v1/kling/videos/motion-create"
    headers = {
        "Content-Type": "application/json",
        "Authorization" : f"Bearer {token}"
    }
    data = {
        "email": email,
        "model_name": "kling-v3-0",
        "imageUrl": "https://s15-kling.klingai.com/.../person.jpg",
        "motionUrl": "https://v15-kling.klingai.com/.../dance.mp4",
        "prompt": "Person dancing energetically",
        "keepAudio": True,
        "mode": "std",
        "element_1": "u_123456789012345"
    }
    response = requests.post(apiUrl, headers=headers, json=data)
    print(response, response.json())
    
Try It