SyncMonster API
Generate lip-sync and expression editing on videos. Find Face detects scenes
and faces in video segments and returns the same. Generate then produces
lip-sync, drama, or both on the faces you choose by face_id.
🔑 Authentication
Every request must include your API key in the request headers. Keep this key secret and never expose it in client-side code.
| Header | Value | Description |
|---|---|---|
| x-api-key | YOUR_API_KEY | Pass your secret key here |
curl -X GET \
https://studio.syncmonster.ai/neuralgarage/saas/api/v1/clients/list-assets \
-H "x-api-key: YOUR_API_KEY"
🧪 API Sandbox
Call any endpoint right from this page with your own API key. Your key stays in this browser tab only and is sent straight to the SyncMonster API. POST requests run real jobs and use credits.
🔀 How It Works
The pipeline runs in two stages. Find Face handles scene detection and face detection; Generate drives the chosen faces with lip-sync and/or drama.
/generate — that one face is used automatically. Selection matters when a scene has
multiple faces.
skip_find_face=1 directly to
POST /generate with the video attached — steps 1–3 above run inline
automatically (scene detect, face detect, auto-select) and you get back a single
request_id. Faster for the common case; use the multi-step flow when you need to
preview/choose a specific face first via /get-face.
All steps are billed per second of video.
📡 Status Codes
All API responses include a status field and a corresponding HTTP status code. Use
these to handle responses programmatically.
| Status | Name | Description |
|---|---|---|
| success | Success | The request was successful. |
| created | Created | The request has been fulfilled and a new resource has been created. |
| in_progress | In Progress | The request is being processed. |
| pending | Pending | The request is pending and awaiting processing. |
| invalid_request | Invalid Request | The request is invalid. |
| failed | Failed | The request failed to process. |
| unauthorized | Unauthorized | Authentication is required and has failed. |
| forbidden | Forbidden | You do not have permission to access this resource. |
| not_found | Not Found | The requested resource was not found. |
| internal_error | Internal Server Error | An unexpected error occurred on the server. |
🔍 Find Face
Find Face detects scenes and faces in video segments and returns the same. This runs one time per video — submit, poll for status, then fetch the faces to drive in generation.
find_face_id you poll on
/find-face/status, then read with /get-face.
| Parameter | Type | Required | Description |
|---|---|---|---|
| assets | array | Required (JSON) | Video asset with url or asset_id |
| video | file | Required (Form) | Video file upload — .mp4 or .mov |
| video_asset_id | integer | Optional | Existing video asset ID (alternative to upload) |
| options.scene_threshold | float | Optional | Scene split sensitivity |
| options.min_scene_length | integer | Optional | Minimum frames between scene cuts |
{
"assets": [
{ "type": "video", "asset_id": 123 }
],
}
video=@/path/to/video.mp4
{
"status": "success",
"message": "Find-face job created",
"data": {
"find_face_id": "ff_740006cb51da497fa1930dfe10520cc4",
"video_asset_id": 123,
"credit_details": { "rate_per_sec": 0.5 }
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| find_face_id | string | Required | Find-face ID from POST /find-face |
GET /v2/find-face/status?find_face_id=ff_740006cb51da497fa1930dfe10520cc4
{
"status": "success",
"message": "Status fetched",
"data": {
"find_face_id": "ff_740006cb51da497fa1930dfe10520cc4",
"status": "in_progress",
"status_code": 102
}
}
global_face_id to select a face in /generate.
| Parameter | Type | Required | Description |
|---|---|---|---|
| find_face_id | string | Required | Find-face ID |
GET /v2/get-face?find_face_id=ff_740006cb51da497fa1930dfe10520cc4
global_face_id and includes a base64-encoded representative image in
representative_face_base64.
| Field | Type | Description |
|---|---|---|
| global_face_id | integer | Unique identifier for the face across the find-face response |
| representative_face_base64 | string | Base64-encoded representative image for the detected face |
{
"status": "success",
"message": "Faces fetched",
"data": {
"find_face_id": "ff_740006cb51da497fa1930dfe10520cc4",
"video_asset_id": 264,
"faces": [
{
"global_face_id": 0,
"representative_face_base64": "base64code"
},
{
"global_face_id": 1,
"representative_face_base64": "base64code"
}
]
}
}
The response can return several faces, each with global_face_id and
representative_face_base64. Pick which face(s) to drive in
/generate.
The faces array is empty. In that case, there is nothing to select and the
request has no face-based output to drive.
Only one face is returned. You can skip selection and go straight to lip-sync or drama generation — that face is used automatically.
🎬 Generate
Generate is used to produce lip-sync, drama, or both on the face you selected.
is_lipsync, is_drama, or both. Combine them to apply
emotional performance on top of lip-sync. Select a single face with
global_face_id and tune intensity via options.
skip_find_face=1 to skip
POST /find-face entirely. Send the video directly to
/generate and scene detection, face detection and
clustering all run inline, then a face is auto-selected — global_face_id defaults to
0 if omitted. One request in, one request_id out. Trade-off:
you don't get to preview detected faces via /get-face before dubbing, so
use it when you already know which face you want (or the video only has one).
| Parameter | Type | Required | Description |
|---|---|---|---|
| skip_find_face | boolean | Optional (default 0) | Set to 1 for one-shot mode — provide
video directly instead of find_face_id. See the
one-shot example below. |
| find_face_id | string | Required unless skip_find_face=1 | Completed find-face request ID (the find_face_id from
POST /find-face)
|
| video | file | Required if skip_find_face=1 (Form) | Video upload for one-shot mode — alternative to video_asset_id
or a video entry in assets (JSON) |
| video_asset_id | integer | Optional (Form, skip_find_face=1) | Existing video asset ID, reused instead of re-uploading |
| is_lipsync | boolean | Required | Enable lip-sync |
| is_drama | boolean | Required | Enable drama. May be combined with lip-sync |
| model | string | Required if is_lipsync=true | Lip-sync model — e1 Pro (recommended), e2
Adaptive, e3 Legacy |
| assets | array | Required (JSON) | Audio input with url or asset_id — plus a
video entry when skip_find_face=1 |
| audio | file | Required (Form) | Audio upload — .mp3 or .wav |
| global_face_id | integer | Required unless skip_find_face=1 | Selected face ID returned from /get-face. With
skip_find_face=1 this is optional and defaults to
0 (a face is auto-selected for you). |
| drama_params | object | Optional if is_drama=true | Same shape as drama below — {"happy":0.8,"sad":0.2,...}.
Accepted as an alternate key name (e.g. in form-data). |
| audio_asset_id | integer | Optional | Existing audio asset ID |
| options.intensity | float | Optional if is_lipsync=true | Lip-sync strength: 0.5 to 3.5. Sent in
options.
|
| drama.happy | float | Optional if is_drama=true | Happy intensity: 0 to 1 |
| drama.sad | float | Optional if is_drama=true | Sad intensity: 0 to 1 |
| drama.excited | float | Optional if is_drama=true | Excited intensity: 0 to 1 |
| drama.angry | float | Optional if is_drama=true | Angry intensity: 0 to 1 |
is_lipsync and is_drama in
any combination. At least one must be true. Use
global_face_id to select a face and send intensity in
options.
{
"find_face_id": "ff_740006cb51da497fa1930dfe10520cc4",
"is_lipsync": true,
"is_drama": true,
"model": "e2",
"assets": [
{ "type": "audio", "asset_id": 124 }
],
"drama": {
"happy": 0.8,
"sad": 0.2,
"excited": 0.6,
"angry": 0.1
},
"options": {
"intensity": 2.0
}
}
{
"find_face_id": "ff_740006cb51da497fa1930dfe10520cc4",
"is_lipsync": true,
"is_drama": false,
"model": "e2",
"assets": [
{ "type": "audio", "asset_id": 124 }
],
"options": { "intensity": 1.5 }
}
{
"find_face_id": "ff_740006cb51da497fa1930dfe10520cc4",
"is_lipsync": false,
"is_drama": true,
"assets": [
{ "type": "audio", "url": "https://example.com/audio.wav" }
],
"drama": { "happy": 0.7, "excited": 0.5 }
}
find_face_id or global_face_id needed — send the video
straight in, and lip-sync/drama get applied to face global_face_id=0 (the
auto-selected face) in a single call.
{
"skip_find_face": 1,
"is_lipsync": true,
"is_drama": true,
"model": "e1",
"assets": [
{ "type": "video", "url": "https://example.com/podcastSarvam.mp4" },
{ "type": "audio", "url": "https://example.com/podcastSarvam.mp3" }
],
"drama_params": { "excited": 1 },
"options": { "intensity": 2.0 }
}
{
"status": "success",
"message": "Job Created",
"data": {
"request_id": "9fdfaf1a24d14db2b6e6821a69add99b",
"assets": [
{ "type": "video", "asset_id": 536 },
{ "type": "audio", "asset_id": 537 }
],
"auto_find_face": true
}
}
GET /get-request?request_id=... and read credit_details.credits_deducted
once status is Success. auto_find_face tells you
which billing path applied: true = one-shot (face detection + lip-sync/drama),
false = two-step (face detection already billed by the earlier
/find-face call, only lip-sync/drama billed here).
{
"status": "failed",
"message": "Invalid audio format '.txt'. Allowed: .mp4, .mov, .wav, .mp3",
"data": {
"error_code": "ERR_008",
"error_name": "INVALID_FORMAT",
"message": "Invalid file type. Supported types are: .mp4, .mov"
}
}
🎭 Lipsync & Drama Parameters
Drives mouth movement to match the supplied audio. Requires a model — pick one of
the three modes below; lipsync_intensity tunes how pronounced the sync is.
Ideal for frontal faces. Delivers natural output with high precision.
Handles a wide range of angles with balanced realism.
Generalized model designed for overall coverage across consistency and sync.
e1,
e2, e3.
| Parameter | Type | Range | Description |
|---|---|---|---|
| model | string | e1 / e2 / e3 | Lip-sync model — e1 Pro, e2 Adaptive, e3
Legacy. Required when is_lipsync=true. e1 recommended
|
| intensity | float | 0.5 – 3.5 | Sync strength: lower is subtle, higher is more pronounced |
Adds emotional performance to the driven faces. Each emotion is a float in 0 – 1
acting as its intensity. Combine emotions to shape the delivery.
Raising happy effectively lowers sad, and vice versa — they sit on the same axis.
| Parameter | Type | Range | Description |
|---|---|---|---|
| drama.happy | float | 0 – 1 | Happy intensity (inverse of sad) |
| drama.sad | float | 0 – 1 | Sad intensity (inverse of happy) |
| drama.excited | float | 0 – 1 | Excited intensity |
| drama.angry | float | 0 – 1 | Angry intensity |
After /get-face returns the detected faces, choose the face to drive using
global_face_id. Send lip-sync intensity inside options.
{
"find_face_id": "65bf2dc3926d48498ac76c7aae539647",
"global_face_id": 0,
"options": { "intensity": 2.5 }
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string | Required | The job request ID returned from POST /generate |
GET /get-status?find_face_id=a1b2c3d4e5f6g7h8
{
"status": "success",
"message": "Request status fetched",
"data": {
"request_id": "a1b2c3d4e5f6g7h8",
"status": "Success",
"status_code": "success",
"assets": { "video": 38, "audio": 45 }
}
}
{
"status": "failed",
"message": "Request ID not found"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string | Required | The completed job request ID |
GET /get-file?request_id=a1b2c3d4e5f6g7h8
Content-Type: video/mp4 Content-Disposition: attachment; filename="output.mp4" // Binary video data stream
{
"status": "success",
"data": {
"request_id": "a1b2c3d4e5f6g7h8",
"status": "in_progress",
"status_code": 102,
"message": "Job is still processing. Please try again later."
}
}
📦 Assets & Requests
Utility endpoints for listing and inspecting requests and uploaded assets.
| Parameter | Type | Default | Description |
|---|---|---|---|
| limit | integer | 10 | Records to return per page |
| offset | integer | 0 | Starting offset for pagination |
| type | string | all | Optional filter: generate, find-face, or omit to
return all requests |
GET /list-requests?limit=10&offset=0&type=generate GET /list-requests?limit=10&offset=0&type=find-face GET /list-requests?limit=10&offset=0
{
"status": "success",
"message": "Requests fetched",
"data": {
"requests": [
{
"request_id": "eca2322beafb427fb26fe39d90714ef5",
"type": "generate",
"status": "Success",
"status_code": "success",
"created_at": "2026-07-10T11:44:23",
"completed_at": "2026-07-10T11:50:26"
}
],
"total_requests": 19,
"end_of_records": false
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string | Required | Find-face or generate request ID |
GET /get-request?request_id=a1b2c3d4e5f6g7h8
{
"status": "success",
"message": "Request fetched",
"data": {
"request_id": "a1b2c3d4e5f6g7h8",
"type": "generate",
"status": "Success",
"status_code": "success",
"is_lipsync": true,
"is_drama": true,
"model": "e2",
"assets": { "video": 123, "audio": 124 },
"created_at": "2026-04-07T04:13:23",
"completed_at": "2026-04-07T04:14:04",
"credit_details": { "credits_deducted": 2 }
}
}
No parameters required. Returns all assets associated with your API key.
GET /list-assets
{
"status": "success",
"message": "Assets listed",
"data": [
{ "asset_id": 123, "media_type": "video" },
{ "asset_id": 124, "media_type": "audio" },
{ "asset_id": 125, "media_type": "video" }
]
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| asset_id | integer | Required | The asset ID to retrieve |
GET /get-asset?asset_id=123
{
"status": "success",
"message": "Asset Fetched",
"data": {
"asset_id": 123,
"media_type": "video"
}
}
{
"status": "failed",
"message": "Asset not found"
}
🛠️ Utility Endpoints
Check your credit balance and confirm that the service is healthy.
x-api-key header used by the rest of the API.
{
"status": "success",
"message": "Credits fetched",
"data": {
"credits": 1234.0
}
}
{
"status": "success",
"message": "OK",
"data": {
"status": "healthy"
}
}
⚙️ Processing Phases
/find-face and can be skipped if the video was already processed.
⚠️ Error Codes
| Code | Name | Description |
|---|---|---|
| ERR_003 | INTERNAL_SERVER_ERROR | An internal server error occurred |
| ERR_004 | NO_FACE_FOUND | No face was detected in the provided video |
| ERR_006 | INSUFFICIENT_CREDITS | Not enough credits to complete the request |
| ERR_007 | DATA_CORRUPTED | Uploaded data is corrupted or invalid |
| ERR_008 | INVALID_FORMAT | Unsupported file type. Accepted: .mp4, .mov, .mp3, .wav |
| ERR_009 | LIMIT_EXCEEDS | Video duration exceeds the limit. |