Skip to content
DashboardGet API Key

Polling & Request Status

How to check the status of lip sync jobs and list your generation history.

Chamelaion processes lip sync jobs asynchronously. After submitting a generation request, you’ll receive a request_id that you use to poll for the result. This guide covers how to check individual request status and list your generation history.

Every lip sync request goes through these stages:

StatusDescription
queuedRequest received and waiting to be processed
processingLip sync generation is in progress
completedGeneration finished — output_url is available
failedGeneration failed — check error_message for details

Use GET /v1/lipsync/requests/{id} to check the status of a specific request. You can pass either the Chamelaion UUID or your own reference_id.

Terminal window
curl https://api.chamelaion.com/api/v1/lipsync/requests/6f82a2d8-a6d4-4e8a-a0fa-e8b09823a2d8 \
-H "Authorization: Bearer $CHAMELAION_API_KEY"
Terminal window
curl https://api.chamelaion.com/api/v1/lipsync/requests/my-custom-reference \
-H "Authorization: Bearer $CHAMELAION_API_KEY"
{
"id": "6f82a2d8-a6d4-4e8a-a0fa-e8b09823a2d8",
"reference_id": "my-custom-reference",
"status": "completed",
"created_at": "2026-04-07T10:00:00Z",
"started_at": "2026-04-07T10:00:05Z",
"finished_at": "2026-04-07T10:01:30Z",
"output_url": "https://storage.chamelaion.com/output/6f82a2d8.mp4"
}
{
"id": "6f82a2d8-a6d4-4e8a-a0fa-e8b09823a2d8",
"reference_id": "my-custom-reference",
"status": "failed",
"created_at": "2026-04-07T10:00:00Z",
"started_at": "2026-04-07T10:00:05Z",
"finished_at": "2026-04-07T10:00:12Z",
"error_message": "video URL is not accessible"
}

Here’s the recommended polling pattern with exponential backoff:

import requests
import time
import os
API_KEY = os.environ["CHAMELAION_API_KEY"]
BASE_URL = "https://api.chamelaion.com/api"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def wait_for_completion(request_id: str, timeout: int = 600) -> dict:
"""Poll a lip sync request until it completes or fails."""
start = time.time()
delay = 2
while time.time() - start < timeout:
response = requests.get(
f"{BASE_URL}/v1/lipsync/requests/{request_id}",
headers=HEADERS,
)
response.raise_for_status()
result = response.json()
if result["status"] == "completed":
return result
elif result["status"] == "failed":
raise Exception(f"Generation failed: {result.get('error_message')}")
time.sleep(delay)
delay = min(delay * 1.5, 15) # cap at 15 seconds
raise TimeoutError(f"Request {request_id} did not complete within {timeout}s")
async function waitForCompletion(
requestId: string,
timeoutMs = 600_000
): Promise<Record<string, unknown>> {
const start = Date.now();
let delay = 2000;
while (Date.now() - start < timeoutMs) {
const response = await fetch(
`https://api.chamelaion.com/api/v1/lipsync/requests/${requestId}`,
{ headers: { Authorization: `Bearer ${process.env.CHAMELAION_API_KEY}` } }
);
const result = await response.json();
if (result.status === "completed") return result;
if (result.status === "failed") {
throw new Error(`Generation failed: ${result.error_message}`);
}
await new Promise((r) => setTimeout(r, delay));
delay = Math.min(delay * 1.5, 15_000);
}
throw new Error(`Request ${requestId} timed out`);
}

Use GET /v1/lipsync/requests to retrieve a paginated list of your lip sync requests.

Terminal window
curl "https://api.chamelaion.com/api/v1/lipsync/requests" \
-H "Authorization: Bearer $CHAMELAION_API_KEY"
Terminal window
curl "https://api.chamelaion.com/api/v1/lipsync/requests?limit=10&offset=20" \
-H "Authorization: Bearer $CHAMELAION_API_KEY"
Terminal window
curl "https://api.chamelaion.com/api/v1/lipsync/requests?reference_id=batch-2026-04" \
-H "Authorization: Bearer $CHAMELAION_API_KEY"
ParameterTypeDefaultDescription
limitinteger20Number of results per page (minimum 1)
offsetinteger0Number of results to skip
reference_idstringFilter by exact reference_id
{
"data": [
{
"id": "6f82a2d8-a6d4-4e8a-a0fa-e8b09823a2d8",
"reference_id": "batch-2026-04",
"status": "completed",
"created_at": "2026-04-07T10:00:00Z",
"started_at": "2026-04-07T10:00:05Z",
"finished_at": "2026-04-07T10:01:30Z",
"output_url": "https://storage.chamelaion.com/output/6f82a2d8.mp4"
},
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"reference_id": "batch-2026-04",
"status": "queued",
"created_at": "2026-04-07T10:02:00Z"
}
],
"pagination": {
"limit": 20,
"offset": 0,
"total": 2
}
}
import requests
import os
API_KEY = os.environ["CHAMELAION_API_KEY"]
BASE_URL = "https://api.chamelaion.com/api"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def list_all_requests():
"""Iterate through all lip sync requests."""
offset = 0
limit = 50
all_requests = []
while True:
response = requests.get(
f"{BASE_URL}/v1/lipsync/requests",
headers=HEADERS,
params={"limit": limit, "offset": offset},
)
response.raise_for_status()
data = response.json()
all_requests.extend(data["data"])
if offset + limit >= data["pagination"]["total"]:
break
offset += limit
return all_requests
FieldTypePresentDescription
idstringAlwaysChamelaion request UUID
reference_idstringIf provided at creationYour custom identifier
statusstringAlwaysCurrent status (queued, processing, completed, failed)
created_atdatetimeAlwaysWhen the request was created (UTC)
started_atdatetimeAfter processing startsWhen processing began (UTC)
finished_atdatetimeAfter completion/failureWhen processing ended (UTC)
output_urlstringOn completedURL to download the generated video
error_messagestringOn failedDescription of what went wrong