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://developers.synthesia.io/docs/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 | api_key_expired | API key expired |
| 401 | unauthenticated | Unauthenticated |
| 402 | feature_not_in_plan | Feature not in plan |
| 402 | no_credit | No credit |
| 402 | payment_required | Payment required |
| 402 | quota_exceeded | Quota exceeded |
| 402 | user_credit_limit_reached | User credit limit reached |
| 403 | connection_required | Connection required |
| 403 | forbidden | Forbidden |
| 403 | insufficient_scope | Insufficient scope |
| 403 | organization_disabled | Organization disabled |
| 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 | admission_unavailable | Admission temporarily unavailable |
| 503 | service_unavailable | Service unavailable |
| 504 | timeout | Upstream timeout |
bad_request
bad_requestBad request — status 400 — type
The request could not be parsed as sent — usually a body that is not JSON. Fix the request before retrying; an unchanged retry fails the same way.
Example detail messages:
- The request body is missing or null. Send a JSON object.
- The request body is not valid JSON. Send a JSON object.
- The request body was not sent as JSON. Set the Content-Type header to application/json.
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:
- Could not establish a media connection to the LiveKit server at livekitUrl. Its WebRTC ports (UDP/TCP) or a TURN server must be reachable from the internet; HTTP-only tunnels such as Cloudflare quick tunnels or ngrok carry signalling but not media.
- Not a valid {concept} id.
- One or more fields were rejected.
- The supplied livekitToken cannot be used to join the room.
- query.cursor: Not a cursor this list issued. Omit it to start from the first page.
api_key_expired
api_key_expiredAPI key expired — status 401 — type
The API key is genuine but past its expiry date. Not retryable with this key — create a new key and use it instead. The WWW-Authenticate: Bearer header carries error="invalid_token".
Example detail messages:
- Your API key has expired. Create a new key and retry with it.
unauthenticated
unauthenticatedUnauthenticated — status 401 — type
The request carried no usable API key. Send your key as Authorization: Bearer <key>. An unknown or revoked key is reported only as invalid; an expired key answers api_key_expired instead. The WWW-Authenticate: Bearer header carries realm alone when no key was sent, error="invalid_request" for an Authorization scheme other than Bearer, and error="invalid_token" for a rejected key.
Example detail messages:
- Invalid API key.
- Provide your API key in the Authorization header.
- Provide your application's OAuth access token in the Authorization header.
- Unsupported Authorization scheme. Send your API key as 'Authorization: Bearer
'. - Unsupported Authorization scheme. Send your application's OAuth access token as 'Authorization: Bearer
'.
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 interactive avatars — upgrade to use this API.
- Your plan does not include the '{feature}' feature.
no_credit
no_creditNo credit — status 402 — type
Your workspace has no credit remaining for the metered feature this request consumes. Not retryable until the balance is positive again — top up or upgrade your plan.
Example detail messages:
- Your plan has no interactive avatar credits. Top up or upgrade to create interactive avatars.
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.
user_credit_limit_reached
user_credit_limit_reachedUser credit limit reached — status 402 — type
You have run out of your monthly credit limit for the metered feature this request consumes, while your workspace still has credit. Not retryable until the limit resets — ask a workspace admin to raise it.
Example detail messages:
- You have run out of your monthly credit limit. Ask a workspace admin to raise it, or wait for it to reset.
connection_required
connection_requiredConnection required — status 403 — type
The access token is valid, but the Synthesia account behind it has no active connection for your application: it was never completed, was disconnected, or expired after 30 days without use. Call POST /connections with the same token, then retry. If the token has expired and refreshing it fails, re-authorize the user first.
Example detail messages:
- This Synthesia account has no active connection for your application. Call POST /connections, then retry.
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.
Example detail messages:
- This endpoint accepts an OAuth access token issued to your application, not an API key.
insufficient_scope
insufficient_scopeInsufficient scope — status 403 — type
Your API key or access token does not carry the scope this endpoint requires; detail names it, as does scope in the WWW-Authenticate: Bearer error="insufficient_scope" header. Use or create a key with that scope, or re-authorize to request it — retrying with the same credential fails the same way. A stronger scope on the same resource also works (:write satisfies :read); Scopes lists every scope and the endpoints that need it.
Example detail messages:
- Your API key does not have the '{scope}' scope this endpoint requires.
- Your access token does not have the '{scope}' scope this endpoint requires.
organization_disabled
organization_disabledOrganization disabled — status 403 — type
The access token is valid, but the user's Synthesia organization has not enabled the integration for your application. Keep the access and refresh tokens and do not re-authorize: consent was given and only the organization's setting blocks the call. Ask the user to contact their Synthesia admin, then retry the same request once it is enabled.
Example detail messages:
- This user's Synthesia organization has not enabled the integration for your application. Ask a Synthesia admin in the organization to enable it, then retry the same request; no new authorization is needed.
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.
Example detail messages:
- The LiveKit room was closed or deleted, or the avatar's participant was removed or replaced by another participant with the same identity, while the session was starting. Retrying against a room that is no longer open fails the same way: start the session in an open room, with a livekitToken for that room, and keep it open until the session starts. If another participant joined with the livekitToken's identity, give the avatar an identity of its own.
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.
admission_unavailable
admission_unavailableAdmission temporarily unavailable — status 503 — type
A billing or rate decision this request needs could not be obtained, so it was denied rather than admitted unchecked. Transient — retry with backoff, honoring Retry-After when present.
Example detail messages:
- Admission is temporarily unavailable. Retry shortly.
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 read the plan. 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 reading the plan. 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.