For Developers
Using the API

Errors

The one error format every /v1 route uses, every stable code, and how to handle each in your integration.

Every failed /v1 request returns a non-2xx status and the same JSON envelope. Branch on code, and show or log error.

The error envelope

JSON
{
  "success": false,
  "error": "The request is invalid.",
  "code": "VALIDATION_ERROR",
  "requestId": "6f1a2b3c-4d5e-4f60-8a7b-9c0d1e2f3a4b",
  "timestamp": "2026-10-31T09:30:00.000Z",
  "details": {
    "issues": [
      { "path": "phoneNumber", "message": "This field is required." }
    ]
  }
}

Fields

successbooleanrequired
Always false on an error.
errorstringrequired
A readable message. Always a string. The wording can change, so don't parse it.
codestringrequired
A stable code to branch on. See Error codes.
requestIdstringrequired
The ID to quote when you contact support.
timestampstringrequired
When the error happened, in ISO 8601.
detailsobject
Extra information. Left out when there is none. It can hold only the keys below.

details

issuesobject[]
Validation problems, up to 20. Each has a path and a message.
actionstring
What to do next, on refusals to place a call.
balancenumber
Your wallet balance, on INSUFFICIENT_BALANCE.
requiredBalancenumber
The balance needed, on INSUFFICIENT_BALANCE.
shortfallnumber
The difference between those two, on INSUFFICIENT_BALANCE.

path names the field with dots, such as customFields or conditions.conditions.0.field. It is an empty string when the problem is with the whole body or query.

Every /v1 response has Cache-Control: no-store, because it holds one account's data.

Status codes

StatusMeaningWhat to do
200Success.
201Created, or a call was accepted.
400The request is invalid.Fix the request. Don't retry it unchanged.
401The API key is missing or isn't valid.Check the SYNTH_API_KEY header.
402The wallet can't pay for this.Add funds.
403The key or its owner isn't allowed to do this.Check the key's permissions and the owner's role.
404The resource or route doesn't exist, or belongs to another account.Check the ID and path.
409The request conflicts with the resource's current state.See the code.
413The body is too large.Send less data. See Body limits.
415The Content-Type isn't supported.Send application/json.
422The request is valid, but the resources aren't ready for it.Follow details.action.
429You hit a limit.Wait for Retry-After, then retry.
500Something failed on our side.Retry with backoff. Contact support if it continues.
502A service we depend on failed.Retry with backoff.
503We're temporarily unavailable.Wait for Retry-After if it's present, then retry.
504An operation timed out.Retry with backoff.

A 404 covers another account's resources too, so you can't tell whether an ID exists elsewhere. A path ID that isn't a valid UUID returns 400.

Error codes

Authentication and access

CodeStatusMeaning
UNAUTHORIZED401The key is missing, malformed, wrong, revoked or expired. The response doesn't say which.
FORBIDDEN403The key lacks the required permission, or its owner's role or account doesn't allow this.
AUTH_ERROR500Authentication couldn't be completed. Retry.

Requests and resources

CodeStatusMeaning
VALIDATION_ERROR400A parameter or body failed a check. details.issues lists the fields when the check is on a field.
NOT_FOUND404The resource or route wasn't found.
CONFLICT409A duplicate, such as a contact's phone number or an audience's name, or settings that changed since you read them.
PAYLOAD_TOO_LARGE413The body is over the limit.
UNSUPPORTED_MEDIA_TYPE415The Content-Type isn't supported.
RECORDING_NOT_READY409The recording has no audio to download yet.
BUSINESS_RULE_ERROR422The request can't be completed in the resource's current state.
RATE_LIMIT_EXCEEDED429The key used its allowance, or this IP address sent too many bad keys. See Rate limits.
EXECUTION_CAPACITY_EXCEEDED429Too many of your calls are already queued or in progress. Comes with Retry-After: 60.

Idempotency

These apply to POST /v1/calls. See Idempotency.

CodeStatusMeaning
MISSING_IDEMPOTENCY_KEY400The Idempotency-Key header is missing.
INVALID_IDEMPOTENCY_KEY400The key isn't 1 to 255 letters, numbers, dashes or underscores.
IDEMPOTENCY_KEY_REUSED409This key was already used with a different body. Nothing was placed.
REQUEST_IN_PROGRESS409The first request with this key is still running. Wait, then retry with the same key.
DUPLICATE_REQUEST409This key was used before and its stored response isn't available.
IDEMPOTENCY_UNAVAILABLE503Requests can't be deduplicated right now, so nothing was placed. Retry with the same key shortly.

Placing calls

POST /v1/calls returns these when it refuses a call before queueing it.

CodeStatusMeaning
ACCOUNT_LOCKED403The account is locked and can't place calls.
AGENT_INACTIVE422The agent isn't active.
AGENT_NOT_READY422The agent isn't set up to place calls.
PHONE_NUMBER_AGENT_MISMATCH422The phone number is assigned to a different agent.
PHONE_NUMBER_UNASSIGNED422The phone number isn't assigned to an agent.
PHONE_NUMBER_INACTIVE422The phone number isn't active.
PHONE_NUMBER_OUTBOUND_UNSUPPORTED422The phone number can't place outbound calls.
PHONE_NUMBER_COMPLIANCE_PENDING422The phone number is awaiting regulatory approval.
PHONE_NUMBER_COMPLIANCE_BLOCKED422The phone number failed regulatory approval.
PHONE_NUMBER_NOT_SYNCED422The phone number is still being set up, or needs setting up again.
PHONE_NUMBER_NOT_READY422The phone number's setup isn't finished.
DESTINATION_NOT_ALLOWED422This phone number isn't allowed to call that destination.
DESTINATION_NOT_READY422The number being called is one of your own, and it isn't ready to receive a call.
CALL_NOT_READY422The call can't be placed right now, for another reason.

Every 422 in this table except AGENT_INACTIVE includes details.action.

Payments

CodeStatusMeaning
INSUFFICIENT_BALANCE402The wallet is too low for this request. details has balance, requiredBalance and shortfall.
PAYMENT_DECLINED402The payment was declined.

POST /v1/calls checks your balance after it accepts a call, so a low balance there appears as a failure_code. See Failure codes.

Server failures

CodeStatusMeaning
INTERNAL_ERROR500An unexpected failure.
UPSTREAM_UNAVAILABLE502A service this request depends on is unavailable.
SERVICE_UNAVAILABLE503The service is temporarily unavailable.
TIMEOUT504The request timed out.

When we can't check your key, you get 503 SERVICE_UNAVAILABLE with Retry-After: 5. Nothing is wrong with the key, so retry it and don't replace it. Other 503 responses may not have the header, so use your own backoff for those.

Body limits

A request body can be up to 256 KB. PUT /v1/agents/:id/custom-tools allows 2 MB. A larger body returns 413 PAYLOAD_TOO_LARGE before the key is checked.

Bodies must be JSON with Content-Type: application/json.

ProblemResult
The Content-Type header is missing on a request with a body400 VALIDATION_ERROR
The Content-Type isn't a supported type415 UNSUPPORTED_MEDIA_TYPE
The JSON is malformed400 VALIDATION_ERROR
The JSON is nested more than 64 levels deep400 VALIDATION_ERROR
A value or query parameter has a NUL character or invalid Unicode400 VALIDATION_ERROR

Some fields have tighter limits of their own, listed on each resource's page.

Handle errors in code

curl -s -w "\nstatus: %{http_code}\n" https://backend.synthesys.app/api/v1/agents \
  -H "SYNTH_API_KEY: YOUR_API_KEY"

For common failures and fixes, see Troubleshooting.