> ## Documentation Index
> Fetch the complete documentation index at: https://tryunsora.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Motion control

> Make the character in an image copy the motion of a reference video, with Kling, Wan Animate or DreamActor.

Animates the character in `character_image_url` with the motion from `motion_video_url`. Runs through [Generate](https://tryunsora.com/docs/api-reference/catalog/generate.md) with live pricing; check a model's inputs with [List models](https://tryunsora.com/docs/api-reference/catalog/list.md) (`?category=motion-control`) and its price with [Quote a generation](https://tryunsora.com/docs/api-reference/catalog/quote.md).

Models: `kling-mc-3.0-pro` (default), `kling-mc-3.0-std`, `kling-mc-2.6-pro`, `wan-2.2-animate`, `dreamactor-v2`. Poll [Poll video status](https://tryunsora.com/docs/api-reference/video/poll-status.md) with `generation.id`.

```bash theme={null}
curl -X POST "https://mvp.tryunsora.com/api/v1/motion-control/create" \
  -H "Authorization: Bearer uns_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-mc-3.0-pro",
    "character_image_url": "https://cdn.example.com/character.png",
    "motion_video_url": "https://cdn.example.com/dance.mp4",
    "keep_sound": true
  }'
```


## OpenAPI

````yaml POST /motion-control/create
openapi: 3.1.0
info:
  title: Unsora API
  version: 1.4.0
  description: >-
    Public API for Unsora integrations. Authenticate with an Unsora API key
    (`uns_…`, created under Developers → API keys in the app) as a Bearer token
    in the Authorization header. Limit: 60 requests per minute per key; over it,
    429 with code RATE_LIMIT_EXCEEDED.
servers:
  - url: https://mvp.tryunsora.com/api/v1
    description: Production
  - url: /api/v1
    description: This server
security: []
tags:
  - name: User
  - name: Models
    description: >-
      Every video, image and motion-control model, with each model's inputs
      taken from the provider's own request schema and prices quoted live. One
      generate endpoint covers all of them.
  - name: Video
  - name: Image
  - name: Influencer
  - name: Thumbnail
  - name: Clipping
  - name: Music
  - name: Voiceover
  - name: Upscaler
  - name: Subtitle removal
  - name: Motion control
  - name: Avatar
  - name: Movie materials
  - name: Voice clones
  - name: Voice changer
  - name: Uploads
  - name: Scheduler
paths:
  /motion-control/create:
    post:
      tags:
        - Motion control
      summary: Animate a character with a reference video
      description: >-
        Makes the character in an image perform the motion from a reference
        video. Runs through POST /catalog/generate with live pricing; price a
        run first with POST /catalog/quote, and see each model's inputs with GET
        /catalog?category=motion-control. Poll GET /video/status/{id}.
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
            maxLength: 128
          description: >-
            API key requests only. Retrying with the same key within 24 hours
            replays the first response (with the `Idempotent-Replayed: true`
            header) instead of charging again. The body isn't compared; reusing
            the key on a different endpoint returns 409 IDEMPOTENCY_CONFLICT.
            Keys over 128 characters are ignored.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                model:
                  type: string
                  enum:
                    - kling-mc-3.0-pro
                    - kling-mc-3.0-std
                    - kling-mc-2.6-pro
                    - wan-2.2-animate
                    - dreamactor-v2
                  default: kling-mc-3.0-pro
                character_image_url:
                  type: string
                  format: uri
                  description: >-
                    Image of the character. Aliases: `characterImageUrl`,
                    `image`.
                motion_video_url:
                  type: string
                  format: uri
                  description: >-
                    Video whose motion the character copies. Aliases:
                    `motionVideoUrl`, `video`.
                prompt:
                  type: string
                  description: Optional guidance, for models that take one.
                keep_sound:
                  type: boolean
                  description: >-
                    Keep the reference video's audio, for models that offer it.
                    Aliases: `keepSound`, `keep_original_sound`.
                character_orientation:
                  type: string
                  description: >-
                    Which way the character faces, for models that offer it;
                    values per model in GET /catalog. Alias:
                    `characterOrientation`.
      responses:
        '200':
          description: Generation queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CatalogGenerateResponse'
        '400':
          description: Invalid model or inputs, or a media file couldn't be imported
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: Insufficient credits
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            Idempotency-Key already used on a different endpoint (code
            IDEMPOTENCY_CONFLICT)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '502':
          description: The pricing service couldn't be reached; try again
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Generation is temporarily unavailable (code PROVIDER_UNAVAILABLE)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - bearerAuth: []
components:
  schemas:
    CatalogGenerateResponse:
      type: object
      properties:
        success:
          type: boolean
        model:
          type: string
        generation:
          type: object
          properties:
            id:
              type: string
            status:
              type: string
            model:
              type: string
            mode:
              type: string
            modelId:
              type: string
          required:
            - id
            - status
        creditsDeducted:
          type: integer
        creditsRemaining:
          type: integer
      required:
        - success
        - generation
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
        error:
          type: string
        code:
          type: string
        message:
          type: string
      required:
        - error
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: An Unsora API key (`uns_…`). A Clerk session token also works.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.