> ## Documentation Index
> Fetch the complete documentation index at: https://heygen-1fa696a7.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Lipsyncs

> Submit up to 100 lipsync requests in a single call. Re-sync many videos to new audio tracks together, then poll one batch id for per-item progress.

## Overview

Lipsync batches let you submit many lipsync jobs in one request instead of calling [`POST /v3/lipsyncs`](/reference/create-lipsync) once per job. You send an array of lipsync payloads, get back a single `batch_id` right away, and poll that one id for the status and id of every item.

Each item in a batch is a standard lipsync payload — the exact shape [`POST /v3/lipsyncs`](/reference/create-lipsync) accepts — so anything you can lipsync on its own can be batched, in either [Speed](/lipsync-speed) or [Precision](/lipsync-precision) mode.

<Note>
  A batch holds up to **100** items. Each payload becomes exactly one batch item, and each item is created and processed independently — one bad source does not fail the rest.
</Note>

## Create a Batch

* Endpoint: `POST /v3/lipsyncs/batches`
* Purpose: Queue up to 100 lipsync payloads and return a `batch_id` immediately.

### Quick Example

```bash theme={null}
curl -X POST "https://api.heygen.com/v3/lipsyncs/batches" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Course module redubs",
    "callback_url": "https://example.com/hooks/heygen",
    "lipsyncs": [
      {
        "video": { "type": "url", "url": "https://example.com/module-1.mp4" },
        "audio": { "type": "url", "url": "https://example.com/module-1-v2.mp3" },
        "title": "Module 1 — updated narration",
        "mode": "speed"
      },
      {
        "video": { "type": "asset_id", "asset_id": "asset_abc123" },
        "audio": { "type": "asset_id", "asset_id": "asset_def456" },
        "title": "Module 2 — updated narration",
        "mode": "precision"
      }
    ]
  }'
```

```json Response theme={null}
{
  "data": {
    "batch_id": "batch_ls_abc123"
  }
}
```

The call returns `202 Accepted` — the batch is queued, not finished. Use the returned `batch_id` to [poll for progress](#get-a-batch).

### Request Body

| Parameter      | Type   | Required | Default | Description                                                                                                             |
| -------------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------- |
| `lipsyncs`     | array  | Yes      | —       | Lipsync payloads, each identical in shape to [`POST /v3/lipsyncs`](/reference/create-lipsync). Between 1 and 100 items. |
| `title`        | string | No       | `null`  | Display name for the batch, shown in the HeyGen app.                                                                    |
| `callback_url` | string | No       | `null`  | [Webhook](/docs/webhooks) URL invoked once when every item in the batch reaches a terminal state.                       |

Each entry in `lipsyncs` takes the full set of lipsync options — `video` and `audio` (each as a `url` or `asset_id`), `mode` (`speed` or `precision`), plus captions, partial-range, and format controls. See [`POST /v3/lipsyncs`](/reference/create-lipsync) for every field.

### Idempotency

Pass an `Idempotency-Key` header to make retries safe — replaying the same key returns the original batch instead of creating a duplicate.

## Get a Batch

* Endpoint: `GET /v3/lipsyncs/batches/{batch_id}`
* Purpose: Return the batch's aggregate status plus one page of items with their id and per-item status.

### Quick Example

```bash theme={null}
curl -X GET "https://api.heygen.com/v3/lipsyncs/batches/batch_ls_abc123?limit=100" \
  -H "x-api-key: YOUR_API_KEY"
```

```json Response theme={null}
{
  "data": {
    "batch_id": "batch_ls_abc123",
    "title": "Course module redubs",
    "status": "processing",
    "total_items": 2,
    "counts_by_status": {
      "completed": 1,
      "processing": 1
    },
    "created_at": 1783891200,
    "items": [
      {
        "item_index": 0,
        "status": "completed",
        "video_id": "ls_9f2c...",
        "error": null
      },
      {
        "item_index": 1,
        "status": "processing",
        "video_id": null,
        "error": null
      }
    ],
    "has_more": false,
    "next_token": null
  }
}
```

<Info>
  The batch read model is shared across the batch APIs, so the per-item id field is named `video_id` — for lipsync batches it holds the **lipsync id**. Use it with [`GET /v3/lipsyncs/{lipsync_id}`](/reference/get-lipsync) for the full record and download URL.
</Info>

### Query Parameters

| Parameter | Type    | Required | Default | Description                                                       |
| --------- | ------- | -------- | ------- | ----------------------------------------------------------------- |
| `limit`   | integer | No       | `100`   | Items per page, `1`–`100`.                                        |
| `token`   | string  | No       | —       | Opaque pagination cursor from a previous response's `next_token`. |

The response shape matches the [video batch](/batch-videos#response-fields): aggregate `status` (`processing`, `completed`, or `failed`), `total_items`, `counts_by_status`, and a paged `items` array where each item carries `item_index`, `status` (`queued`, `processing`, `completed`, or `failed`), its id, and `error` details when failed.

## Bulk Statuses

* Endpoint: `GET /v3/lipsyncs/statuses`
* Purpose: Check up to 100 lipsyncs in one request — across batches, or for jobs created individually.

```bash theme={null}
curl -X GET "https://api.heygen.com/v3/lipsyncs/statuses?batch_ids=batch_ls_abc123" \
  -H "x-api-key: YOUR_API_KEY"
```

| Parameter     | Type   | Required | Description                                                     |
| ------------- | ------ | -------- | --------------------------------------------------------------- |
| `lipsync_ids` | string | No       | Comma-separated lipsync ids to look up.                         |
| `batch_ids`   | string | No       | Comma-separated batch ids; each expands to its member lipsyncs. |

Statuses are `queued`, `processing`, `completed`, or `failed`, plus `not_found` for unknown or unowned ids.

## Tracking completion

* **Webhook (push).** Set `callback_url` on the batch to be notified once, when the last item reaches a terminal state. See [Webhooks](/docs/webhooks) to register an endpoint and verify signatures.
* **Polling (pull).** Call `GET /v3/lipsyncs/batches/{batch_id}` and read `counts_by_status`. Items surface their lipsync id as soon as the job is created, so you can start fetching finished renders with [`GET /v3/lipsyncs/{lipsync_id}`](/reference/get-lipsync) while the rest of the batch is still processing.
