# ElevenLabs

Connect an ElevenLabs Agents Platform agent to Vonyx numbers over WebSocket or a SIP trunk.

There are two ways to connect an ElevenLabs agent to Vonyx. The [Call API](/docs/call-api) streams outbound call audio straight to the agent's WebSocket, with no SIP setup. A SIP trunk import gives you both outbound and inbound calls.

## Before you start

- A Vonyx [SIP trunk](/docs/console/sip-trunks) with a [number](/docs/console/numbers) attached
- An ElevenLabs account with an agent on the Agents Platform, and its agent ID
- An ElevenLabs API key, if your agent is private or you place calls through the ElevenLabs API

<Tabs items={['WebSocket (Call API)', 'SIP trunk']}>
<Tab value="WebSocket (Call API)">

## Outbound calls

Vonyx dials the number. When the call is answered, it opens the agent's WebSocket and speaks the ElevenLabs conversation protocol (`ws_protocol: "elevenlabs"`).

<Steps>
<Step>

### Set the agent's audio format

The agent's input and output audio formats must match the `sample_rate` you send to Vonyx. Set both to the same value:

| Agent setting | Value | `sample_rate` |
| --- | --- | --- |
| User input audio format (`conversation_config.asr.user_input_audio_format`) | `pcm_16000` (the ElevenLabs default) | `16000` |
| Agent output audio format (`conversation_config.tts.agent_output_audio_format`) | `pcm_16000` | `16000` |

For 8 kHz audio, set both to `pcm_8000` and send `sample_rate: 8000`. Use `pcm_16000` unless you have a reason not to.

</Step>
<Step>

### Get the agent's WebSocket URL

For a public agent, use:

```text
wss://api.elevenlabs.io/v1/convai/conversation?agent_id=YOUR_AGENT_ID
```

For a private agent (authentication turned on in the agent's **Security** settings), get a signed URL from your server before each call:

```bash title="Get a signed URL"
curl "https://api.elevenlabs.io/v1/convai/conversation/get-signed-url?agent_id=YOUR_AGENT_ID" \
  -H "xi-api-key: YOUR_ELEVENLABS_API_KEY"
```

The response's `signed_url` field is the WebSocket URL to use. It is valid for 15 minutes, so request it just before you place the call. Keep the API key on your server.

</Step>
<Step>

### Place the call

```bash title="Place a call"
curl -X POST https://api.vocalstack.site/v1/calls \
  -H "Content-Type: application/json" \
  -d '{
    "did": "91XXXXXXXXXX",
    "phone_number": "91XXXXXXXXXX",
    "websocket_url": "wss://api.elevenlabs.io/v1/convai/conversation?agent_id=YOUR_AGENT_ID",
    "ws_protocol": "elevenlabs",
    "sample_rate": 16000
  }'
```

| Field | Value |
| --- | --- |
| `did` | Your Vonyx number, used as the caller ID |
| `phone_number` | The number to call |
| `websocket_url` | The public URL or the signed URL from the last step |
| `ws_protocol` | `elevenlabs` |
| `sample_rate` | `16000` for `pcm_16000`, `8000` for `pcm_8000` |
| `webhook_url` | Optional. Where Vonyx sends call status updates |

See the [Call API reference](/docs/call-api) for every field.

</Step>
<Step>

### Let the agent end the call

Give the agent the `end_call` system tool. Agents created in the ElevenLabs dashboard have it by default; agents created through the API need it added under `built_in_tools`. The agent calls it when the conversation is done.

</Step>
</Steps>

## Inbound calls

<Callout title="Use the SIP trunk for inbound">
The Call API places outbound calls only. To have the agent answer calls to your Vonyx number, use the **SIP trunk** tab.
</Callout>

</Tab>
<Tab value="SIP trunk">

ElevenLabs imports your Vonyx number as a SIP trunk number. ElevenLabs sends outbound calls to Vonyx, and Vonyx forwards inbound calls to ElevenLabs.

## Outbound calls

<Steps>
<Step>

### Import the number

In the ElevenLabs dashboard, open **Phone numbers**, choose **Import number**, then **From SIP Trunk**.

| Field | Value |
| --- | --- |
| Label | Any name, e.g. `Vonyx 91XXXXXXXXXX` |
| Phone Number | Your Vonyx number as `91XXXXXXXXXX`, without `+` |

Vonyx forwards inbound calls with the number as `91XXXXXXXXXX`, and ElevenLabs matches it exactly, so leave out the `+`.

</Step>
<Step>

### Fill in the outbound settings

| Field | Value |
| --- | --- |
| Address | `43.204.9.41` (IP only, no `sip:` prefix) |
| Transport Type | TCP |
| Media Encryption | Disabled |
| Enabled Codecs | PCMU and PCMA (turn off G.722) |
| SIP Trunk Username | `your_trunk_username` |
| SIP Trunk Password | `your_trunk_password` |

Vonyx supports UDP and TCP, but ElevenLabs marks UDP as experimental, so use TCP. Vonyx has no TLS or SRTP, so media encryption must be **Disabled**.

</Step>
<Step>

### Assign the agent

Open the imported number and choose the agent that handles its calls.

</Step>
<Step>

### Place calls

Use any of these:

- **Batch calls:** in the dashboard's batch calling page, click **Create a batch call**, pick the Vonyx number and the agent, and upload a CSV or XLS file with a `phone_number` column. Other columns become dynamic variables.
- **API:** call the SIP trunk outbound call endpoint.

```bash title="Outbound call through the SIP trunk"
curl -X POST https://api.elevenlabs.io/v1/convai/sip-trunk/outbound-call \
  -H "xi-api-key: YOUR_ELEVENLABS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "YOUR_AGENT_ID",
    "agent_phone_number_id": "YOUR_PHONE_NUMBER_ID",
    "to_number": "91XXXXXXXXXX"
  }'
```

`agent_phone_number_id` is the ElevenLabs ID of the imported number. The response returns `success`, `message`, `conversation_id` and `sip_call_id`.

</Step>
</Steps>

## Inbound calls

<Steps>
<Step>

### Fill in the inbound settings

On the imported number in ElevenLabs:

| Field | Value |
| --- | --- |
| Media Encryption | Disabled |
| Allowed Numbers | Leave empty to accept every caller |
| Allowed Source IP Addresses | Leave empty. Vonyx forwards over UDP, and ElevenLabs applies this list to TCP only. |
| Remote Domains | Leave empty (no TLS) |
| Authentication | Leave empty |

</Step>
<Step>

### Point Vonyx at ElevenLabs

In the Vonyx console, open the trunk, turn on **Inbound calls**, and set **Inbound address** to:

```text
sip.rtc.elevenlabs.io:5060
```

Vonyx forwards calls to the attached number there over UDP, from `43.204.9.41`. ElevenLabs lists UDP as experimental, so test inbound calls before going live. See [inbound calls](/docs/console/inbound-calls).

</Step>
</Steps>

</Tab>
</Tabs>

## Test the connection

- **WebSocket:** place a call to your own phone with the Call API. The agent should speak its first message once you answer.
- **SIP outbound:** run a **Test call** from the batch call form, or call the outbound endpoint with your own number as `to_number`.
- **SIP inbound:** call your Vonyx number from another phone. The assigned agent should answer.

## Limitations

- DTMF and call transfer are not available on Vonyx yet, so ElevenLabs' transfer and keypad tools won't work on these calls.
- New accounts make 1 call at a time ([raise limits](/docs/sip/limits)).
- The caller ID must be one of your Vonyx numbers.
- Vonyx has no TLS or SRTP, so ElevenLabs' TLS transport and encrypted media can't be used.
- The Call API is outbound only. Inbound calls need the SIP trunk.
- ElevenLabs limits concurrent calls by subscription tier.

## Troubleshooting

| Problem | Fix |
| --- | --- |
| Agent sounds sped up, slowed down or garbled | The agent's input and output formats don't match `sample_rate`. Set both to `pcm_16000` with `16000`, or `pcm_8000` with `8000`. |
| WebSocket call connects, then drops at once | The private agent needs a signed URL, or the signed URL is older than 15 minutes. Request a new one per call. |
| Outbound SIP calls fail to connect | Check the address is `43.204.9.41` with no `sip:` prefix, the trunk username and password, and that the number is attached to the trunk. |
| One-way or no audio on SIP | Make sure PCMU or PCMA is enabled and media encryption is **Disabled**. |
| Inbound calls don't reach the agent | Check the inbound address is `sip.rtc.elevenlabs.io:5060`, the number's `+` matches what Vonyx sends, and an agent is assigned. If you set allowed source IPs, include `43.204.9.41`. |
| Calls rejected when a second one starts | You hit the 1-channel default. [Raise limits](/docs/sip/limits). |

See [SIP troubleshooting](/docs/sip/troubleshooting) for more.
