API REFERENCE
Errors & limits
Every error is JSON with a stable type you can branch on. Rate limits default to 100 requests a minute and are raised through your point of contact.
01.The error shape
{
"error": {
"type": "unsupported_language",
"message": "\"xx\" is not one of the 30 supported language codes.",
"doc_url": "https://thefamiliarlab.com/docs/languages"
}
}Branch on type, log message, follow doc_url -- messages may be reworded; types are stable within /v1.
02.Request IDs
HTTP/1.1 200 OK Familiar-Request-Id: req_7hk2p0d4
Every response -- success or error -- carries a Familiar-Request-Id header. Log it with your own request logs, and include it when reporting an issue (Help Center): it points the team at the exact request.
03.Status codes
| CODE | TYPE | MEANING |
|---|---|---|
| 400 | invalid_request | A field is missing or malformed; the message names it. |
| 401 | invalid_key | No key, a malformed key, or a key that was rotated away. |
| 403 | api_access_disabled | The key is valid but API access is disabled for its organization (a billing hold or an abuse review). |
| 404 | not_found | No such resource under your organization. |
| 409 | conflict | The action doesn't fit the state -- e.g. rendering a manualdub that isn't in_review, or deleting one mid-render. |
| 422 | unsupported_language | A language code outside the 30, or a source that matches a requested target. |
| 422 | validation_failed | Fields are well-formed but can't be honored together; the message names the pair. |
| 429 | rate_limited | Too many requests; back off per Retry-After. |
| 5xx | internal | Our side. Safe to retry with backoff. |
04.Example bodies
{
"error": {
"type": "conflict",
"message": "dub_31xk9m is \"rendering\"; /render is only valid at \"in_review\".",
"doc_url": "https://thefamiliarlab.com/docs/dubbing/transcript"
}
}HTTP/1.1 429 Too Many Requests
Retry-After: 12
{
"error": {
"type": "rate_limited",
"message": "Request rate above your organization's limit; retry after 12 seconds.",
"doc_url": "https://thefamiliarlab.com/docs/errors"
}
}05.Rate limits
The default limit is 100 requests per minute per organization. Every response reports where you stand:
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1786731720
Past it, requests return 429 with Retry-After in seconds (the example above); honor it and the limiter recovers immediately. Jobs already accepted are never dropped by the limiter.
Need more? Ask and they're raised on your organization -- Studio contracts have a named point of contact; every other account writes support.
06.Default limits
| LIMIT | DEFAULT |
|---|---|
| API request rate | 100 requests per minute |
| Concurrent dub renders | 10 |
| Concurrent live sessions | 2 (once live is enabled) |
| Upload size | 10 GB per file |
| Source duration | 24 hours per video |
| Target languages | 29 per dub -- the full set minus the source |
Page size (limit) | 20 default · 100 max |
Idempotency-Key window | 24 hours |
| Webhook delivery | 10-second acknowledgement · retried up to 24 hours |
Every default is raised the same way: ask your point of contact, and the new limit is set on your organization.
07.Idempotent retries
Network timeouts happen mid-POST. Send an Idempotency-Key header (any unique string, e.g. a UUID) on any POST and retries with the same key return the original result instead of creating a second resource. Keys are remembered for 24 hours; reusing one with a different body returns 409.
curl -X POST https://api.thefamiliarlab.com/v1/dubs \ -H "Authorization: Bearer $FAMILIAR_API_KEY" \ -H "Idempotency-Key: 4c1b2f0e-9d3a-4d8e-b1c7-2f6a0e8d5b91" \ -F "source_url=https://cdn.yourapp.com/upload.mp4" \ -F "target_langs=es"
Webhooks can also arrive twice -- dedupe on the event id; see Webhooks.
08.Access
The API is enterprise-only: private access under a Studio contract, with volume pricing, raised limits, and a named point of contact for the integration. Book a call and your key is issued with the contract.