---
type: AI Model
id: sync-lipsync
title: Sync Lipsync API
provider: Sync.so
description: "Lip-sync any talking-head video to a separate audio track with Sync.so v3 (via fal.ai). Submit a video URL + audio URL; the model re-syncs the speaker's mouth to the audio."
resource: https://www.pixazo.ai/models/sync-lipsync
docs_url: https://www.pixazo.ai/models/sync-lipsync
latest_version: v3
tags:
  - video-to-video
  - lipsync
  - sync.so
variants:
  - id: sync-lipsync-v3
    name: Sync Lipsync v3
    version: v3
    capabilities:
      - Video to Video (Ref Video + Ref Audio to Video - Lipsync)
  - id: sync-lipsync-v2-pro
    name: Sync Lipsync v2 Pro
    version: v2 Pro
    capabilities:
      - Video to Video (Ref Video + Ref Audio to Video - Lipsync)
timestamp: 2026-07-17T16:20:02.152Z
---

# Sync Lipsync API

> Provider: **Sync.so**
> Source: https://www.pixazo.ai/models/sync-lipsync

Lip-sync any talking-head video to a separate audio track with Sync.so v3 (via fal.ai). Submit a video URL + audio URL; the model re-syncs the speaker's mouth to the audio.

## Sync Lipsync v3

### Video to Video (Ref Video + Ref Audio to Video - Lipsync)

## Sync Lipsync v3 Video + Audio to Video API Documentation

```
POST https://gateway.pixazo.ai/sync-lipsync-v3/v1/video-to-video/lip-sync
```

## Authentication

All requests require an API key passed via header.

Header

Type

Required

Description

Ocp-Apim-Subscription-Key

string

Yes

Your API subscription key

## Video + Audio to Video - Sync Lipsync v3

## Request Code

HTTP Python JavaScript cURL

```
POST https://gateway.pixazo.ai/sync-lipsync-v3/v1/video-to-video/lip-sync
Content-Type: application/json
Cache-Control: no-cache
Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY

{
  "video_url": "https://example.com/input.mp4",
  "audio_url": "https://example.com/voice.mp3",
  "sync_mode": "cut_off"
}
```

```
import requests

url = "https://gateway.pixazo.ai/sync-lipsync-v3/v1/video-to-video/lip-sync"
headers = {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
}
payload = {
    "video_url": "https://example.com/input.mp4",
    "audio_url": "https://example.com/voice.mp3",
    "sync_mode": "cut_off"
}

resp = requests.post(url, headers=headers, json=payload)
print(resp.json())  # { "request_id": "...", "status": "QUEUED", "polling_url": "..." }
```

```
const res = await fetch("https://gateway.pixazo.ai/sync-lipsync-v3/v1/video-to-video/lip-sync", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
  },
  body: JSON.stringify({
    video_url: "https://example.com/input.mp4",
    audio_url: "https://example.com/voice.mp3",
    sync_mode: "cut_off"
  })
});
const data = await res.json();
console.log(data); // { request_id, status: "QUEUED", polling_url }
```

```
curl -X POST "https://gateway.pixazo.ai/sync-lipsync-v3/v1/video-to-video/lip-sync" \
  -H "Content-Type: application/json" \
  -H "Cache-Control: no-cache" \
  -H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY" \
  --data-raw '{
    "video_url": "https://example.com/input.mp4",
    "audio_url": "https://example.com/voice.mp3",
    "sync_mode": "cut_off"
  }'
```

## Output

```
{
  "request_id": "sync-lipsync-v3_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/sync-lipsync-v3_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

[Try Now](https://api.pixazo.ai/api-details#api=sync-lipsync-v3&operation=sync-lipsync-v3-request)

## Webhook (Optional)

Instead of polling, you can receive a callback when the request reaches a terminal state. Pass the webhook headers on the submit request; the gateway will POST the result to your URL.

Header

Type

Required

Description

X-Webhook-URL

string

No

HTTPS URL to receive the callback. Providing it enables webhook delivery.

X-Webhook-Mode

string

No

`terminal` (default) fires once on COMPLETED/ERROR; `sync` fires on each status transition.

### Example: enable webhook

```
curl -X POST "https://gateway.pixazo.ai/sync-lipsync-v3/v1/video-to-video/lip-sync" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY" \
  -H "X-Webhook-URL: https://your-server.com/webhooks/pixazo" \
  -H "X-Webhook-Mode: terminal" \
  --data-raw '{ "video_url": "https://example.com/input.mp4", "audio_url": "https://example.com/voice.mp3" }'
```

### Callback Payload (success)

```
{
  "request_id": "sync-lipsync-v3_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "sync-lipsync-v3",
  "output": {
    "media_url": ["https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/sync-lipsync-v3_019dxxxx.../output.mp4"],
    "media_type": "video/mp4"
  }
}
```

### Failure callback shape

```
{
  "request_id": "sync-lipsync-v3_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "ERROR",
  "error": "Failed to download the file. Please check if the URL is accessible."
}
```

-   **terminal** mode delivers one callback on COMPLETED or ERROR; **sync** mode delivers on each status transition.
-   Deliveries are keyed by `request_id` — make your handler idempotent.
-   Respond with HTTP 200 within a few seconds; non-2xx responses are retried.
-   The webhook URL must be HTTPS and publicly reachable.

## Request Parameters

Parameter

Required

Type

Default

Allowed values / range

Description

video\_url

Yes

string

—

—

Upload the talking-head video clip whose lips will be re-synced to your audio.

audio\_url

Yes

string

—

—

Upload the audio track to sync the video's lips to.

sync\_mode

No

string

cut\_off

cut\_off, loop, bounce, silence, remap

How to handle a duration mismatch between the audio and video. `cut_off` truncates the longer stream; `loop` repeats the shorter stream; `bounce` plays forward then backward; `silence` pads with silence; `remap` time-stretches the audio to match the video.

options

No

object

—

—

Optional container for advanced Sync.so generation settings (see the `options.*` rows below). If `options.sync_mode` is set, it overrides the top-level `sync_mode`.

options.sync\_mode

No

string

—

cut\_off, loop, bounce, silence, remap

How to handle a duration mismatch between the audio and video; overrides the top-level `sync_mode` when provided.

options.model\_mode

No

string

—

lips, face, head, lipsync, emotion, talking\_head

Edit region for the model. A Sync.so option primarily used by react-1.

options.prompt

No

string

—

happy, sad, angry, disgusted, surprised, neutral

Emotion prompt for generation. A Sync.so option primarily used by react-1.

options.temperature

No

float

—

0 – 1

Controls how expressive the lipsync can be; 0 is least expressive, 1 is most expressive. Sync.so handles this natively for sync-3, so this option is ignored by this model.

options.active\_speaker\_detection

No

object

—

—

Active-speaker detection settings for videos with multiple people. Supports `auto_detect` (boolean), `v3` (boolean), `frame_number` (integer), `coordinates` (\[x, y\]), `bounding_boxes` (per-frame \[x1, y1, x2, y2\]), `bounding_boxes_url` (JSON file URL), and `face_image` (base64) for manual speaker selection.

options.occlusion\_detection\_enabled

No

boolean

—

true, false

Whether to detect occlusion during generation. Sync.so handles this automatically for sync-3, so this option is ignored by this model.

### Content Item Types & Limits

Type

Max

Format / Size

Description

video

1

MP4, MOV

Source video.

audio

1

MP3, WAV

Voice / audio track.

## Example Request

```
{
  "video_url": "https://example.com/input.mp4",
  "audio_url": "https://example.com/voice.mp3",
  "sync_mode": "cut_off"
}
```

## Example Response

```
{
  "request_id": "sync-lipsync-v3_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/sync-lipsync-v3_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

## Request Headers

Header

Required

Description

Ocp-Apim-Subscription-Key

Yes

Your API subscription key.

Content-Type

Yes

Must be `application/json`.

X-Webhook-URL

No

HTTPS callback URL (see Webhook section).

## Response Handling

Common status codes returned by the submit endpoint.

Status Code

Meaning

202 Accepted

Request queued. Returns `request_id`, `status: "QUEUED"`, and `polling_url`.

400 Bad Request

Invalid request body or unknown model.

401 Unauthorized

Missing or invalid subscription key.

402 Payment Required

Insufficient wallet balance.

403 Forbidden

Subscription not permitted to access this API.

429 Too Many Requests

Rate limit exceeded.

500 Internal Server Error

Unexpected gateway error.

## Error Responses

Queue-system errors are returned at submit time; generation errors are surfaced via the status endpoint / webhook with `status: "ERROR"`.

```
// 402 — insufficient balance
{ "error": "Insufficient balance", "message": "Wallet balance is too low for this request." }

// 400 — model not found / invalid body
{ "error": "Model not found", "message": "Model 'sync-lipsync-v3' not found or is disabled" }

// generation failure (via status / webhook)
{ "request_id": "sync-lipsync-v3_019dxxxx...", "status": "ERROR", "error": "Failed to download the input file." }
```

## Retrieving Results

Poll the status endpoint with the `request_id` until `status` is `COMPLETED` (or `FAILED`/`ERROR`).

```
curl -X GET "https://gateway.pixazo.ai/v2/requests/status/sync-lipsync-v3_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \
  -H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY"
```

### Completed response

```
{
  "request_id": "sync-lipsync-v3_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "sync-lipsync-v3",
  "error": null,
  "output": {
    "media_url": ["https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/sync-lipsync-v3_019dxxxx.../output.mp4"],
    "media_type": "video/mp4"
  },
  "created_at": "2026-06-30T09:20:33.812Z",
  "completed_at": "2026-06-30T09:22:19.000Z"
}
```

## Response Fields

Field

Type

Description

request\_id

string

Unique identifier for the request.

status

string

QUEUED, PROCESSING, COMPLETED, FAILED, or ERROR.

model\_id

string

The model that handled the request (`sync-lipsync-v3`).

error

string | null

Error message when the request fails; null otherwise.

output.media\_url

string\[\]

Array of URLs to the generated lip-synced MP4 video.

output.media\_type

string

MIME type of the output (`video/mp4`).

created\_at

string

ISO-8601 timestamp when the request was created.

completed\_at

string

ISO-8601 timestamp when the request reached a terminal state.

polling\_url

string

URL to poll for status (returned on submit).

## Status Values & Flow

Status

Meaning

QUEUED

Request accepted and waiting to be processed.

PROCESSING

The lip-sync job is running.

COMPLETED

Done — `output.media_url` contains the synced video.

FAILED / ERROR

Generation failed — see `error`.

### Typical workflow

QUEUED → PROCESSING → COMPLETED (or FAILED / ERROR). Submit the request, then poll `GET /v2/requests/status/{request_id}` (or use a webhook) until the status is terminal, then download the video from `output.media_url`.

## Sync Lipsync v2 Pro

### Video to Video (Ref Video + Ref Audio to Video - Lipsync)

## Sync Lipsync v2 Pro Video + Audio to Video API Documentation

```
POST https://gateway.pixazo.ai/sync-lipsync-v2-pro/v1/video-to-video/lip-sync
```

## Authentication

All requests require an API key passed via header.

Header

Type

Required

Description

Ocp-Apim-Subscription-Key

string

Yes

Your API subscription key

## Video + Audio to Video - Sync Lipsync v2 Pro

## Request Code

HTTP Python JavaScript cURL

```
POST https://gateway.pixazo.ai/sync-lipsync-v2-pro/v1/video-to-video/lip-sync
Content-Type: application/json
Cache-Control: no-cache
Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY

{
  "video_url": "https://example.com/input.mp4",
  "audio_url": "https://example.com/voice.mp3",
  "sync_mode": "cut_off"
}
```

```
import requests

url = "https://gateway.pixazo.ai/sync-lipsync-v2-pro/v1/video-to-video/lip-sync"
headers = {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
}
payload = {
    "video_url": "https://example.com/input.mp4",
    "audio_url": "https://example.com/voice.mp3",
    "sync_mode": "cut_off"
}

resp = requests.post(url, headers=headers, json=payload)
print(resp.json())  # { "request_id": "...", "status": "QUEUED", "polling_url": "..." }
```

```
const res = await fetch("https://gateway.pixazo.ai/sync-lipsync-v2-pro/v1/video-to-video/lip-sync", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
  },
  body: JSON.stringify({
    video_url: "https://example.com/input.mp4",
    audio_url: "https://example.com/voice.mp3",
    sync_mode: "cut_off"
  })
});
const data = await res.json();
console.log(data); // { request_id, status: "QUEUED", polling_url }
```

```
curl -X POST "https://gateway.pixazo.ai/sync-lipsync-v2-pro/v1/video-to-video/lip-sync" \
  -H "Content-Type: application/json" \
  -H "Cache-Control: no-cache" \
  -H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY" \
  --data-raw '{
    "video_url": "https://example.com/input.mp4",
    "audio_url": "https://example.com/voice.mp3",
    "sync_mode": "cut_off"
  }'
```

## Output

```
{
  "request_id": "sync-lipsync-v2-pro_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/sync-lipsync-v2-pro_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

[Try Now](https://api.pixazo.ai/api-details#api=sync-lipsync-v2-pro&operation=sync-lipsync-v2-pro-request)

## Webhook (Optional)

Instead of polling, you can receive a callback when the request reaches a terminal state. Pass the webhook headers on the submit request; the gateway will POST the result to your URL.

Header

Type

Required

Description

X-Webhook-URL

string

No

HTTPS URL to receive the callback. Providing it enables webhook delivery.

X-Webhook-Mode

string

No

`terminal` (default) fires once on COMPLETED/ERROR; `sync` fires on each status transition.

### Example: enable webhook

```
curl -X POST "https://gateway.pixazo.ai/sync-lipsync-v2-pro/v1/video-to-video/lip-sync" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY" \
  -H "X-Webhook-URL: https://your-server.com/webhooks/pixazo" \
  -H "X-Webhook-Mode: terminal" \
  --data-raw '{ "video_url": "https://example.com/input.mp4", "audio_url": "https://example.com/voice.mp3" }'
```

### Callback Payload (success)

```
{
  "request_id": "sync-lipsync-v2-pro_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "sync-lipsync-v2-pro",
  "output": {
    "media_url": ["https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/sync-lipsync-v2-pro_019dxxxx.../output.mp4"],
    "media_type": "video/mp4"
  }
}
```

### Failure callback shape

```
{
  "request_id": "sync-lipsync-v2-pro_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "ERROR",
  "error": "Failed to download the file. Please check if the URL is accessible."
}
```

-   **terminal** mode delivers one callback on COMPLETED or ERROR; **sync** mode delivers on each status transition.
-   Deliveries are keyed by `request_id` — make your handler idempotent.
-   Respond with HTTP 200 within a few seconds; non-2xx responses are retried.
-   The webhook URL must be HTTPS and publicly reachable.

## Request Parameters

Parameter

Required

Type

Default

Allowed values / range

Description

video\_url

Yes

string

—

—

Upload the talking-head video clip whose lips will be re-synced to your audio.

audio\_url

Yes

string

—

—

Upload the audio track to sync the video's lips to.

sync\_mode

No

string

cut\_off

cut\_off, loop, bounce, silence, remap

How to handle a duration mismatch between the audio and video. `cut_off` truncates the longer stream; `loop` repeats the shorter stream; `bounce` plays forward then backward; `silence` pads with silence; `remap` time-stretches the audio to match the video.

### Content Item Types & Limits

Type

Max

Format / Size

Description

video

1

MP4, MOV

Source video.

audio

1

MP3, WAV

Voice / audio track.

## Example Request

```
{
  "video_url": "https://example.com/input.mp4",
  "audio_url": "https://example.com/voice.mp3",
  "sync_mode": "cut_off"
}
```

## Example Response

```
{
  "request_id": "sync-lipsync-v2-pro_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/sync-lipsync-v2-pro_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

## Request Headers

Header

Required

Description

Ocp-Apim-Subscription-Key

Yes

Your API subscription key.

Content-Type

Yes

Must be `application/json`.

X-Webhook-URL

No

HTTPS callback URL (see Webhook section).

## Response Handling

Common status codes returned by the submit endpoint.

Status Code

Meaning

202 Accepted

Request queued. Returns `request_id`, `status: "QUEUED"`, and `polling_url`.

400 Bad Request

Invalid request body or unknown model.

401 Unauthorized

Missing or invalid subscription key.

402 Payment Required

Insufficient wallet balance.

403 Forbidden

Subscription not permitted to access this API.

429 Too Many Requests

Rate limit exceeded.

500 Internal Server Error

Unexpected gateway error.

## Error Responses

Queue-system errors are returned at submit time; generation errors are surfaced via the status endpoint / webhook with `status: "ERROR"`.

```
// 402 — insufficient balance
{ "error": "Insufficient balance", "message": "Wallet balance is too low for this request." }

// 400 — model not found / invalid body
{ "error": "Model not found", "message": "Model 'sync-lipsync-v2-pro' not found or is disabled" }

// generation failure (via status / webhook)
{ "request_id": "sync-lipsync-v2-pro_019dxxxx...", "status": "ERROR", "error": "Failed to download the input file." }
```

## Retrieving Results

Poll the status endpoint with the `request_id` until `status` is `COMPLETED` (or `FAILED`/`ERROR`).

```
curl -X GET "https://gateway.pixazo.ai/v2/requests/status/sync-lipsync-v2-pro_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \
  -H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY"
```

### Completed response

```
{
  "request_id": "sync-lipsync-v2-pro_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "sync-lipsync-v2-pro",
  "error": null,
  "output": {
    "media_url": ["https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/sync-lipsync-v2-pro_019dxxxx.../output.mp4"],
    "media_type": "video/mp4"
  },
  "created_at": "2026-06-30T09:20:33.812Z",
  "completed_at": "2026-06-30T09:22:19.000Z"
}
```

## Response Fields

Field

Type

Description

request\_id

string

Unique identifier for the request.

status

string

QUEUED, PROCESSING, COMPLETED, FAILED, or ERROR.

model\_id

string

The model that handled the request (`sync-lipsync-v2-pro`).

error

string | null

Error message when the request fails; null otherwise.

output.media\_url

string\[\]

Array of URLs to the generated lip-synced MP4 video.

output.media\_type

string

MIME type of the output (`video/mp4`).

created\_at

string

ISO-8601 timestamp when the request was created.

completed\_at

string

ISO-8601 timestamp when the request reached a terminal state.

polling\_url

string

URL to poll for status (returned on submit).

## Status Values & Flow

Status

Meaning

QUEUED

Request accepted and waiting to be processed.

PROCESSING

The lip-sync job is running.

COMPLETED

Done — `output.media_url` contains the synced video.

FAILED / ERROR

Generation failed — see `error`.

### Typical workflow

QUEUED → PROCESSING → COMPLETED (or FAILED / ERROR). Submit the request, then poll `GET /v2/requests/status/{request_id}` (or use a webhook) until the status is terminal, then download the video from `output.media_url`.
