> For the documentation index, fetch https://sync.so/docs/llms.txt. Append .md to a page URL for Markdown. Documentation-search MCP: https://sync.so/docs/_mcp/server. # SDKs > Official Python and TypeScript SDKs for the sync. labs lip sync API. Install, authenticate, and start generating lip synced videos. Sync Labs provides official lip sync SDK libraries for Python and TypeScript. Both SDKs wrap the [Sync Labs API](/api-reference) and give you typed methods for creating generations, polling status, and retrieving results -- so you can add video lip sync integration to your app in minutes. Python JavaScript ## Installation #### Python Requires **Python 3.8+**. ```bash pip install syncsdk ``` #### TypeScript Requires **Node.js 18+**. ```bash npm i @sync.so/sdk ``` ## Authentication Both SDKs read your API key from the `SYNC_API_KEY` environment variable automatically. Set it before running your code: ```bash export SYNC_API_KEY="your-api-key" ``` You can create an API key from the [API Keys](https://sync.so/settings/api-keys) page in your dashboard. See the [Authentication](/api-reference/guides/authentication) guide for more details and security best practices. ## Quick Start The example below creates a lip sync generation and polls until the result is ready. #### Python ```python import time from sync import Sync from sync.common import Audio, Video sync = Sync() # Create a lipsync generation response = sync.generations.create( input=[ Video(url="https://assets.sync.so/docs/example-video.mp4"), Audio(url="https://assets.sync.so/docs/example-audio.wav"), ], model="lipsync-2", ) job_id = response.id print(f"Job submitted: {job_id}") # Poll until complete generation = sync.generations.get(job_id) while generation.status not in ["COMPLETED", "FAILED", "REJECTED"]: time.sleep(10) generation = sync.generations.get(job_id) if generation.status == "COMPLETED": print(f"Output: {generation.output_url}") else: print(f"Generation {job_id} failed") ``` #### TypeScript ```typescript import { SyncClient } from "@sync.so/sdk"; const sync = new SyncClient(); async function main() { // Create a lipsync generation const response = await sync.generations.create({ input: [ { type: "video", url: "https://assets.sync.so/docs/example-video.mp4" }, { type: "audio", url: "https://assets.sync.so/docs/example-audio.wav" }, ], model: "lipsync-2", }); const jobId = response.id; console.log(`Job submitted: ${jobId}`); // Poll until complete let generation = await sync.generations.get(jobId); while (!["COMPLETED", "FAILED", "REJECTED"].includes(generation.status)) { await new Promise((r) => setTimeout(r, 10000)); generation = await sync.generations.get(jobId); } if (generation.status === "COMPLETED") { console.log(`Output: ${generation.outputUrl}`); } else { console.log(`Generation ${jobId} failed`); } } main(); ``` For a full walkthrough with error handling, see the [Quickstart](/quickstart) guide. ## When should I use the SDK vs the raw API? Use the SDK when you want typed methods, automatic authentication, and less boilerplate. Use the raw REST API when you need full control over HTTP requests, work in a language without an official SDK, or want to minimize dependencies. | | SDK | Raw REST API | | :------------------- | :------------------------------------------------- | :--------------------------------------------------- | | **Authentication** | Automatic via `SYNC_API_KEY` env var | Manual `x-api-key` header on every request | | **Type safety** | Full type hints (Python) and TypeScript types | None -- you parse JSON responses yourself | | **Boilerplate** | Minimal -- one-liner to create a generation | Build HTTP requests, parse responses, handle headers | | **Language support** | Python 3.8+ and TypeScript/Node.js 18+ | Any language with an HTTP client | | **Async support** | Python `AsyncSync` client, TypeScript native async | Build your own async handling | | **File uploads** | `create_with_files()` helper method | Multipart form-data via POST /v2/generate/upload | | **Cost estimation** | `estimate_cost()` typed method | POST /v2/generate/estimate-cost | ## Feature comparison Both SDKs cover the full Sync Labs API surface with equivalent functionality: | Feature | Python SDK | TypeScript SDK | | :-------------------- | :------------------------------------------- | :----------------------------------- | | **Package** | `pip install syncsdk` | `npm i @sync.so/sdk` | | **Min runtime** | Python 3.8+ | Node.js 18+ | | **Client class** | `Sync()` / `AsyncSync()` | `SyncClient()` | | **Create generation** | `sync.generations.create(...)` | `sync.generations.create(...)` | | **File upload** | `sync.generations.create_with_files(...)` | POST /v2/generate/upload | | **Poll status** | `sync.generations.get(id)` | `sync.generations.get(id)` | | **List generations** | `sync.generations.list()` | `sync.generations.list()` | | **Cost estimation** | `sync.generations.estimate_cost(...)` | `sync.generations.estimateCost(...)` | | **Batch processing** | `sync.batch.create(...)` | `sync.batch.create(...)` | | **Asset management** | `sync.assets.list()` / `sync.assets.get(id)` | `sync.assets.list()` | | **Async support** | `AsyncSync` client for asyncio | Native async/await | | **Error class** | `ApiError` (status\_code, body) | `SyncError` (statusCode, body) | ## Error handling overview Both SDKs raise typed exceptions for API errors. Wrap your calls in try/except (Python) or try/catch (TypeScript) and inspect the status code to decide how to respond: | Status Code | Meaning | Recommended Action | | :---------- | :------------------------------------------ | :----------------------------------------- | | 400 | Invalid input (bad URL, unsupported format) | Fix input parameters before retrying | | 401 | Missing or invalid API key | Check that `SYNC_API_KEY` is set correctly | | 402 | Feature requires a higher plan | Upgrade at [sync.so](https://sync.so) | | 429 | Rate limit or concurrency limit exceeded | Back off and retry with exponential delay | | 500+ | Transient server error | Retry with exponential backoff | For generation creation, send an [Idempotency-Key](/api-reference/guides/idempotency) on the first attempt and preserve it and the payload across retries. Use backoff and honor `Retry-After`; do not blindly retry an unkeyed create after a timeout or 5xx response. The idempotency guide includes raw HTTP examples you can use independently of your installed SDK version. See the [Python SDK Guide](/developer-guides/sdk-python#error-handling) and [TypeScript SDK Guide](/developer-guides/sdk-typescript#error-handling) for error handling. For the complete list of methods, parameters, and response types, see the [API Reference](/api-reference). > Official Python and TypeScript SDKs for the sync. labs lip sync API. Install, authenticate, and start generating lip synced videos.