# LiveKit

Use [LiveKit](https://livekit.io/) voice AI agents with **DIDWW SIP Trunking** to handle inbound and outbound calling
over standard phone lines.
Connect your DIDWW SIP trunks with LiveKit Cloud to route incoming calls to your agent, place outbound calls through
DIDWW trunks, and transfer active calls to a live person.

- Route incoming calls from DIDWW numbers to a LiveKit voice AI agent.
- Connect each caller to an agent in a separate room.
- Authenticate incoming calls with SIP credentials.

- Place outbound calls through DIDWW Outbound Trunks.
- Transfer active calls to external phone numbers through DIDWW.
- Encrypt SIP signaling with TLS and call media with SRTP.

---

## 1. Route Incoming Calls to LiveKit

Configure an Inbound SIP Trunk in the DIDWW User Panel to send incoming calls from your DIDWW numbers to LiveKit.
This trunk defines the SIP path that delivers calls to your LiveKit project and can be configured to support SIP REFER
call transfers.

### Before You Begin

- An active DIDWW account is required. [Sign in to DIDWW](https://my.didww.com/users/sign_in) or [Create DIDWW account](https://my.didww.com/users/sign_up#/users/sign_up).
- At least one active **DID number** with capacity to receive incoming calls is required. [Buy Numbers](https://my.didww.com/users/sign_up#/coverage).
- A project on [LiveKit Cloud](https://cloud.livekit.io/) is required.
- Your **LiveKit SIP endpoint** is required. In LiveKit Cloud, open **Project settings**, copy the **SIP URI**, and remove the `sip:` prefix. For example, `sip:vjnxecm0tjk.sip.livekit.cloud` becomes `vjnxecm0tjk.sip.livekit.cloud`. See [LiveKit SIP trunk setup](https://docs.livekit.io/telephony/start/sip-trunk-setup/).

### Step 1: Create New SIP Trunk

1. In the [DIDWW User Panel](https://my.didww.com/#/trunks), go to **Voice > Inbound Trunks**.
2. Click **Create New > SIP Trunk**.

![Creating a new inbound SIP trunk](../../_images/inbound1.webp)


**Fig. 1.** Creating a new inbound SIP trunk

### Step 2: Configure General SIP Trunk Settings

In the **General** tab, configure the endpoint settings used to deliver calls from DIDWW to LiveKit.

1. Enter a descriptive **Name** for the trunk (e.g., `LiveKit`).
2. Select **Static Endpoint**.
3. In **Host**, enter your LiveKit SIP endpoint (e.g., `vjnxecm0tjk.sip.livekit.cloud`).
4. In **Port**, enter `5061` for **TLS**. For unencrypted signaling, enter `5060`.
5. In **Transport**, select **TLS**. For unencrypted signaling, select **TCP** or **UDP**.
6. In **Network Protocol**, select **Prefer IPv4 over IPv6** or **IPv4 only** to match the IPv4 addresses allowed on your DIDWW outbound trunk.

![SIP trunk configured for LiveKit](../../_images/inbound2_v2.webp)


**Fig. 2.** SIP trunk configured for LiveKit

Note

To keep inbound SIP traffic in a specific region, enter a [LiveKit region-based SIP
endpoint](https://docs.livekit.io/telephony/features/region-pinning/) in **Host**.

### Step 3: Configure Media & DTMF

1. Open the **Media & DTMF** tab.
2. In **Codecs**, keep only **PCMA** and **PCMU**, and remove the other codecs.
3. In **SRTP Mode**, select **SRTP SDES**. For unencrypted media, keep **Disabled**.

![Media and DTMF settings for the inbound SIP trunk](../../_images/inbound4.webp)


**Fig. 3.** Media and DTMF settings for the inbound SIP trunk

### Step 4: Enable Call Transfer Signaling

To support call transfers, configure the inbound trunk to allow in-dialog SIP REFER requests.

1. Open the **Signalling** tab.
2. Set **Max Transfers** to `1` or higher.

![Max Transfers set on the Signalling tab of the inbound SIP trunk](../../_images/inbound_signalling.webp)


**Fig. 4.** Enabling call transfer signaling

Note

**Max Transfers** is `0` by default, and DIDWW rejects every transfer until you change it.

### Step 5: Save the Inbound SIP Trunk

When all required fields in the Create Inbound SIP Trunk are filled, click **Create** to save your inbound SIP trunk.

Note

For advanced SIP trunk configuration, see [Advanced Inbound SIP Trunk
documentation](../../voice/inbound-trunks/sip-trunks/sip-trunk-settings-reference.html#user-panel-sipin-trunk-advanced-configuration).

![Create button for the inbound SIP trunk](../../_images/inbound5.webp)


**Fig. 5.** Create the Inbound SIP Trunk

### Step 6: Assign Inbound SIP Trunk to Your DID Numbers

After creating the Inbound SIP Trunk for LiveKit, assign it to the DID number(s) that will deliver incoming calls to
your LiveKit agent.

1. In the DIDWW User Panel, go to **Phone Numbers > My Numbers**.
2. Select the DID number(s) you want to assign to the inbound SIP trunk.
3. At the bottom of the page, click **Batch Actions > Update Trunks**.

![Selecting Update Trunks from the Batch Actions menu](../../_images/inbound6.webp)


**Fig. 6.** Selecting **Update Trunks** from the Batch Actions menu

4. From the dropdown menu, choose the **LiveKit SIP trunk** you created earlier.
5. Click **Confirm** to apply the changes.

![Assigning the LiveKit SIP trunk to DID numbers](../../_images/inbound7.webp)


**Fig. 7.** Assigning the LiveKit SIP trunk to the selected DID(s)



---

## 2. Enable Outbound Calling from LiveKit through DIDWW

Configure an Outbound SIP Trunk in the DIDWW User Panel to allow LiveKit to place outbound calls through DIDWW.
This trunk provides the SIP credentials required for outbound calls and call transfers to external phone numbers.

### Before You Begin

- Access to **DIDWW Outbound Trunks** is required for making outbound calls. See [Get Access to DIDWW Outbound Termination](../../voice/outbound-trunks/get-access.html#user-panel-voice-out-get-access).

### Step 1: Create New Outbound Voice Trunk

1. In the [DIDWW User Panel](https://my.didww.com/#/trunks), go to **Voice > Outbound Trunks**.
2. Click **Create New**.

![Creating a new outbound SIP trunk](../../_images/outbound1.webp)


**Fig. 8.** Creating a new outbound SIP trunk

### Step 2: Configure Authentication

1. Update the **Friendly name** (e.g., `LiveKit`).
2. Keep the default **Credentials & IP-based** authentication method selected. The SIP digest credentials (username and password) will be provided after the trunk is created.
3. In **Allowed SIP IP addresses**, add the LiveKit Cloud static IP ranges:

   - `143.223.88.0/21`
   - `161.115.160.0/19`
   - `153.57.128.0/18`

   Then add the DIDWW inbound SIP addresses used for call transfers:

   - New York: `46.19.209.14`
   - Frankfurt: `46.19.210.14`
   - Los Angeles: `46.19.212.14`
   - Miami: `46.19.213.14`
   - Singapore: `46.19.214.14`
   - Hong Kong: `46.19.215.14`
   - Amsterdam: `185.238.173.14`

   Transferred calls are placed through your outbound trunk using these signaling addresses. See [Static Endpoint
signaling
addresses](../../voice/inbound-trunks/sip-trunks/sip-connectivity-reference.html#inbound-sip-static-signaling-endpoints).

Note

LiveKit publishes its static IP ranges for its Canada, EU, India, Japan, and US regions.
Calls that LiveKit places from other regions come from addresses outside these ranges, and DIDWW rejects them.
To control the region LiveKit places outbound calls from, set `destination_country` on the LiveKit outbound trunk. See
[LiveKit region pinning](https://docs.livekit.io/telephony/features/region-pinning/).
Check the current ranges in [LiveKit regions and static IPs](https://docs.livekit.io/deploy/admin/regions/endpoints/)
before you create the trunk.

![Allowed SIP IP addresses for outbound trunk authentication](../../_images/outbound2_v2.webp)


**Fig. 9.** Entering the LiveKit static IP ranges and DIDWW inbound SIP addresses for outbound authentication

### Step 3: Configure Media Encryption

1. Expand **Media**.
2. In **Media encryption mode**, select **SRTP SDES**. For unencrypted media, keep **Disabled**.

![Media encryption mode set to SRTP SDES](../../_images/outbound3.webp)


**Fig. 10.** Media encryption mode set to SRTP SDES

### Step 4: Save the Outbound SIP Trunk

When all required fields in the Create Outbound SIP Trunk are filled, click **Create** to save your outbound SIP trunk.

Note

For advanced outbound SIP trunk configuration, see [Outbound SIP Trunk
Guide](../../voice/outbound-trunks/how-to-guides/index.html#outbound-trunk-create).

![Create button for the outbound SIP trunk](../../_images/outbound4.webp)


**Fig. 11.** Create the Outbound SIP Trunk

### Step 5: Copy Outbound Trunk Credentials

When the outbound trunk is created, you can view and copy its credentials by selecting the key icon in the credentials
column on the Outbound Trunks page.

1. Go to **Voice > Outbound Trunks**.
2. Locate your outbound trunk and click the **key icon** in the **Credentials** column.
3. The trunk credentials will appear, showing the **Username** and **Password** (click the **eye icon** to reveal the password).
4. Copy and securely store these credentials. You will need them in [Step 6: Add Outbound Credentials to the Inbound Trunk](#livekit-inbound-authorization), and when you create the LiveKit inbound and outbound trunks in [3. Connect DIDWW SIP Trunks in LiveKit](#livekit-connect).

![Accessing outbound trunk credentials](../../_images/outbound5.webp)


**Fig. 12.** Opening the outbound trunk credentials view

### Step 6: Add Outbound Credentials to the Inbound Trunk

To support call transfers, configure the DIDWW inbound trunk to authenticate with the credentials generated for the
outbound trunk.
DIDWW uses these credentials to authenticate to LiveKit and to place transferred calls through your outbound trunk.

1. Go to **Voice > Inbound Trunks** and locate the LiveKit inbound trunk.
2. Click **Actions**, then select **Edit**.
3. Open the **Authorization** tab.
4. Turn on **Enable Authorization**.
5. In **Auth User**, paste the outbound trunk **Username**.
6. In **Auth Password**, paste the outbound trunk **Password**.
7. Click **Submit**.

![Outbound trunk credentials entered on the Authorization tab of the inbound SIP
trunk](../../_images/inbound_auth_outbound.webp)


**Fig. 13.** Adding outbound trunk credentials to the inbound trunk



---

## 3. Connect DIDWW SIP Trunks in LiveKit

Connect the DIDWW SIP trunks in LiveKit Cloud so your agent can receive incoming calls and place outbound calls through
DIDWW.
This setup creates the LiveKit inbound trunk, a dispatch rule that sends each caller to your agent, and the LiveKit
outbound trunk, and shows how to transfer calls to a live person.

### Before You Begin

- A project on [LiveKit Cloud](https://cloud.livekit.io/) is required. Use the same project as in [1. Route Incoming Calls to LiveKit](#livekit-inbound).
- A running or deployed **LiveKit voice AI agent** in the same project is required. See the [LiveKit Voice AI quickstart](https://docs.livekit.io/agents/start/voice-ai/) to create one.
- The **agent name** your agent registers with is required. Set it with `agent_name` (Python) or `agentName` (Node.js) in your agent code. The dispatch rule only sends calls to an agent with this name. The examples use `didww-agent`. See [LiveKit Agent dispatch](https://docs.livekit.io/agents/server/agent-dispatch/).

### Step 1: Create an Inbound Trunk in LiveKit

The LiveKit inbound trunk accepts calls to your DIDWW number.

1. Sign in to [LiveKit Cloud](https://cloud.livekit.io/) and select your project.
2. Go to **Telephony > SIP trunks** and click **Create new trunk**.

   ![SIP trunks page in LiveKit Cloud](../../_images/livekit1.webp)


   **Fig. 14.** Creating a new SIP trunk in LiveKit Cloud
3. In **Trunk direction**, select **Inbound**.
4. Open the **JSON editor** tab and enter the following configuration. Replace `+15105550100` with your DIDWW number in E.164 format. In `authUsername` and `authPassword`, enter the outbound trunk **Username** and **Password** from [Step 5: View Outbound Trunk Credentials](#livekit-outbound-credentials). The DIDWW inbound trunk uses the same credentials.

   ```
   {
     "name": "DIDWW inbound",
     "numbers": ["+15105550100"],
     "authUsername": "<didww-outbound-username>",
     "authPassword": "<didww-outbound-password>",
     "media": {
       "encryption": "SIP_MEDIA_ENCRYPT_REQUIRE",
       "onlyListedCodecs": true,
       "codecs": [
         { "name": "PCMA", "rate": 8000 },
         { "name": "PCMU", "rate": 8000 }
       ]
     }
   }
   ```

   For unencrypted media, remove `encryption` from `media`. This setting must match **SRTP Mode** on the DIDWW inbound
trunk, or the call fails.
5. Click **Create** and copy the inbound trunk ID.

![LiveKit inbound trunk configuration in the JSON editor](../../_images/livekit2_v2.webp)


**Fig. 15.** LiveKit inbound trunk configuration in the JSON editor

Note

The authentication fields are available in the **JSON editor** tab only.

### Step 2: Create a Dispatch Rule and Assign Your Agent

In LiveKit, every call takes place in a room, where the caller and your agent are connected.
A dispatch rule decides which room receives an incoming call and which agent joins it.
An individual dispatch rule creates a separate room for each caller.

1. In LiveKit Cloud, go to **Telephony > Dispatch rules**.
2. Click **Create new dispatch rule**.
3. Open the **JSON editor** tab and enter the following configuration. Replace `<livekit-inbound-trunk-id>` with the ID from [Step 1](#livekit-create-inbound-trunk) and `didww-agent` with your agent name.

   ```
   {
     "name": "DIDWW inbound calls",
     "trunkIds": ["<livekit-inbound-trunk-id>"],
     "rule": {
       "dispatchRuleIndividual": {
         "roomPrefix": "didww-call-"
       }
     },
     "roomConfig": {
       "agents": [
         { "agentName": "didww-agent" }
       ]
     }
   }
   ```
4. Click **Create**.

![Individual dispatch rule in the LiveKit JSON editor](../../_images/livekit3.webp)


**Fig. 16.** Individual dispatch rule for DIDWW inbound calls

This rule matches calls from your DIDWW inbound trunk and dispatches the named agent to each new call room.
For other routing options, see [LiveKit dispatch
rules](https://docs.livekit.io/telephony/accepting-calls/dispatch-rule/).

### Step 3: Create an Outbound Trunk in LiveKit

1. In LiveKit Cloud, go to **Telephony > SIP trunks** and click **Create new trunk**.
2. In **Trunk direction**, select **Outbound**.
3. Open the **JSON editor** tab and enter the following configuration. Replace `+15105550100` with one of your DIDWW numbers to use as caller ID, and enter the credentials from [Step 5: View Outbound Trunk Credentials](#livekit-outbound-credentials).

   ```
   {
     "name": "DIDWW outbound",
     "address": "fra.eu.out.didww.com",
     "transport": "SIP_TRANSPORT_TLS",
     "numbers": ["+15105550100"],
     "authUsername": "<didww-outbound-username>",
     "authPassword": "<didww-outbound-password>",
     "media": {
       "encryption": "SIP_MEDIA_ENCRYPT_REQUIRE",
       "onlyListedCodecs": true,
       "codecs": [
         { "name": "PCMA", "rate": 8000 },
         { "name": "PCMU", "rate": 8000 }
       ]
     }
   }
   ```

   For unencrypted signaling and media, set `transport` to `SIP_TRANSPORT_TCP` and remove `encryption` from `media`. The
media setting must match **Media encryption mode** on the DIDWW outbound trunk, or the call fails.
4. Click **Create** and copy the outbound trunk ID.

![LiveKit outbound trunk configuration in the JSON editor](../../_images/livekit4.webp)


**Fig. 17.** LiveKit outbound trunk configuration in the JSON editor

In `address`, you can enter any DIDWW [outbound signaling
endpoint](../../voice/outbound-trunks/outbound-sip-information.html#voice-out-signaling-endpoints). Choose the one
closest to your LiveKit region.
Enter it as a hostname only, without a `sip:` prefix, port, or `;transport=` parameter.

### Step 4: Add Call Transfers to Your Agent

Call transfers are not configured in LiveKit Cloud.
Your agent or application starts a transfer in code during an active call by calling the LiveKit
`TransferSIPParticipant` server API.
For example, add a function tool to your agent that it runs when the caller asks to speak with a live person.

DIDWW supports cold call transfers using the SIP REFER method for inbound calls.
When your agent transfers a caller, LiveKit sends a SIP REFER request to DIDWW, and DIDWW places a new call to the
transfer destination through your DIDWW outbound trunk.
The caller then leaves the LiveKit room, and the agent is no longer part of the call.

**Call transfer at a glance**

```
        %%{init: {
  "theme": "base",
  "themeVariables": {
    "fontSize": "14px",
    "primaryColor": "#e0f2fe",
    "primaryBorderColor": "#38bdf8",
    "primaryTextColor": "#1f2d3d",
    "secondaryColor": "#ccfbf1",
    "secondaryBorderColor": "#2dd4bf",
    "secondaryTextColor": "#1f2d3d",
    "lineColor": "#0066cc",
    "textColor": "#1f2d3d",
    "nodeTextColor": "#1f2d3d",
    "edgeLabelBackground": "#ffffff"
  }
}}%%

flowchart LR
    caller["Caller"] -->|"1. Dials your DID number"| didww["DIDWW"]
    didww -->|"2. Inbound SIP trunk"| livekit["LiveKit room<br/>AI agent"]
    livekit -.->|"3. SIP REFER<br/>Transfer request"| didww
    didww -->|"4. New outbound call"| recipient["Person / team<br/>Transfer recipient"]

    classDef endpoint fill:#e0f2fe,stroke:#0066cc,color:#1f2d3d,stroke-width:1.5px
    classDef process fill:#ccfbf1,stroke:#2dd4bf,color:#1f2d3d,stroke-width:1.5px
    class caller,recipient endpoint
    class didww,livekit process
    linkStyle default stroke:#0066cc,stroke-width:1.5px
```

The **dashed arrow** is the SIP REFER request from LiveKit to DIDWW. Your agent starts this
request by calling `TransferSIPParticipant`. DIDWW places the new outbound call.

**After a successful transfer:** Caller → DIDWW → person or team. The original inbound call
continues, while the LiveKit room and AI agent are no longer part of the call.

View the transfer sequence: API request and SIP REFER

This simplified sequence shows a successful transfer. Routine SIP responses and media
negotiation are omitted.

```
        %%{init: {
  "theme": "base",
  "themeVariables": {
    "fontSize": "14px",
    "actorBkg": "#e0f2fe",
    "actorBorder": "#38bdf8",
    "actorTextColor": "#1f2d3d",
    "actorLineColor": "#38bdf8",
    "signalColor": "#0066cc",
    "signalTextColor": "#1f2d3d",
    "noteBkgColor": "#fef3c7",
    "noteBorderColor": "#facc15",
    "noteTextColor": "#1f2d3d",
    "labelBoxBkgColor": "#ccfbf1",
    "labelBoxBorderColor": "#2dd4bf",
    "labelTextColor": "#1f2d3d",
    "loopTextColor": "#1f2d3d",
    "sequenceNumberColor": "#ffffff"
  }
}}%%

sequenceDiagram
    participant C as Caller
    participant D as DIDWW
    participant L as LiveKit SIP service
    participant A as Your AI agent
    participant R as Person / team

    rect rgb(224, 242, 254)
        Note over C,A: 1. Original inbound call
        C->>D: Dial your DIDWW number
        D->>L: Deliver call through inbound trunk
        L->>A: Connect caller in the LiveKit room
    end
    rect rgb(204, 251, 241)
        Note over D,A: 2. Request a cold transfer
        A->>L: TransferSIPParticipant API<br/>roomName, participant identity, transferTo
        L->>D: SIP REFER<br/>Refer-To: sip:+number@outbound-gateway
    end
    rect rgb(224, 242, 254)
        Note over D,R: 3. Place the new outbound call
        D->>R: Call recipient through outbound trunk
        R-->>D: Recipient answers
    end
    rect rgb(204, 251, 241)
        Note over L,A: 4. Transfer complete<br/>Caller leaves the LiveKit room<br/>Agent is no longer in the call
        Note over C,R: Caller and recipient talk through DIDWW<br/>Original inbound call + new outbound call
    end
```

Note

Each transfer places a new outbound call through your DIDWW outbound trunk.
This call is charged per minute at the outbound rate for the transfer destination, in addition to the original inbound
call.

1. **Configure the transfer in your agent**

   A transfer needs two values from the active call:

   - **Room name**: the room of the call. With the dispatch rule from [Step 2](#livekit-create-dispatch-rule), each incoming call gets its own room with the `didww-call-` prefix.
   - **Participant identity**: the identity of the caller, who joins the room as a SIP participant.

   Your agent can read both values from the call it is handling.

   Set the transfer destination to a SIP URI at your DIDWW outbound gateway, in the format `sip:+[phone number]@[DIDWW
outbound gateway]`:

   - `[phone number]`: the number of the live person or team that takes transferred calls, in E.164 format. Do not use the DIDWW number assigned to your LiveKit inbound trunk, or the transferred call returns to your agent.
   - `[DIDWW outbound gateway]`: one of the DIDWW [outbound signaling endpoints](../../voice/outbound-trunks/outbound-sip-information.html#voice-out-signaling-endpoints), for example the one in `address` on your LiveKit outbound trunk.

   Note

   Call transfers require a `sip:` destination URI. The `tel:` URI format is not supported.

   The following Node.js example transfers the caller. `roomName` is the room of the active call and `participant` is
the caller's SIP participant. Replace `+15105550199` with the number to transfer to.
   For agent examples in Python and Node.js, see [LiveKit call
forwarding](https://docs.livekit.io/telephony/features/transfers/cold/).

   ```
   import { LiveKitAPI } from 'livekit-server-sdk';

   async function transferParticipant(roomName, participant) {
     const api = new LiveKitAPI();

     const transferTo = 'sip:+15105550199@fra.eu.out.didww.com';

     await api.sip.transferSipParticipant(roomName, participant.identity, transferTo, {
       playDialtone: false,
     });
   }
   ```
2. **Test the transfer with the CLI**

   To test a transfer without changing your agent, run the following [LiveKit
CLI](https://docs.livekit.io/reference/developer-tools/livekit-cli/) command during an active call.
   Replace `<room-name>` with the room name shown in the **Session** column on the **Telephony > Calls** page in LiveKit
Cloud, `<sip-participant-identity>` with the caller's **Participant identity** shown when you open that session (for
example, `sip_15105550123`), and `+15105550199` with the number to transfer to.

   ```
   lk sip participant transfer --room <room-name> \
     --identity <sip-participant-identity> \
     --to "sip:+15105550199@fra.eu.out.didww.com"
   ```

   The transfer destination sees the original caller's phone number as the caller ID.

### Step 5: Test the Configuration

Verify that inbound calling, outbound calling, and call transfers are working as expected.

**Inbound calls**

1. Make sure your voice AI agent is running or deployed with the agent name used in the dispatch rule.
2. Call the DIDWW number assigned to the inbound trunk.
3. Check that the agent answers and that both parties can hear each other.
4. Make a second test call and check that LiveKit creates a different room for it.

**Outbound calls**

Place a test call with the [LiveKit CLI](https://docs.livekit.io/reference/developer-tools/livekit-cli/).

1. Install and authenticate the LiveKit CLI, then select the project that contains your outbound trunk and agent.
2. Create a file named `sip-participant.json` with the following content. Replace the trunk ID and the number to dial. Enter the number in E.164 format (e.g., `+19085550100`).

   ```
   {
     "sip_trunk_id": "<livekit-outbound-trunk-id>",
     "sip_call_to": "<number-to-dial>",
     "room_name": "didww-outbound-test-001",
     "participant_identity": "sip-test",
     "participant_name": "Test Caller"
   }
   ```
3. Start the test call:

   ```
   lk sip participant create sip-participant.json
   ```
4. Answer the call on the destination phone.
5. To talk to your agent, dispatch it to the same room. Replace `didww-agent` with your agent name.

   ```
   lk dispatch create --agent-name didww-agent --room didww-outbound-test-001
   ```
6. Check the caller ID on the destination phone and that both parties can hear each other.

Use a new room name for each test call, in both `sip-participant.json` and the `lk dispatch create` command.

**Call transfers**

1. Call the DIDWW number assigned to the inbound trunk and wait for the agent to answer.
2. Trigger the transfer, for example by asking the agent to transfer you to a live person, or by running the `lk sip participant transfer` command from [Step 4](#livekit-transfer-calls). Asking the agent works only if your agent code includes a transfer.
3. Answer the call at the transfer destination.
4. Check that both parties can hear each other and that the destination shows the original caller's number as the caller ID.

Note

- Creating a SIP participant places the phone call. The agent joins only when you dispatch it to the room. Dispatch rules apply to inbound calls only.
- For application-level outbound calling, see [LiveKit outbound calls](https://docs.livekit.io/telephony/making-calls/outbound-calls/).
- You can review call activity and verify call status or error codes in the DIDWW **Inbound** and **Outbound Call Logs**. See [Inbound Call Logs](../../logs-analytics/call-logs/inbound-logs.html#inbound-cdr-logs) and [Outbound Call Logs](../../logs-analytics/call-logs/outbound-logs.html#outbound-cdr-logs) for more details.

---

## Troubleshooting

**404 Not Found** on an inbound call

LiveKit may not be matching the call to an inbound trunk or dispatch rule. Check that:

- **User Part of R-URI** on the DIDWW inbound trunk is `{DID}`.
- Your DIDWW number is listed on the LiveKit inbound trunk.
- The dispatch rule uses the correct LiveKit inbound trunk ID.

**407 Proxy Authentication Required** followed by **401 Unauthorized** on an inbound call

Check that **Auth User** and **Auth Password** on the DIDWW inbound trunk match the
credentials on the LiveKit inbound trunk.

A single **407 Proxy Authentication Required** response is the normal authentication
challenge. If it is followed by **401 Unauthorized** and the call fails, check the
credentials on both trunks.

**400 Bad Request** on an inbound call

The media settings may not match. On the DIDWW inbound trunk, check that:

- **SRTP Mode** is **SRTP SDES**.
- **Codecs** are limited to **PCMA** and **PCMU**.

The call connects, but the agent does not answer

Check that:

- The agent is running in the same LiveKit project as the SIP trunk.
- The registered agent name matches `agentName` in the dispatch rule.

For outbound calls, dispatch the agent to the same room as the SIP participant.

**500 No suitable media** on an outbound call

SRTP may not be enabled on the DIDWW outbound trunk. Set **Media encryption mode** to
**SRTP SDES** to match the encrypted media configuration on the LiveKit outbound trunk.

**401 Unauthorized**, **403 Forbidden**, or **407 Proxy Authentication Required** on an outbound call

If the call is rejected, check the authentication settings on both trunks:

- The username and password on the LiveKit outbound trunk must match the DIDWW outbound
  trunk credentials.
- **Allowed SIP IP addresses** on the DIDWW outbound trunk must include the LiveKit Cloud
  source IP ranges for the region placing the call.

**484 Address Incomplete** on an outbound call

Dial the full international number in E.164 format, for example `+19085550100`.
Remove local or international dialing prefixes such as `0`, `00`, or `011`.

The outbound call is rejected after authentication

Check the following on your DIDWW account and outbound trunk:

- The caller ID is permitted by **CLI Settings**.
- Calls to the destination are allowed.
- The trunk has not reached its **24 hour limit (USD)** or **Capacity limit**.
- Your account balance is sufficient.

**403 Forbidden** on a call transfer, followed by a dropped call

The transferred call could not be placed through your outbound trunk. Check that:

- **Allowed SIP IP addresses** on the DIDWW outbound trunk includes all DIDWW inbound
  SIP addresses used for transfers.
- The DIDWW inbound trunk uses the same credentials as the DIDWW outbound trunk.

A rejected transfer does not appear in the DIDWW **Outbound Call Logs**.

The call transfer is rejected

On the DIDWW inbound trunk, check that:

- **Max Transfers** is `1` or higher.
- **Network Protocol** matches the IP version of the addresses allowed on the DIDWW
  outbound trunk.

**603 Unconfigured xfer for tel URIs** on a call transfer

The transfer destination uses a `tel:` URI, which is not supported. Use a SIP URI in
this format instead: `sip:+[phone number]@[DIDWW outbound gateway]`.

For LiveKit diagnostics, see the [LiveKit SIP troubleshooting
guide](https://docs.livekit.io/reference/telephony/troubleshooting/).

## Additional Resources

- [LiveKit Voice AI quickstart](https://docs.livekit.io/agents/start/voice-ai/)
- [LiveKit inbound trunks](https://docs.livekit.io/telephony/accepting-calls/inbound-trunk/)
- [LiveKit dispatch rules](https://docs.livekit.io/telephony/accepting-calls/dispatch-rule/)
- [LiveKit outbound trunks](https://docs.livekit.io/telephony/making-calls/outbound-trunk/)
- [LiveKit call forwarding](https://docs.livekit.io/telephony/features/transfers/cold/)
- [LiveKit secure trunking](https://docs.livekit.io/telephony/features/secure-trunking/)

On this page
