Python SDK Guide
The Sync Labs Python SDK (syncsdk) wraps the Sync Labs REST API with typed methods for Python 3.8+. It provides methods for creating lip sync generations, polling for results, estimating costs, and managing assets.
Source code: sync-python-sdk on GitHub
Installation
Requires Python 3.8+. Install from PyPI:
This guide covers syncsdk 0.4.0 and later. Check your version with pip show syncsdk and upgrade with pip install --upgrade syncsdk. Version 0.4.0 adds image inputs, dub_params, dialogue_edit and project_id on generation create, asset uploads, projects, voices, text-to-speech, transcriptions, dialogue edits, account.get(), feedback.submit(), output_audio and lipsync=False segments, and a working estimate_cost. In 0.4.0, estimate_cost takes a model and a duration (it previously took a full generation request), and generations.delete returns the stored-generation shape.
We recommend using a virtual environment to avoid dependency conflicts:
Authentication
The SDK reads your API key from the SYNC_API_KEY environment variable automatically:
You can also pass the key directly:
Create an API key from the API Keys page in your dashboard. See the Authentication guide for security best practices.
Quick Start
Create a lip sync generation, poll until it finishes, and print the output URL.
Run it:
Core Operations
Creating Generations
Video + Audio
The most common use case. Provide a video and an audio file, and Sync Labs generates matching lip movements.
Video + Text-to-Speech
Use the built-in ElevenLabs integration to go straight from text to lip-synced video. No separate TTS step needed.
The script field has a maximum of 5,000 characters per generation. For longer scripts, split them into segments. See the Text-to-Speech Lip Sync Guide for details.
Polling vs Webhooks
Polling is the simplest approach. Call generations.get() in a loop until the status is terminal:
Webhooks are better for production. Pass a webhook_url when creating the generation, and Sync Labs sends a POST request when the job finishes:
See the Webhooks guide for payload format and signature verification.
Listing Generations
Retrieve your recent generations. Optionally filter by status:
Getting Generation Details
Fetch the full details of a single generation by ID:
Cost Estimation
Estimate a generation from its model and billable duration in seconds. The response is a single object; estimated_credits is None for dollar-billed organizations, and duration_check says whether your plan allows that duration.
Pass workflow="translate-and-dub" to quote dubbing plus lip sync; the response then carries a breakdown.
Working with Files
URL Inputs
The simplest approach — pass publicly accessible URLs for your video and audio:
Image Inputs
sync-3 can animate a still image instead of a video:
Asset IDs
If you have uploaded files to the Sync Labs media library (via the dashboard or Assets API), reference them by asset ID:
Uploading Assets
For large or reused local files, upload them once and generate from the asset ID. See Asset Uploads for the full flow:
File Uploads
Upload local files directly using the multipart endpoint:
The application parser limits file uploads to 5 GiB per file, subject to your plan and any lower proxy limits. For large files, upload them as assets and pass the returned asset ID, so retries don’t resend the file. You can also host them at a public URL and use the URL-based input.
Browsing Assets
List and retrieve assets from your media library:
Other Resources
Every public endpoint in the API Reference has a client method:
Error Handling
The SDK raises ApiError for HTTP errors. Wrap your calls in try/except blocks:
Common Errors
Retry Logic
For generation creation, use the Idempotent Requests contract to protect retries after timeouts and uncertain failures. Save the key before the first attempt and preserve it and the inputs across retries. Send it with idempotency_key= on generations.create, or through request options on any method:
The unkeyed example below retries only explicit HTTP 429 rejections. It does not retry 5xx or transport failures, which may have an unknown submission outcome:
The client’s own max_retries request option also retries HTTP 409. For an unkeyed create, a retry within 60 seconds of an identical request receives DUPLICATE_SUBMISSION instead of a second generation; poll the returned generationId. See Requests without a key.
Async Usage
The SDK includes an async client for use with asyncio. Use AsyncSync instead of Sync:
The async client supports the same methods as the sync client, on every resource.
The async client works with any asyncio-compatible framework like FastAPI, Sanic, or aiohttp.
Type Hints
The SDK is fully typed. All request parameters, response objects, and enums have type annotations. Your editor will provide autocomplete and inline documentation out of the box.
Available Models
See the Models page for detailed comparisons.
Next Steps
- API Reference — Full endpoint documentation with parameter details
- TypeScript SDK Guide — Equivalent guide for the TypeScript SDK
- Video Dubbing API Guide — Build a dubbing pipeline
- Text-to-Speech Lip Sync Guide — Combine TTS with lip sync
- Webhooks — Replace polling with real-time notifications
- Segments Guide — Handle multi-speaker videos
- Error Handling — Full error code reference
Frequently Asked Questions
Does the Python SDK support async?
Yes. The SDK includes an AsyncSync client for use with asyncio. Import AsyncSync instead of Sync and use await with all SDK methods. The async client supports the same operations as the sync client and works with frameworks like FastAPI, Sanic, and aiohttp.
How do I handle timeouts?
Wrap SDK calls in try/except blocks. A generation create timeout can mean the server accepted the request. Retry with the same key and payload if the first attempt used an Idempotency-Key; otherwise confirm the outcome before submitting again. Poll an existing generation ID for status instead of creating another generation.
Can I cancel a generation?
The Sync Labs API does not currently provide a cancel endpoint for in-progress generations. Once a generation is submitted, it will run to completion or fail. You only pay for successfully completed generations. Monitor status via polling or webhooks to track progress.

