Create Video from Motion and Image

October 7, 2025 (January 6, 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. Uses Kling v2.6 motion control API.

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]",
  "imageUrl": "https://example.com/person.jpg",
  "motionUrl": "https://example.com/dance-video.mp4",
  "prompt": "Person dancing energetically",
  "keepAudio": true,
  "motionDirection": "motion_direction",
  "mode": "std",
  "replyUrl": "https://your-callback-url.com/webhook",
  "replyRef": "your-reference-id"
}
  • email is optional when only one account configured. However, if you have multiple accounts configured, this parameter becomes required.

  • 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. 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

  • 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
  • Uses Kling v2.6 m2v_motion_control API
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",
              "fromWorkId": null
            }
          ],
          "arguments": [
            { "name": "biz", "value": "klingai" },
            { "name": "prompt", "value": "Person dancing energetically" },
            { "name": "duration", "value": 5.76 },
            { "name": "imageCount", "value": 1 },
            { "name": "kling_version", "value": "2.6" },
            { "name": "keep_original_sound", "value": false },
            { "name": "motion_direction", "value": "motion_direction" },
            { "name": "model_mode", "value": "std" }
          ],
          "callbackPayloads": [
            { "name": "motionFrom", "value": "UPLOAD" }
          ]
        },
        "createTime": 1767669665000,
        "updateTime": 1767669665000
      },
      "works": [],
      "status": 5,
      "status_name": "submitted",
      "status_final": false,
      "message": ""
    }
    
  • 400 Bad Request

    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
                fromWorkId?: number | null
            }>
            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]",
         "imageUrl": "https://s15-kling.klingai.com/.../person.jpg",
         "motionUrl": "https://v15-kling.klingai.com/.../dance.mp4",
         "prompt": "Person dancing energetically",
         "keepAudio": true,
         "mode": "std"
       }'
    
  • 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,
        imageUrl: "https://s15-kling.klingai.com/.../person.jpg",
        motionUrl: "https://v15-kling.klingai.com/.../dance.mp4",
        prompt: "Person dancing energetically",
        keepAudio: true,
        mode: "std"
      })
    });
    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,
        "imageUrl": "https://s15-kling.klingai.com/.../person.jpg",
        "motionUrl": "https://v15-kling.klingai.com/.../dance.mp4",
        "prompt": "Person dancing energetically",
        "keepAudio": True,
        "mode": "std"
    }
    response = requests.post(apiUrl, headers=headers, json=data)
    print(response, response.json())
    
Try It