For Developers
Calls

Place your first call

Choose an agent and phone number, send a lead's details, place an outbound call, and track it by its ID.

You need three things before you start:

  • An API key with write permission. See Authentication.
  • An active agent with a phone number assigned to it. You set both up in the dashboard, because these API routes are read-only.
  • Funds in your wallet. Calls are paid, so check your balance first.

The JavaScript samples use top-level await. Save them as .mjs files and run them with Node 18 or later.

  1. Choose an agent

    List your agents and copy the id of one whose status is active. The full object is in the agents reference.

    curl "https://backend.synthesys.app/api/v1/agents?limit=10" \
      -H "SYNTH_API_KEY: YOUR_API_KEY"
  2. Choose a phone number

    The number must be assigned to the agent you chose. Look for a number where assignedAgentId matches the agent and isCallableForCampaigns is true. If that field is false, campaignExecutionMessage says why. The full object is in the phone numbers reference.

    curl "https://backend.synthesys.app/api/v1/phone-numbers" \
      -H "SYNTH_API_KEY: YOUR_API_KEY"
  3. Place the call

    Send the agent, the number to call from, and the lead's number and details to POST /v1/calls. The Idempotency-Key header is required. Use one key for each call you intend to make, such as your own ID for the lead.

    Replace +12025550123 with a real number you have permission to call.

    curl -X POST "https://backend.synthesys.app/api/v1/calls" \
      -H "SYNTH_API_KEY: YOUR_API_KEY" \
      -H "Idempotency-Key: lead-1042-growth-plan" \
      -H "Content-Type: application/json" \
      -d '{
        "agentId": "3f0c1a52-7b7e-4c7a-9a55-1f2d3e4c5b6a",
        "phoneNumberId": "8d2e6b14-90c3-4f1e-b7a6-2c4d5e6f7a8b",
        "phoneNumber": "+12025550123",
        "firstName": "Jane",
        "lastName": "Doe",
        "email": "jane@example.com",
        "company": "Example Co",
        "customFields": {
          "planTier": "growth",
          "timezone": "America/New_York"
        },
        "firstMessage": "Hi {{first_name}}, I am calling about your {{plan_tier}} plan."
      }'

    A 201 means the call was accepted. It doesn't mean the call has been dialed. Keep the callId.

    JSON
    {
      "success": true,
      "data": {
        "callId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
        "jobId": "c7a1e0f4-52d8-4b36-8e19-6f0a3b7d2c11",
        "status": "queued"
      }
    }
  4. Track the call

    Pass the callId to GET /v1/calls/{id}. It works straight away, even while the call is waiting.

    curl "https://backend.synthesys.app/api/v1/calls/9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d" \
      -H "SYNTH_API_KEY: YOUR_API_KEY"

    The status moves from queued to dialing, then in_progress, and ends as completed or failed. A failed call has a failure_code that says why. See Get transcripts and recordings for the next steps.

Retry safely

Network failures happen. If you don't get a response, send the same request again with the same Idempotency-Key.

CaseWhat happens
Same key and same bodyYou get the original answer, with Idempotency-Replay: true. No second call is placed.
Same key and a different body409 IDEMPOTENCY_KEY_REUSED. Nothing is placed.
The first request is still running409 REQUEST_IN_PROGRESS. Wait, then retry with the same key.
The call failed and you want to try againSend a new key.

If a request was refused with a 403, 404, 422 or 429, nothing was placed. Fix the cause and retry with the same key. See Idempotency for the full rules.

Pass lead details

Request body

agentIdstringrequired
UUID of the agent that makes the call.
phoneNumberIdstringrequired
UUID of the number to call from. It must be assigned to the agent.
phoneNumberstringrequired
The number to dial. Use E.164 format, such as +12025550123. It must be a valid number.
firstNamestring
The lead's first name, up to 200 characters.
lastNamestring
The lead's last name, up to 200 characters.
emailstring
The lead's email address.
companystring
The lead's company, up to 200 characters.
customFieldsobject
Any other values the agent should have. Up to 50 keys and 16 KB, nested up to 32 levels deep.
firstMessagestring
Replaces the agent's opening line for this call, up to 1,000 characters.
callContextstring
outbound or callback. Selects which of the agent's configured opening lines to use.
voiceCloneIdstring
UUID of one of your voice clones, to use instead of the agent's voice on this call.
leadNotesstring
Notes stored with the call, up to 5,000 characters. They aren't sent to the agent.

The name, email, company and custom fields become variables for the call. Keys are converted to snake case, so planTier becomes plan_tier. A full_name variable is built from the first and last names.

Use the variables in firstMessage as {{plan_tier}} or [plan_tier].

When the call is dialed

Calls only go out from 09:00 to 20:00 at the destination. A call requested outside those hours still returns 201, stays queued and holds no funds. It goes out when the hours open.

If a call hasn't started 35 hours after you requested it, it fails with outside_calling_hours.

The destination's hours come from the number's area code in the US and Canada, or its country elsewhere. A time zone you send can only narrow them. Use a timezone, time_zone, timeZone, tz, customer_timezone or customerTimezone key in customFields. A zone from another country is ignored, and so are UTC and Etc/UTC. See Calling hours for the details.

These hours are a platform rule. They aren't legal advice, and other rules can apply to your calls.

Your account also has a limit on calls that can be live at once. A call that can't get a line waits for up to 5 minutes, then fails with line_capacity_reached.

When a call fails

These errors come back from the request itself, and no call is placed. See Errors for the response format.

StatusCodeCause
400VALIDATION_ERRORA field failed validation, or phoneNumber isn't a dialable number.
400MISSING_IDEMPOTENCY_KEYThe Idempotency-Key header is missing.
403FORBIDDENThe API key doesn't have write permission.
403ACCOUNT_LOCKEDThe account is locked.
404NOT_FOUNDThe agent or phone number doesn't exist in your account.
422AGENT_INACTIVEThe agent isn't active.
422VariousThe number can't place this call. For example, it's inactive, awaiting regulatory approval or assigned to a different agent. Read details.action.
429EXECUTION_CAPACITY_EXCEEDEDYou have 100 calls queued or in progress. Retry after 60 seconds.

Other checks run after the 201, including whether your wallet can fund the call. If one fails, the call's status becomes failed with a failure_code. See Failure codes.