> **Reading as an AI agent?** This is the Markdown version of https://docs.meshy.ai/api/animation.
>
> - Full docs index: https://docs.meshy.ai/llms.txt
> - Single-fetch full content: https://docs.meshy.ai/llms-full.txt
> - Tool-calling access via MCP server: https://docs.meshy.ai/api/ai

---
# Animation API

Endpoints for discovering available animations and applying them to rigged characters.

---

## POST /openapi/v1/animations -- Create an Animation Task

This endpoint allows you to create a new task to apply an animation to a previously rigged character — a preset action from the animation library (`action_id`), several preset actions merged into one file (`action_ids`), or a motion clip you generated with the [Text to Motion API](/api/text-to-motion) (`motion_task_id`). Includes post-processing options.

The task runs in the background. For how long it usually takes, see [Processing Times](/api/task-lifecycle#processing-times).

### Parameters

  - `rig_task_id` · *string* · **required**

  The `id` of a successfully completed rigging task (from `POST /openapi/v1/rigging`). The character from this task will be animated.

  - `action_id` · *integer*

  The identifier of the preset animation action to apply. See the [Animation Library Reference](/api/animation-library) for a complete list of available animations. Provide exactly one of `action_id`, `action_ids` or `motion_task_id`.

  - `action_ids` · *array of integers*

  Several preset animation actions to apply at once, returned as a single file containing one animation clip per action — useful for driving a character from a state machine in a game engine. Provide 1 to 10 `action_id` values from the [Animation Library Reference](/api/animation-library); ids must be unique. Costs 3 credits per action. Provide exactly one of `action_id`, `action_ids` or `motion_task_id`.

  Passing a single-element `action_ids` is equivalent to passing that value as `action_id`.

  - `motion_task_id` · *string*

  The `id` of a successfully completed [Text to Motion](/api/text-to-motion) task to apply instead of a preset action. The generated clip is retargeted onto the rigged character and the clip is snapshotted at creation time, so this task is unaffected if the source task later expires or is deleted. The source task's assets are retained for 3 days — apply the clip before it expires. Requires a biped rig. Provide exactly one of `action_id`, `action_ids` or `motion_task_id`.

  - `post_process` · *object*

  Optional post-processing for the animation output. Omit it to receive the standard animation files.

**Only when `post_process` is set:**
  - `operation_type` · *string* · **required**

  The type of operation to perform. Available values: `change_fps`, `fbx2usdz`, `extract_armature`.

  - `fps` · *integer* · default: `30`

  The target frame rate. Applicable only when `operation_type` is `change_fps`. Allowed values: `24`, `25`, `30`, `60`.

> **Note:** With `action_ids`, the task returns one merged file rather than one file per action: `animation_glb_url` and `animation_fbx_url` each point at a single asset containing every requested action as a separate clip.
>
>       * **Clip order**: the order of the `action_ids` array, not the numeric order of the ids.
>       * **Clip names**: the animation's name in the library, matching the names you get when exporting all animations of a character as a single file from the Meshy web app. If two requested ids resolve to the same clip name, the later one is suffixed with its `action_id` to keep names unique.
>       * **Post-processing**: applied to the merged file, not to the individual clips.

> **Note:** With `motion_task_id`, the retarget may produce a GLB-only animation. If you requested `post_process` and no FBX is available, the task fails with a `task_error` and your credits are refunded automatically; without `post_process` the task succeeds and `animation_fbx_url` is empty.

### Returns
The `result` property of the response contains the task `id` of the newly created animation task.

### Failure Modes

  - `400 - Bad Request`

  The request was unacceptable. Common causes:
  * **Missing parameter**: `rig_task_id` is missing, or none of `action_id`, `action_ids` and `motion_task_id` is provided.
  * **Conflicting parameters**: more than one of `action_id`, `action_ids` and `motion_task_id` was provided — they are mutually exclusive.
  * **Invalid rig task**: The `rig_task_id` is invalid or refers to a failed/non-existent task.
  * **Invalid action ID**: An `action_id` — or an entry of `action_ids` — does not correspond to a valid animation.
  * **Too many actions**: `action_ids` contains more than 10 ids.
  * **Duplicate actions**: `action_ids` contains the same id more than once.
  * **Motion task not ready**: the `motion_task_id` task has not `SUCCEEDED` yet.
  * **Unsupported rig**: `motion_task_id` requires a biped rig; quadruped rigs are rejected.

  - `401 - Unauthorized`

  Authentication failed. Please check your API key.

  - `402 - Payment Required`

  Insufficient credits to perform this task.

  - `404 - Not Found`

  The rigging task specified by `rig_task_id` was not found, the motion task specified by `motion_task_id` was not found, or the motion clip has expired (source task assets are retained for 3 days).

  - `429 - Too Many Requests`

  You have exceeded your rate limit.

**cURL**

```bash
# Animate a rigged model with required params only
curl https://api.meshy.ai/openapi/v1/animations \
  -X POST \
  -H "Authorization: Bearer ${YOUR_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
    "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579",
    "action_id": 92
  }'

# Apply several preset actions and get one file with one clip per action
curl https://api.meshy.ai/openapi/v1/animations \
  -X POST \
  -H "Authorization: Bearer ${YOUR_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
    "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579",
    "action_ids": [10, 25, 92]
  }'

# Apply a generated Text to Motion clip instead of a preset action
curl https://api.meshy.ai/openapi/v1/animations \
  -X POST \
  -H "Authorization: Bearer ${YOUR_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
    "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579",
    "motion_task_id": "018c425b-b2c6-727e-d333-3c1887i9h791"
  }'

# With post-processing to change FPS
curl https://api.meshy.ai/openapi/v1/animations \
  -X POST \
  -H "Authorization: Bearer ${YOUR_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
    "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579",
    "action_id": 92,
    "post_process": {
      "operation_type": "change_fps",
      "fps": 24
    }
  }'
```

```javascript
import axios from 'axios'

const headers = { Authorization: `Bearer ${YOUR_API_KEY}` };

// Animate a rigged model with required params only
const payload = {
  rig_task_id: "018b314a-a1b5-716d-c222-2f1776f7f579",
  action_id: 92
};

try {
  const response = await axios.post(
    'https://api.meshy.ai/openapi/v1/animations',
    payload,
    { headers }
  );
  console.log(response.data);
} catch (error) {
  console.error(error);
}

// Apply several preset actions and get one file with one clip per action
const multiActionPayload = {
  rig_task_id: "018b314a-a1b5-716d-c222-2f1776f7f579",
  action_ids: [10, 25, 92]
};

try {
  const response = await axios.post(
    'https://api.meshy.ai/openapi/v1/animations',
    multiActionPayload,
    { headers }
  );
  console.log(response.data);
} catch (error) {
  console.error(error);
}

// With post-processing to change FPS
const advancedPayload = {
  rig_task_id: "018b314a-a1b5-716d-c222-2f1776f7f579",
  action_id: 92,
  post_process: {
    operation_type: "change_fps",
    fps: 24
  }
};

try {
  const response = await axios.post(
    'https://api.meshy.ai/openapi/v1/animations',
    advancedPayload,
    { headers }
  );
  console.log(response.data);
} catch (error) {
  console.error(error);
}
```

```python
import requests

headers = {
    "Authorization": f"Bearer {YOUR_API_KEY}"
}

# Animate a rigged model with required params only
payload = {
    "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579",
    "action_id": 92
}

response = requests.post(
    "https://api.meshy.ai/openapi/v1/animations",
    headers=headers,
    json=payload,
)
response.raise_for_status()
print(response.json())

# Apply several preset actions and get one file with one clip per action
multi_action_payload = {
    "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579",
    "action_ids": [10, 25, 92]
}

response = requests.post(
    "https://api.meshy.ai/openapi/v1/animations",
    headers=headers,
    json=multi_action_payload,
)
response.raise_for_status()
print(response.json())

# With post-processing to change FPS
advanced_payload = {
    "rig_task_id": "018b314a-a1b5-716d-c222-2f1776f7f579",
    "action_id": 92,
    "post_process": {
        "operation_type": "change_fps",
        "fps": 24
    }
}

response = requests.post(
    "https://api.meshy.ai/openapi/v1/animations",
    headers=headers,
    json=advanced_payload,
)
response.raise_for_status()
print(response.json())
```

**Response**

```json
{
  "result": "018c425b-b2c6-727e-d333-3c1887i9h791"
}
```

---

## GET /openapi/v1/animations/:id -- Retrieve an Animation Task

This endpoint allows you to retrieve an animation task given a valid task `id`. Refer to [The Animation Task Object](#the-animation-task-object) to see which properties are included.

### Parameters

  - `id` · *path*

  Unique identifier for the animation task to retrieve.

### Returns
The response contains the Animation Task object. Check [The Animation Task Object](#the-animation-task-object) section for details.

**cURL**

```bash
curl https://api.meshy.ai/openapi/v1/animations/018c425b-b2c6-727e-d333-3c1887i9h791
  -H "Authorization: Bearer ${YOUR_API_KEY}"
```

```javascript
import axios from 'axios'

const taskId = '018c425b-b2c6-727e-d333-3c1887i9h791';
const headers = { Authorization: `Bearer ${YOUR_API_KEY}` };

try {
  const response = await axios.get(
    `https://api.meshy.ai/openapi/v1/animations/${taskId}`,
    { headers }
  );
  console.log(response.data);
} catch (error) {
  console.error(error);
}
```

```python
import requests

task_id = "018c425b-b2c6-727e-d333-3c1887i9h791"
headers = {
    "Authorization": f"Bearer {YOUR_API_KEY}"
}

response = requests.get(
    f"https://api.meshy.ai/openapi/v1/animations/{task_id}",
    headers=headers,
)
response.raise_for_status()
print(response.json())
```

**Response**

```json
{
  "id": "018c425b-b2c6-727e-d333-3c1887i9h791",
  "type": "animate",
  "status": "SUCCEEDED",
  "created_at": 1747032440896,
  "progress": 100,
  "started_at": 1747032441210,
  "finished_at": 1747032457530,
  "expires_at": 1747291657530,
  "task_error": {

    "message": ""

  },

  "consumed_credits": 3,
  "result": {
    "animation_glb_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/Animation_Reaping_Swing_withSkin.glb?Expires=...",
    "animation_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/Animation_Reaping_Swing_withSkin.fbx?Expires=...",
    "processed_usdz_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/processed.usdz?Expires=...",
    "processed_armature_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/processed_armature.fbx?Expires=...",
    "processed_animation_fps_fbx_url": "https://assets.meshy.ai/0630d47c-84b8-4d37-bc02-69e45d9272c1/tasks/018c425b-b2c6-727e-d333-3c1887i9h791/output/processed_60fps.fbx?Expires=..."
  },
  "preceding_tasks": 0
}
```

---

## DELETE /openapi/v1/animations/:id -- Delete an Animation Task

This endpoint permanently deletes an animation task, including all associated models and data. This action is irreversible.

### Path Parameters

  - `id` · *path*

  The ID of the animation task to delete.

### Task Status
A task that is still `PENDING` is deleted and the credits consumed at
create-time are refunded.

A task that is already `IN_PROGRESS` cannot be deleted: the request is
rejected with `409 Conflict` and the task keeps running. Credits for a task
the worker has already started are not refundable, so deleting it mid-run
would cost you the credits and the result both. Wait for it to reach
`SUCCEEDED`, `FAILED` or `CANCELED`, then delete it.

A task in a terminal state (`SUCCEEDED`, `FAILED` or `CANCELED`) is deleted
without a refund.

### Returns
Returns `200 OK` on success, or `409 Conflict` when the task is
`IN_PROGRESS`.

  **cURL**

  ```bash
  curl --request DELETE \
    --url https://api.meshy.ai/openapi/v1/animations/018b314a-a1b5-716d-c222-2f1776f7f579 \
    -H "Authorization: Bearer ${YOUR_API_KEY}"
  ```

  ```javascript
  import axios from 'axios'

  const taskId = '018b314a-a1b5-716d-c222-2f1776f7f579'
  const headers = { Authorization: `Bearer ${YOUR_API_KEY}` }

  try {
    await axios.delete(
      `https://api.meshy.ai/openapi/v1/animations/${taskId}`,
      { headers }
    )
  } catch (error) {
    console.error(error)
  }
  ```

  ```python
  import requests

  task_id = "018b314a-a1b5-716d-c222-2f1776f7f579"
  headers = {
      "Authorization": f"Bearer {YOUR_API_KEY}"
  }

  response = requests.delete(
      f"https://api.meshy.ai/openapi/v1/animations/{task_id}",
      headers=headers,
  )
  response.raise_for_status()
  ```

**Response**

```json
// 200 OK on success, with an empty body.
//
// 409 Conflict when the task is IN_PROGRESS — the task is left running:
{
  "message": "Task is IN_PROGRESS and cannot be deleted. Credits for a task the worker has already started are not refundable; wait for it to reach SUCCEEDED, FAILED or CANCELED, then delete it."
}
```

---

## GET /openapi/v1/animations -- List Animation Tasks

Returns a paginated list of the caller's animation tasks, newest first. Standard pagination via `page_num` and `page_size`.

Note that tasks created through the API are managed through the API — they do not appear in the web app's My Assets. Use this endpoint to find a task whose ID you no longer have.

  **cURL**

  ```bash
  curl "https://api.meshy.ai/openapi/v1/animations?page_num=1&page_size=20" \
  -H "Authorization: Bearer ${YOUR_API_KEY}"
  ```

---

## GET /openapi/v1/animations/:id/stream -- Stream an Animation Task

This endpoint streams real-time updates for an Animation task using Server-Sent Events (SSE).

### Parameters

  - `id` · *path*

  Unique identifier for the Animation task to stream.

### Returns

Returns a stream of [The Animation Task Objects](#the-animation-task-object) as Server-Sent Events.

For `PENDING` or `IN_PROGRESS` tasks, the response stream will only include necessary `progress` and `status` fields.

  **cURL**

  ```bash
  curl -N https://api.meshy.ai/openapi/v1/animations/018c425b-b2c6-727e-d333-3c1887i9h791/stream
  -H "Authorization: Bearer ${YOUR_API_KEY}"
  ```

  ```javascript
  const response = await fetch(
    'https://api.meshy.ai/openapi/v1/animations/018c425b-b2c6-727e-d333-3c1887i9h791/stream',
    {
      headers: { Authorization: `Bearer ${YOUR_API_KEY}` }
    }
  );

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split('\n');
    buffer = lines.pop();

    for (const line of lines) {
      if (line.startsWith('data:')) {
        const data = JSON.parse(line.slice(5));
        console.log(data);

        if (['SUCCEEDED', 'FAILED', 'CANCELED'].includes(data.status)) {
          reader.cancel();
        }
      }
    }
  }
  ```

  ```python
  import requests
  import json

  headers = {
      "Authorization": f"Bearer {YOUR_API_KEY}",
      "Accept": "text/event-stream"
  }
  task_id = "018c425b-b2c6-727e-d333-3c1887i9h791"

  response = requests.get(
      f'https://api.meshy.ai/openapi/v1/animations/{task_id}/stream',
      headers=headers,
      stream=True
  )

  for line in response.iter_lines():
      if line:
          if line.startswith(b'data:'):
              data_str = line.decode('utf-8')[5:]
              try:
                  data = json.loads(data_str)
                  print(data)

                  if data.get('status') in ['SUCCEEDED', 'FAILED', 'CANCELED']:
                      break
              except json.JSONDecodeError:
                  print(f"Failed to decode JSON: {data_str}")

  response.close()
  ```

  **Response Stream**

  ```javascript
  // Error event example
  event: error
  data: {
    "status_code": 404,
    "message": "Task not found"
  }

  // Message event examples illustrate task progress.
  // For PENDING or IN_PROGRESS tasks, the response stream will not include all fields.
  event: message
  data: {
    "id": "018c425b-b2c6-727e-d333-3c1887i9h791",
    "progress": 0,
    "status": "PENDING"
  }

  event: message
  data: {
    "id": "018c425b-b2c6-727e-d333-3c1887i9h791",
    "progress": 50,
    "status": "IN_PROGRESS"
  }

  event: message
  data: { // Example of a SUCCEEDED task stream item, mirroring The Animation Task Object structure
    "id": "018c425b-b2c6-727e-d333-3c1887i9h791",
    "type": "animate",
    "status": "SUCCEEDED",
    "created_at": 1747032440896,
    "progress": 100,
    "started_at": 1747032441210,
    "finished_at": 1747032457530,
    "expires_at": 1747291657530,
    "task_error": {

      "message": ""

    },

    "consumed_credits": 3,
    "result": {
      "animation_glb_url": "https://assets.meshy.ai/.../Animation_Reaping_Swing_withSkin.glb?...",
      "animation_fbx_url": "https://assets.meshy.ai/.../Animation_Reaping_Swing_withSkin.fbx?...",
      "processed_usdz_url": "https://assets.meshy.ai/.../processed.usdz?...",
      "processed_armature_fbx_url": "https://assets.meshy.ai/.../processed_armature.fbx?...",
      "processed_animation_fps_fbx_url": "https://assets.meshy.ai/.../processed_60fps.fbx?..."
    },
    "preceding_tasks": 0
  }
```

---

## The Animation Task Object
The Animation Task object represents the work unit for applying an animation to a rigged character.

### Properties

  - `id` · *string*

  Unique identifier for the task.

  - `type` · *string*

  Type of the Animation task. The value is `animate`.

  - `status` · *string*

  Status of the task. Possible values: `PENDING`, `IN_PROGRESS`, `SUCCEEDED`, `FAILED`, `CANCELED`.

  - `progress` · *integer*

  Progress of the task (0-100).

  - `created_at` · *timestamp*

  Timestamp (milliseconds since epoch) when the task was created.

  > **Note:** A timestamp represents the number of milliseconds elapsed since January 1, 1970 UTC, following
  >             the [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) standard.
  >             For example, Friday, September 1, 2023 12:00:00 PM GMT is represented as `1693569600000`. This applies
  >             to **all** timestamps in Meshy API.

  - `started_at` · *timestamp*

  Timestamp (milliseconds since epoch) when the task started processing. `0` if not started.

  - `finished_at` · *timestamp*

  Timestamp (milliseconds since epoch) when the task finished. `0` if not finished.

  - `expires_at` · *timestamp*

  Timestamp (milliseconds since epoch) when the task result assets expire.

  - `task_error` · *object*

  Error details for failed tasks. See [Errors](/api/errors#task-errors) for the full `task_error` object reference.

  - `consumed_credits` · *integer*

  The number of credits consumed by this task. Present when the task status is `PENDING`, `IN_PROGRESS`, or `SUCCEEDED`. Returns `0` for `FAILED` tasks (credits are refunded on failure).

  - `result` · *object*

  Contains the output animation URLs if the task `SUCCEEDED`.

- `animation_glb_url` · *string*

  Downloadable URL for the animation in GLB format. For a task created with `action_ids`, this single file contains every requested action as a separate clip.

- `animation_fbx_url` · *string*

  Downloadable URL for the animation in FBX format. For a task created with `action_ids`, this single file contains every requested action as a separate clip.

- `processed_usdz_url` · *string*

  Downloadable URL for the processed animation in USDZ format.

- `processed_armature_fbx_url` · *string*

  Downloadable URL for the processed armature in FBX format.

- `processed_animation_fps_fbx_url` · *string*

  Downloadable URL for the animation with changed FPS in FBX format (e.g., if `change_fps` operation was used).

  - `preceding_tasks` · *integer*

  The count of preceding tasks in the queue. Meaningful only if status is `PENDING`.

  <span id="example-animation-task-object" />

  **Example Animation Task Object**

  ```json
  {
    "id": "018c425b-b2c6-727e-d333-3c1887i9h791",
    "type": "animate",
    "status": "SUCCEEDED",
    "created_at": 1747032440896,
    "progress": 100,
    "started_at": 1747032441210,
    "finished_at": 1747032457530,
    "expires_at": 1747291657530,
    "task_error": {

      "message": ""

    },

    "consumed_credits": 3,
    "result": {
      "animation_glb_url": "https://assets.meshy.ai/.../Animation_Reaping_Swing_withSkin.glb?...",
      "animation_fbx_url": "https://assets.meshy.ai/.../Animation_Reaping_Swing_withSkin.fbx?...",
      "processed_usdz_url": "https://assets.meshy.ai/.../processed.usdz?...",
      "processed_armature_fbx_url": "https://assets.meshy.ai/.../processed_armature.fbx?...",
      "processed_animation_fps_fbx_url": "https://assets.meshy.ai/.../processed_60fps.fbx?..."
    },
    "preceding_tasks": 0
  }
  ```

---

## GET /openapi/v1/animations/library -- List Animations

Returns every animation in the library, ordered by `action_id`. The response is a complete list rather than a page, so one call is enough to populate an action picker. Filters narrow the result; omit them all to fetch everything.

To browse the same catalogue by eye, with an animated preview of each action, see the [Animation Library reference](/api/animation-library).

This endpoint is free — it consumes no credits.

### Parameters

  - `search` · *string*

  Case-insensitive substring match on `name` or `key`. Matched literally, so `%` and `_` are ordinary characters rather than wildcards.

  - `category` · *string*

  Exact match on `category`.

  Available values:
  * `WalkAndRun`
  * `BodyMovements`
  * `DailyActions`
  * `Fighting`
  * `Dancing`

  - `sub_category` · *string*

  Exact match on `sub_category`. Accepted on its own — sub-category names are not unique across categories (`Transitioning` appears under both `Fighting` and `DailyActions`), so without a `category` the filter matches that sub-category wherever it appears.

  - `action_ids` · *string*

  Comma-separated list of `action_id` values to return, for resolving specific ids rather than browsing. Accepts at most 200 ids. Ids that no animation carries are simply absent from the response, so you can also use this to check whether ids you have stored are still available.

### Combining filters

Filters are applied together — each one narrows the result further, so an animation is returned only if it satisfies all of them. Within a single filter, multiple values match any of them: `search` matches `name` or `key`, and `action_ids` matches any id in the list.

That means a combination with no overlap returns an empty array rather than an error. Action `92` is "Double Combo Attack", a `Fighting` animation:

* `?action_ids=92&category=Fighting` returns action `92`.
* `?action_ids=92&category=Dancing` returns `[]` — it is not a `Dancing` animation.
* `?action_ids=92&search=walk` returns `[]` — its name does not match `walk`.

To fetch specific animations regardless of their category, pass `action_ids` on its own.

### Returns

Returns a list of [The Animation Objects](#the-animation-object).

> **Note:** Every `action_id` returned here is accepted by [Create an Animation Task](#create-an-animation-task) above, and every id it accepts is returned here. Retired animations are absent from both. If you cache the library, refresh it periodically so a retired id does not linger in your picker.

  **cURL**

  ```bash
  curl "https://api.meshy.ai/openapi/v1/animations/library?category=Fighting" \
  -H "Authorization: Bearer ${YOUR_API_KEY}"
  ```

  ```javascript
  import axios from 'axios';

  const headers = {Authorization: `Bearer ${YOUR_API_KEY}`};

  try {
    const response = await axios.get(
      'https://api.meshy.ai/openapi/v1/animations/library',
      {
        headers,
        params: {category: 'Fighting'},
      }
    );
    console.log(response.data);
  } catch (error) {
    console.error(error);
  }
  ```

  ```python
  import requests

  headers = {
    "Authorization": f"Bearer {YOUR_API_KEY}"
  }

  response = requests.get(
    "https://api.meshy.ai/openapi/v1/animations/library",
    headers=headers,
    params={"category": "Fighting"},
  )
  response.raise_for_status()
  print(response.json())
  ```

**Response**

```json
[
  {
    "action_id": 4,
    "name": "Attack",
    "key": "Attack",
    "category": "Fighting",
    "sub_category": "AttackingwithWeapon",
    "preview_url": "https://cdn.meshy.ai/webapp-assets/feature-demo/animation/preview/biped/Attack.gif"
  },
  {
    "action_id": 92,
    "name": "Double Combo Attack",
    "key": "Double_Combo_Attack",
    "category": "Fighting",
    "sub_category": "AttackingwithWeapon",
    "preview_url": "https://cdn.meshy.ai/webapp-assets/feature-demo/animation/preview/biped/Double_Combo_Attack.gif"
  }
]
```

---

## The Animation Object

  - `action_id` · *integer*

  The value to pass as `action_id` when creating an animation task. Unique and stable, but not contiguous — retired animations leave gaps in the numbering, so never assume a range of ids is valid.

  - `name` · *string*

  Human-readable label, for display. Not unique: some animations share a name with a different variant, so use `action_id` or `key` as the identity.

  - `key` · *string*

  Unique stable slug for the animation. Use it when you need a non-numeric identifier to key your own storage on.

  - `category` · *string*

  Top-level grouping, e.g. `Fighting`.

  - `sub_category` · *string*

  Grouping within the category, e.g. `AttackingwithWeapon`.

  - `preview_url` · *string*

  URL of an animated GIF previewing the action, suitable for rendering directly in your own picker.

<span id="example-animation-object" />

**Example Animation Object**

```json
{
  "action_id": 92,
  "name": "Double Combo Attack",
  "key": "Double_Combo_Attack",
  "category": "Fighting",
  "sub_category": "AttackingwithWeapon",
  "preview_url": "https://cdn.meshy.ai/webapp-assets/feature-demo/animation/preview/biped/Double_Combo_Attack.gif"
}
```
