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://api.syncmonster.ai/neuralgarage/saas/api/v1/clients/list-assets \
-H "x-api-key: YOUR_API_KEY"
🔀 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.
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 }
],
"options": { "scene_threshold": 0.395, "min_scene_length": 3 }
}
video=@/path/to/video.mp4
option={"scene_threshold": 0.395, "min_scene_length": 3}
{
"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 /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
}
}
scene_id + face_id pairs to build scene_faces in /generate.
| Parameter | Type | Required | Description |
|---|---|---|---|
| find_face_id | string | Required | Find-face ID |
scene_id and its own list of faces. Pair scene_id with face_id to drive a specific face in /generate.
| Field | Type | Description |
|---|---|---|
| scene_id | integer | Identifier for the scene within this find-face request |
| start_frame | integer | First frame of the scene |
| end_frame | integer | Last frame of the scene |
| faces | array | Faces detected in the scene (empty if none) |
| Field | Type | Description |
|---|---|---|
| face_id | integer | Identifier for the face within the scene |
| keyframe | integer | Frame index where the face is clearest |
| face_crop | string (url) | Cropped thumbnail of the face for preview |
| face_coordinate | object | Bounding box { x, y, w, h } in the keyframe |
{
"status": "success",
"data": {
"find_face_id": "ff_740006cb51da497fa1930dfe10520cc4",
"video_asset_id": 123,
"scenes": [
{
"scene_id": 1,
"start_frame": 0,
"end_frame": 156,
"faces": [
{
"face_id": 0,
"keyframe": 42,
"face_crop": "https://cdn.syncmonster.ai/faces/ff_..._s1_f0.jpg",
"face_coordinate": { "x": 320, "y": 110, "w": 180, "h": 180 }
},
{
"face_id": 1,
"keyframe": 51,
"face_crop": "https://cdn.syncmonster.ai/faces/ff_..._s1_f1.jpg",
"face_coordinate": { "x": 640, "y": 130, "w": 170, "h": 170 }
}
]
},
{
"scene_id": 2,
"start_frame": 157,
"end_frame": 320,
"faces": [],
"message": "No face in scene"
},
{
"scene_id": 3,
"start_frame": 321,
"end_frame": 498,
"faces": [
{
"face_id": 0,
"keyframe": 360,
"face_crop": "https://cdn.syncmonster.ai/faces/ff_..._s3_f0.jpg",
"face_coordinate": { "x": 480, "y": 120, "w": 175, "h": 175 }
}
]
}
]
}
}
The scene returns several faces, each with face_id, keyframe, face_crop, and face_coordinate. Pick which face_id(s) to drive in /generate.
The faces array is empty and the scene carries "message": "No face in scene". That scene is passed through untouched.
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 faces as per the face_id chosen.
is_lipsync, is_drama, or both. Combine them to apply emotional performance on top of lip-sync. Drive specific faces with options.scene_faces.
| Parameter | Type | Required | Description |
|---|---|---|---|
| find_face_id | string | Required | Completed find-face request ID (the find_face_id from POST /find-face) |
| 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 |
| audio | file | Required (Form) | Audio upload — .mp3 or .wav |
| audio_asset_id | integer | Optional | Existing audio asset ID |
| options.lipsync_intensity | float | Optional if is_lipsync=true | Lip-sync strength: 0.5 to 3.5 |
| 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 |
| options.scene_faces | array | Optional | Per-scene face selection (scene_id + face_ids). Omit for single-face scenes |
is_lipsync and is_drama in any combination. At least one must be true.
{
"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": {
"lipsync_intensity": 2.0,
"scene_faces": [
{ "scene_id": 1, "face_ids": [0, 1] },
{ "scene_id": 3, "face_ids": [0] }
]
}
}
{
"find_face_id": "ff_740006cb51da497fa1930dfe10520cc4",
"is_lipsync": true,
"is_drama": false,
"model": "e2",
"assets": [
{ "type": "audio", "asset_id": 124 }
],
"options": { "lipsync_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 }
}
{
"status": "success",
"message": "Job Created",
"data": {
"request_id": "a1b2c3d4e5f6g7h8", // Use this to poll status
"assets": [
{ "type": "video", "asset_id": 123 },
{ "type": "audio", "asset_id": 124 }
],
"credit_details": { "lipsync_rate_per_sec": 1, "drama_rate_per_sec": 1 }
}
}
{
"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 |
| lipsync_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 Find Face returns the faces in each scene, choose which to drive. Each entry pairs a scene_id with one or more face_ids. Omit it for scenes with a single face.
"scene_faces": [ { "scene_id": 1, "face_ids": [0, 1] }, { "scene_id": 3, "face_ids": [0] } ]
| Parameter | Type | Required | Description |
|---|---|---|---|
| request_id | string | Required | The job request ID returned from POST /generate |
GET /get-status?request_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 |
| page_no | integer | 0 | Page number for pagination |
GET /list-requests?limit=10&page_no=0
{
"status": "success",
"message": "Requests listed",
"data": [
{
"request_id": "740006cb51da497fa1930dfe10520cc4",
"status": "Success",
"status_code": "success",
"created_at": "2026-04-07T04:13:23",
"completed_at": "2026-04-07T04:14:04"
}
],
"total_requests": 14,
"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"
}
⚙️ 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. |