Public API errors
Every error response is an RFC 9457 Problem Details document (application/problem+json):
codeis the stable machine string to branch on.typelinks to this page (https://docs.synthesia.io/reference/errors#<code>) — it's documentation, not an identifier, and its URL may change.detailis human-readable and may change without notice; each code below shows example
messages ({braces}mark request-specific values).requestId(also theRequest-Idheader) identifies the request in Synthesia's logs —
include it when contacting support.- New codes may appear over time; a rare unmapped 4xx surfaces as
http_<status>, and an
unexpected 5xx keeps its status with codeinternal. Handle any response you don't
recognize by its HTTP status.
| Status | code | title |
|---|---|---|
| 400 | bad_request | Bad request |
| 400 | validation_error | Invalid request |
| 401 | unauthenticated | Unauthenticated |
| 402 | feature_not_in_plan | Feature not in plan |
| 402 | payment_required | Payment required |
| 402 | quota_exceeded | Quota exceeded |
| 403 | forbidden | Forbidden |
| 403 | insufficient_scope | Insufficient scope |
| 404 | not_found | Not found |
| 404 | unknown_reference | Unknown reference |
| 405 | method_not_allowed | Method not allowed |
| 409 | conflict | Conflict |
| 413 | payload_too_large | Payload too large |
| 415 | unsupported_media_type | Unsupported media type |
| 429 | concurrency_limit | Concurrency limit exceeded |
| 429 | rate_limited | Rate limit exceeded |
| 500 | internal | Internal error |
| 503 | service_unavailable | Service unavailable |
| 504 | timeout | Upstream timeout |
bad_request
bad_requestBad request — status 400 — type
The request could not be processed as sent — a malformed header, parameter, or body. Fix the request before retrying; an unchanged retry fails the same way.
validation_error
validation_errorInvalid request — status 400 — type
One or more request fields were rejected. Fix the fields detail lists and resend; an unchanged retry fails the same way.
For a rejected request body, detail lists each rejected field as path: message, joined with ; ; other validation denials use the standalone messages below.
Example detail messages:
- Not a valid {concept} id.
- One or more fields were rejected.
- The supplied livekitToken cannot be used to join the room.
unauthenticated
unauthenticatedUnauthenticated — status 401 — type
The request carried no valid API key. Send your key as Authorization: Bearer <key> and check it has not expired, been revoked, or rotated.
Example detail messages:
- Invalid API key.
- Provide your API key in the Authorization header.
feature_not_in_plan
feature_not_in_planFeature not in plan — status 402 — type
Your workspace's plan does not include a feature this endpoint requires; features names it. Not retryable — upgrade the plan or contact your account manager.
Example detail messages:
- Your plan does not include the '{feature}' feature.
payment_required
payment_requiredPayment required — status 402 — type
The request was declined for billing reasons, such as exhausted credits. Resolve the billing condition, then retry.
quota_exceeded
quota_exceededQuota exceeded — status 402 — type
A usage quota in your plan is used up. Not retryable until your quota is increased or replenished — upgrade your plan or contact your account manager.
Example detail messages:
- Your session quota is exhausted.
forbidden
forbiddenForbidden — status 403 — type
Your API key is valid but not permitted to do this — the resource may belong to another workspace, or your account may lack the required permission. If you believe you should have access, check with your workspace admin.
insufficient_scope
insufficient_scopeInsufficient scope — status 403 — type
Your API key does not carry the scope this endpoint requires; detail names it. Use or create a key with that scope — retrying with the same key fails the same way.
Example detail messages:
- Your API key does not have the '{scope}' scope this endpoint requires.
not_found
not_foundNot found — status 404 — type
Nothing exists at this URL. Check the path and any resource id in it.
unknown_reference
unknown_referenceUnknown reference — status 404 — type
The request referenced a resource that does not exist or is not accessible to your workspace. Fix the referenced id and resend.
Example detail messages:
- One or more of avatarIds does not exist or is not accessible.
- The referenced avatar, outfit or person does not exist or is not accessible.
method_not_allowed
method_not_allowedMethod not allowed — status 405 — type
The URL exists, but not for this HTTP method. The Allow header lists the methods it supports.
conflict
conflictConflict — status 409 — type
The request conflicts with the resource's current state. Fetch the resource, reconcile, and resend.
payload_too_large
payload_too_largePayload too large — status 413 — type
The request body exceeds the size this endpoint accepts. Reduce the payload and resend.
unsupported_media_type
unsupported_media_typeUnsupported media type — status 415 — type
The request's Content-Type is not one this endpoint accepts. Send the body as application/json unless the endpoint documents otherwise.
concurrency_limit
concurrency_limitConcurrency limit exceeded — status 429 — type
Your plan's ceiling on concurrently running sessions is reached. Retryable — end an active session or wait for one to finish, honoring Retry-After when present.
Carries Retry-After when Enact sends a wait interval. When known, detail leads with the caller's plan numbers and keeps the guidance to end or wait for a session.
Example detail messages:
- Too many sessions are running concurrently for your plan. End an active session or wait for one to end.
rate_limited
rate_limitedRate limit exceeded — status 429 — type
Too many requests in the current window. Retryable — back off for the Retry-After interval, then resend the same request.
The facade's own denials carry RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset-At and Retry-After headers; a domain's 429 carries at most Retry-After.
Example detail messages:
- Too many requests. Retry after the interval in the Retry-After header.
internal
internalInternal error — status 500 — type
Something unexpected failed on Synthesia's side. Usually safe to retry; for a request that creates a resource, check whether the operation went through first. If it persists, contact support and quote the requestId.
Example detail messages:
- An unexpected error occurred.
service_unavailable
service_unavailableService unavailable — status 503 — type
A service this request needs is temporarily unavailable. Transient — retry with backoff, honoring Retry-After when present and any instruction in detail. If it persists, contact support and quote the requestId.
Example detail messages:
- Authentication is temporarily unavailable. Retry shortly.
- Plan features for this request could not be verified. Retry shortly.
- Temporarily unable to create an interactive avatar. Retry the same request with regenerate off.
- Temporarily unable to read credits. Retry shortly.
- Temporarily unable to start a session. If you retry, reuse the same livekitUrl and livekitToken.
- The session could not be started. Retry shortly.
timeout
timeoutUpstream timeout — status 504 — type
The request did not finish within its deadline. The underlying operation may still have gone through — follow the guidance in detail on how to retry or poll safely, otherwise retry with backoff.
Example detail messages:
- Authentication is temporarily unavailable. Retry shortly.
- Plan features for this request could not be verified. Retry shortly.
- The request did not complete within its {deadline}s deadline.
- The session did not start before the deadline. It may still start. If you retry, reuse the same livekitUrl and livekitToken.
- Timed out reading credits. Retry shortly.
- Timed out waiting for the avatar status. Generation may still be running; repeat the same request with regenerate off to poll.
- Timed out waiting for the session to start. It may still start. If you retry, reuse the same livekitUrl and livekitToken.