Skip to main content
  • Endpoint: POST https://api.heygen.com/v3/lipsyncs
  • Purpose: Dub or replace audio on a video with high-accuracy lip-sync. The job runs asynchronously — poll status via the Get Lipsync Details endpoint.

Quick Example

curl -X POST "https://api.heygen.com/v3/lipsyncs" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "video": { "type": "url", "url": "https://example.com/source.mp4" },
    "audio": { "type": "url", "url": "https://example.com/new-audio.mp3" },
    "mode": "precision"
  }'

Request Body

ParameterTypeRequiredDefaultDescription
videoobjectYesSource video. Provide as { "type": "url", "url": "https://..." } or { "type": "asset_id", "asset_id": "..." } (from POST /v3/assets).
audioobjectYesReplacement audio. Same format options as video.
modestringNoSet to "precision" for avatar-inference lip-sync.
titlestringNoDisplay title for the lipsync in the HeyGen dashboard.
enable_captionbooleanNofalseGenerate captions for the output video.
enable_dynamic_durationbooleanNotrueAllow output duration to adjust to match the new audio length.
disable_music_trackbooleanNofalseStrip background music from the source video.
enable_speech_enhancementbooleanNofalseEnhance speech quality in the output.
enable_watermarkbooleanNofalseAdd a watermark to the output.
start_timenumberNoStart time in seconds for partial lipsync.
end_timenumberNoEnd time in seconds for partial lipsync.
keep_the_same_formatbooleanNoPreserve the source video’s resolution and bitrate.
fps_modestringNoFrame rate mode: "vfr", "cfr", or "passthrough".
callback_urlstringNoWebhook URL — receives a POST when the job completes or fails.
callback_idstringNoArbitrary ID echoed back in the webhook payload.
folder_idstringNoOrganize the lipsync into a specific project folder.

Response

{
  "data": {
    "lipsync_id": "ls_abc123"
  }
}
FieldTypeDescription
lipsync_idstringUnique identifier. Use with GET /v3/lipsyncs/{lipsync_id} to poll status.

Get Lipsync Details

  • Endpoint: GET https://api.heygen.com/v3/lipsyncs/{lipsync_id}
  • Purpose: Get detailed information about a lipsync including status, download URL, and metadata.

Quick Example

curl -X GET "https://api.heygen.com/v3/lipsyncs/ls_abc123" \
  -H "X-Api-Key: $HEYGEN_API_KEY"

Path Parameters

ParameterTypeRequiredDescription
lipsync_idstringYesUnique lipsync identifier.

Response

{
  "data": {
    "id": "ls_abc123",
    "title": "My Lipsync",
    "status": "completed",
    "duration": 42.5,
    "video_url": "https://files.heygen.ai/...",
    "callback_id": null,
    "created_at": 1717000000,
    "failure_message": null
  }
}

Response Fields

FieldTypeDescription
idstringUnique lipsync identifier.
titlestring or nullDisplay title.
statusstringCurrent status: "pending", "running", "completed", or "failed".
durationnumber or nullVideo duration in seconds. Present when completed.
video_urlstring or nullPresigned download URL for the output video. Only present when status is "completed".
callback_idstring or nullClient-provided callback ID.
created_atinteger or nullUnix timestamp of creation.
failure_messagestring or nullError description. Only present when status is "failed".

List Lipsyncs

  • Endpoint: GET https://api.heygen.com/v3/lipsyncs
  • Purpose: List lipsyncs with cursor-based pagination.

Quick Example

curl -X GET "https://api.heygen.com/v3/lipsyncs?limit=10" \
  -H "X-Api-Key: $HEYGEN_API_KEY"

Query Parameters

ParameterTypeRequiredDefaultDescription
limitintegerNo10Results per page (1–100).
tokenstringNoOpaque cursor token for the next page.

Response

{
  "data": [
    {
      "id": "ls_abc123",
      "title": "My Lipsync",
      "status": "completed",
      "duration": 42.5,
      "video_url": "https://files.heygen.ai/...",
      "created_at": 1717000000
    }
  ],
  "has_more": false,
  "next_token": null
}

Update Lipsync

  • Endpoint: PATCH https://api.heygen.com/v3/lipsyncs/{lipsync_id}
  • Purpose: Update a lipsync’s title.

Quick Example

curl -X PATCH "https://api.heygen.com/v3/lipsyncs/ls_abc123" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Updated Title" }'

Request Body

ParameterTypeRequiredDescription
titlestringYesNew title for the lipsync.

Delete Lipsync

  • Endpoint: DELETE https://api.heygen.com/v3/lipsyncs/{lipsync_id}
  • Purpose: Permanently delete a lipsync.

Quick Example

curl -X DELETE "https://api.heygen.com/v3/lipsyncs/ls_abc123" \
  -H "X-Api-Key: $HEYGEN_API_KEY"

Response

{
  "data": {
    "id": "ls_abc123"
  }
}

CLI Usage

# Create with precision mode
heygen lipsync create -d '{
  "video": {"type": "url", "url": "https://example.com/source.mp4"},
  "audio": {"type": "url", "url": "https://example.com/new-audio.mp3"},
  "mode": "precision"
}' --wait

# Poll status manually
heygen lipsync get <lipsync-id>

# List lipsyncs
heygen lipsync list --limit 10

# Update title
heygen lipsync update <lipsync-id> --title "Updated Title"

# Delete
heygen lipsync delete <lipsync-id> --force
Use --request-schema to see all available request fields without needing auth:
heygen lipsync create --request-schema

Polling Pattern

Lipsyncs are processed asynchronously. Poll until status reaches "completed" or "failed". Status transitions: pendingrunningcompleted | failed
while true; do
  STATUS=$(curl -s "https://api.heygen.com/v3/lipsyncs/ls_abc123" \
    -H "X-Api-Key: $HEYGEN_API_KEY" | jq -r '.data.status')
  echo "Status: $STATUS"
  [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ] && break
  sleep 10
done
Or let the CLI handle polling for you:
heygen lipsync create -d '...' --wait --timeout 30m

Asset Inputs

Both video and audio fields accept two input formats: By URL — any publicly accessible HTTPS link:
{ "type": "url", "url": "https://example.com/file.mp4" }
By asset ID — reference a file previously uploaded via POST /v3/assets:
{ "type": "asset_id", "asset_id": "asset_xyz789" }