Developer API

Lipsync API Platform

Generate lip-sync videos programmatically with our powerful REST API

API Keys

Manage your API authentication keys

Give your API key a memorable name (optional)

Login Required

Please log in to create and manage API keys.

Pricing That Works For You

Get started with flexible and competitive pricing plans

API Pricing

Pay as you go

Note: API credits and user credits operate independently and are not interchangeable.

Price
Credits
Per Credit

Notes:

Minimum charge: 5 seconds per generation
480p resolution: 2 credits per second
720p resolution: 4 credits per second
lipsync-video: If the video is longer than the audio it will be trimmed; if the audio is longer than the video it will be auto-extended. Billing uses audio length for trim cases and video length for extend cases.
lipsync-image-multi: If order is "meanwhile". Billing uses the maximum audio length; otherwise, it uses the sum of "left_audio" and "right_audio" lengths.
Example 1:
3-second audio at 720p = 5 seconds × 4 = 20 credits
(minimum charge applies)
Example 2:
10-second audio at 480p = 10 × 2 = 20 credits

Authentication

Secure your API requests

Include your API key as an Authorization header in all requests:

Authorization: Bearer sk_XXXX_YYYY

Available Endpoints

RESTful API endpoints

POST/api/v1/lipsync-video

Video-to-video lipsync (replace audio in existing video)

POST/api/v1/lipsync-image

Image + audio → single-speaker talking avatar

POST/api/v1/lipsync-image-multi

Image + dual audio → multi-speaker avatar (conversation/dialogue)

GET/api/v1/jobs/{requestId}

Query job status and retrieve result

Detailed API Parameters

Complete endpoint specifications

All endpoints share a common structure with optional webhook parameter and model-specific formState parameters.

POST /api/v1/lipsync-video

Replace the audio in an existing video with new audio while maintaining lip-sync

Top-level Parameters:
webhookoptional

Your callback URL (HTTPS). We POST the result here when complete.

formStaterequired

Object containing all generation parameters (see below).

formState Parameters:
videorequired

Public URL to source video (MP4, MOV, etc.)

audiorequired

Public URL to speech/replacement audio (MP3, WAV, etc.)

resolutionoptional

"480p" or "720p" (default: 480p)

mask_imageoptional

Public URL to mask image (constrains lip-sync area to masked region)

promptoptional

Text prompt for style guidance

seedoptional

Integer random seed for reproducibility

Async Workflow

Choose how to receive your results

All API calls are asynchronous. You have two options to retrieve results:

Option 1: Webhook (Recommended)

Provide a webhook URL in the JSON body. We will POST the result to your endpoint when the job completes.

Benefits:
  • No need to poll repeatedly
  • Instant notification when job completes
  • More efficient for long-running jobs (30-120 seconds typical)

Option 2: Polling

Omit the webhook parameter and use the returned requestId to poll GET /api/v1/jobs/{requestId} every 5-10 seconds until status is "completed".

Use when:
  • You cannot expose a public webhook endpoint
  • Testing or debugging

Example with Webhook:

POST /api/v1/lipsync-image
Authorization: Bearer sk_XXXX_YYYY
Content-Type: application/json

{
  "webhook": "https://your-app.example.com/webhooks/lipsync",
  "formState": {
    "image": "https://.../face.png",
    "audio": "https://.../voice.mp3",
    "resolution": "720p",
    "seed": 42
  }
}

// Immediate Response:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing"
}

// Later, when job completes, we POST to your webhook:
POST https://your-app.example.com/webhooks/lipsync
Content-Type: application/json

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "model": "lipsync-image",
  "status": "completed",
  "output": "https://.../result.mp4",
  "error": "",
  "executionTime": 12345,
  "timings": null
}

Example without Webhook (Polling):

// Step 1: Submit job (no webhook parameter)
POST /api/v1/lipsync-image
Authorization: Bearer sk_XXXX_YYYY
Content-Type: application/json

{
  "formState": {
    "image": "https://.../face.png",
    "audio": "https://.../voice.mp3",
    "resolution": "720p"
  }
}

// Immediate Response:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing"
}

// Step 2: Poll for status (repeat every 5-10 seconds)
GET /api/v1/jobs/550e8400-e29b-41d4-a716-446655440000
Authorization: Bearer sk_XXXX_YYYY

// Response while processing:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "model": "lipsync",
  "status": "processing",
  "output": null,
  "error": "",
  "executionTime": null,
  "timings": null
}

// Response when completed:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "model": "lipsync-image",
  "status": "completed",
  "output": "https://.../result.mp4",
  "error": "",
  "executionTime": 12345,
  "timings": null
}

// Response if failed:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "model": "lipsync-image",
  "status": "failed",
  "output": null,
  "error": "Invalid audio format",
  "executionTime": null,
  "timings": null
}

Complete Code Examples

Ready-to-use integration examples

Node.js with Webhook (Recommended)

import fetch from 'node-fetch';
import express from 'express';

const API_KEY = 'Bearer sk_XXXX_YYYY';
const BASE_URL = 'https://lipsync.studio/api/v1';

// Set up webhook server to receive results
const app = express();
app.use(express.json());

app.post('/webhooks/lipsync', (req, res) => {
  const { id, status, output, error, model } = req.body;
  
  console.log('✅ Job update received!');
  console.log('Job ID:', id);
  console.log('Model:', model);
  console.log('Status:', status);
  if (status === 'completed') {
    console.log('Video URL:', output);
  } else if (status === 'failed') {
    console.error('Error:', error);
  }
  
  // TODO: Save output URL to your database, send notification, etc.
  
  res.status(200).json({ received: true });
});

app.listen(3000, () => {
  console.log('Webhook server listening on port 3000');
});

// Submit job with webhook
async function submitJobWithWebhook() {
  const webhookUrl = 'https://your-public-domain.com/webhooks/lipsync';
  
  const res = await fetch(`${BASE_URL}/lipsync-image`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': API_KEY
    },
    body: JSON.stringify({
      webhook: webhookUrl,
      formState: {
        image: 'https://example.com/portrait.jpg',
        audio: 'https://example.com/speech.mp3',
        resolution: '720p'
      }
    })
  });
  
  const data = await res.json();
  console.log('Job submitted:', data.id);
  console.log('Waiting for webhook callback...');
  
  // You don't need to poll! The result will be POSTed to your webhook.
}

submitJobWithWebhook();