> ## Documentation Index
> Fetch the complete documentation index at: https://plivo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect Any Orchestration Platform

> Connect Plivo SIP trunking to any voice agent orchestration platform that supports SIP

The Plivo side of a voice agent integration is the same regardless of which orchestration platform you use. If your platform supports SIP trunking, this guide connects it to the phone network through Plivo, even if Plivo doesn't have a dedicated guide for it. Each step includes both the [API](/voice-agents/sip-trunking/api/sip-trunking) and the [Console](https://cx.plivo.com/) option.

***

## Prerequisites

| Requirement                | Description                                                                                                                                                             |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Plivo Account**          | [Sign up](https://cx.plivo.com/signup) with SIP trunking enabled                                                                                                        |
| **Phone Number**           | [Purchase a voice-enabled number](https://cx.plivo.com/phone-numbers)<br />**India:** Requires KYC verification. See [Rent India Numbers](/numbers/rent-india-numbers). |
| **Orchestration platform** | An account with any voice agent platform that supports SIP trunking                                                                                                     |

If you're using the API, you also need your Plivo **Auth ID** and **Auth Token**, available on the [Plivo Console home page](https://cx.plivo.com/home). Export them as environment variables to use with the code samples in this guide:

```shell theme={null}
export PLIVO_AUTH_ID="<your_auth_id>"
export PLIVO_AUTH_TOKEN="<your_auth_token>"
```

From your platform's documentation, you need three facts:

1. **Its SIP endpoint**: the host Plivo should send inbound calls to (often `sip.<platform>.com`), and which transport it expects (UDP, TCP, or TLS)
2. **Its outbound authentication method**: SIP digest credentials (username and password), or a published list of static IP addresses
3. **Where to enter Plivo's details**: the screen where you register a phone number and configure a SIP trunk

<Warning>
  **India traffic:** calls to or from India require your platform to terminate SIP and media in India. See [Calling in India](/voice-agents/sip-trunking/production/calling-in-india) before you start.
</Warning>

***

## Part 1: Receive Incoming Calls

Route calls from your Plivo phone number to your platform.

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

<Tabs>
  <Tab title="API">
    First, create an [origination URI](/sip-trunking/api/origination-uris) that points to your platform's SIP endpoint, including the transport parameter it expects:

    <CodeGroup>
      ```python Python theme={null}
      import os
      import requests

      auth_id = os.environ["PLIVO_AUTH_ID"]
      auth_token = os.environ["PLIVO_AUTH_TOKEN"]

      response = requests.post(
          f"https://api.plivo.com/v1/Account/{auth_id}/Zentrunk/URI/",
          auth=(auth_id, auth_token),
          json={
              "name": "My platform SIP endpoint",
              "uri": "sip.example-platform.com;transport=tcp",
          },
      )
      print(response.json())
      ```

      ```javascript Node theme={null}
      const authId = process.env.PLIVO_AUTH_ID;
      const authToken = process.env.PLIVO_AUTH_TOKEN;
      const authHeader = 'Basic ' + Buffer.from(`${authId}:${authToken}`).toString('base64');

      const response = await fetch(`https://api.plivo.com/v1/Account/${authId}/Zentrunk/URI/`, {
        method: 'POST',
        headers: {
          'Authorization': authHeader,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: 'My platform SIP endpoint',
          uri: 'sip.example-platform.com;transport=tcp',
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>

    Copy the `uri_uuid` from the response. Next, create an [inbound trunk](/sip-trunking/api/trunks) using the origination URI as the primary URI:

    <CodeGroup>
      ```python Python theme={null}
      import os
      import requests

      auth_id = os.environ["PLIVO_AUTH_ID"]
      auth_token = os.environ["PLIVO_AUTH_TOKEN"]

      response = requests.post(
          f"https://api.plivo.com/v1/Account/{auth_id}/Zentrunk/Trunk/",
          auth=(auth_id, auth_token),
          json={
              "name": "My platform inbound trunk",
              "trunk_direction": "inbound",
              "primary_uri_uuid": "<uri_uuid>",
          },
      )
      print(response.json())
      ```

      ```javascript Node theme={null}
      const authId = process.env.PLIVO_AUTH_ID;
      const authToken = process.env.PLIVO_AUTH_TOKEN;
      const authHeader = 'Basic ' + Buffer.from(`${authId}:${authToken}`).toString('base64');

      const response = await fetch(`https://api.plivo.com/v1/Account/${authId}/Zentrunk/Trunk/`, {
        method: 'POST',
        headers: {
          'Authorization': authHeader,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: 'My platform inbound trunk',
          trunk_direction: 'inbound',
          primary_uri_uuid: '<uri_uuid>',
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>

    Copy the `trunk_id` from the response. You use it to connect your phone number in the next step.
  </Tab>

  <Tab title="Console">
    1. Go to [SIP Trunking → Inbound Trunks](https://cx.plivo.com/sip-trunking)
    2. Click **Create New Inbound Trunk** and enter a name (e.g., `MyPlatform-Inbound`)
    3. Click **Add New URI** and enter your platform's SIP endpoint, including the transport parameter it expects:

    | Field   | Value                                    |
    | ------- | ---------------------------------------- |
    | Name    | `MyPlatform-Primary`                     |
    | SIP URI | `sip.example-platform.com;transport=tcp` |

    4. Click **Create Trunk**
  </Tab>
</Tabs>

<Tip>
  The `transport` parameter must match what your platform expects. A mismatch is the most common reason an inbound integration fails silently. For TLS, use port 5061: `sip.example-platform.com:5061;transport=tls`.
</Tip>

### Step 2: Connect Your Phone Number

<Tabs>
  <Tab title="API">
    Assign the inbound trunk to your phone number using the [update a number](/numbers/account-phone-numbers#update-an-account-phone-number) endpoint. Set the `app_id` field to the **trunk ID** of your inbound trunk. Use your phone number in E.164 format without the leading `+`. For example, `15105550100`:

    <CodeGroup>
      ```python Python theme={null}
      import os
      import requests

      auth_id = os.environ["PLIVO_AUTH_ID"]
      auth_token = os.environ["PLIVO_AUTH_TOKEN"]
      phone_number = "15105550100"

      response = requests.post(
          f"https://api.plivo.com/v1/Account/{auth_id}/Number/{phone_number}/",
          auth=(auth_id, auth_token),
          json={
              "app_id": "<trunk_id>",
          },
      )
      print(response.json())
      ```

      ```javascript Node theme={null}
      const authId = process.env.PLIVO_AUTH_ID;
      const authToken = process.env.PLIVO_AUTH_TOKEN;
      const authHeader = 'Basic ' + Buffer.from(`${authId}:${authToken}`).toString('base64');
      const phoneNumber = '15105550100';

      const response = await fetch(`https://api.plivo.com/v1/Account/${authId}/Number/${phoneNumber}/`, {
        method: 'POST',
        headers: {
          'Authorization': authHeader,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          app_id: '<trunk_id>',
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>

    A successful response returns HTTP `202` with the message `changed`.
  </Tab>

  <Tab title="Console">
    1. Go to [Your Numbers](https://cx.plivo.com/phone-numbers)
    2. Click on your phone number
    3. Set **Application Type** to `Zentrunk`
    4. Set **Trunk** to your inbound trunk
    5. Click **Update Number**
  </Tab>
</Tabs>

### Step 3: Configure Your Platform

On your platform, register the Plivo number and attach an agent to it. This step varies by platform; look for "SIP trunk", "BYO carrier", or "phone numbers" in its documentation.

Call your Plivo number. Your agent should answer.

***

## Part 2: Make Outgoing Calls

Enable your platform to place calls through Plivo.

### Step 1: Create Authentication

Choose the method your platform supports: SIP digest **credentials** when your platform authenticates with a username and password or its IPs are dynamic, or an **IP access control list** when it publishes static IP addresses for its SIP traffic.

<Tabs>
  <Tab title="API">
    To create a [credential](/sip-trunking/api/credentials), use a username of 5 to 20 alphanumeric characters and a password of 5 to 20 characters with at least one of the special characters `~!@#$%^&*()_+`:

    <CodeGroup>
      ```python Python theme={null}
      import os
      import requests

      auth_id = os.environ["PLIVO_AUTH_ID"]
      auth_token = os.environ["PLIVO_AUTH_TOKEN"]

      response = requests.post(
          f"https://api.plivo.com/v1/Account/{auth_id}/Zentrunk/Credential/",
          auth=(auth_id, auth_token),
          json={
              "name": "My platform outbound credential",
              "username": "<username>",
              "password": "<password>",
          },
      )
      print(response.json())
      ```

      ```javascript Node theme={null}
      const authId = process.env.PLIVO_AUTH_ID;
      const authToken = process.env.PLIVO_AUTH_TOKEN;
      const authHeader = 'Basic ' + Buffer.from(`${authId}:${authToken}`).toString('base64');

      const response = await fetch(`https://api.plivo.com/v1/Account/${authId}/Zentrunk/Credential/`, {
        method: 'POST',
        headers: {
          'Authorization': authHeader,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: 'My platform outbound credential',
          username: '<username>',
          password: '<password>',
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>

    Copy the `credential_uuid` from the response.

    Alternatively, create an [IP access control list](/sip-trunking/api/ip-access-control-lists) with your platform's published IP addresses:

    <CodeGroup>
      ```python Python theme={null}
      import os
      import requests

      auth_id = os.environ["PLIVO_AUTH_ID"]
      auth_token = os.environ["PLIVO_AUTH_TOKEN"]

      response = requests.post(
          f"https://api.plivo.com/v1/Account/{auth_id}/Zentrunk/IPAccessControlList/",
          auth=(auth_id, auth_token),
          json={
              "name": "My platform IPs",
              "ip_addresses": ["203.0.113.10", "203.0.113.11"],
          },
      )
      print(response.json())
      ```

      ```javascript Node theme={null}
      const authId = process.env.PLIVO_AUTH_ID;
      const authToken = process.env.PLIVO_AUTH_TOKEN;
      const authHeader = 'Basic ' + Buffer.from(`${authId}:${authToken}`).toString('base64');

      const response = await fetch(`https://api.plivo.com/v1/Account/${authId}/Zentrunk/IPAccessControlList/`, {
        method: 'POST',
        headers: {
          'Authorization': authHeader,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: 'My platform IPs',
          ip_addresses: ['203.0.113.10', '203.0.113.11'],
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>

    Copy the `ipacl_uuid` from the response.
  </Tab>

  <Tab title="Console">
    **Credentials:**

    1. Go to [SIP Trunking → Outbound Trunks](https://cx.plivo.com/sip-trunking)
    2. Click **Add New Credentials List** and create credentials:
       * Username: `myplatform_trunk` (or your preferred username)
       * Password: Generate a strong password

    **IP access control list:**

    1. Go to [SIP Trunking → Outbound Trunks → IP Access Control List](https://cx.plivo.com/sip-trunking)
    2. Click **Create New IP Access Control List** and enter a name (e.g., `MyPlatform-IPs`)
    3. Add the IP addresses from your platform's documentation
    4. Click **Create**
  </Tab>
</Tabs>

### Step 2: Create an Outbound Trunk in Plivo

<Tabs>
  <Tab title="API">
    Create an [outbound trunk](/sip-trunking/api/trunks) using the credential or IP ACL from Step 1. Pass `credential_uuid`, `ipacl_uuid`, or both. Set `secure` to `true` if your platform supports TLS and SRTP (recommended):

    <CodeGroup>
      ```python Python theme={null}
      import os
      import requests

      auth_id = os.environ["PLIVO_AUTH_ID"]
      auth_token = os.environ["PLIVO_AUTH_TOKEN"]

      response = requests.post(
          f"https://api.plivo.com/v1/Account/{auth_id}/Zentrunk/Trunk/",
          auth=(auth_id, auth_token),
          json={
              "name": "My platform outbound trunk",
              "trunk_direction": "outbound",
              "credential_uuid": "<credential_uuid>",
              "secure": True,
          },
      )
      print(response.json())
      ```

      ```javascript Node theme={null}
      const authId = process.env.PLIVO_AUTH_ID;
      const authToken = process.env.PLIVO_AUTH_TOKEN;
      const authHeader = 'Basic ' + Buffer.from(`${authId}:${authToken}`).toString('base64');

      const response = await fetch(`https://api.plivo.com/v1/Account/${authId}/Zentrunk/Trunk/`, {
        method: 'POST',
        headers: {
          'Authorization': authHeader,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: 'My platform outbound trunk',
          trunk_direction: 'outbound',
          credential_uuid: '<credential_uuid>',
          secure: true,
        }),
      });
      console.log(await response.json());
      ```
    </CodeGroup>

    Copy the `trunk_id` from the response, then retrieve the trunk to get your **Termination SIP Domain** from the `trunk_domain` field (e.g., `21784177241578.zt.plivo.com`):

    <CodeGroup>
      ```python Python theme={null}
      import os
      import requests

      auth_id = os.environ["PLIVO_AUTH_ID"]
      auth_token = os.environ["PLIVO_AUTH_TOKEN"]
      trunk_id = "<trunk_id>"

      response = requests.get(
          f"https://api.plivo.com/v1/Account/{auth_id}/Zentrunk/Trunk/{trunk_id}/",
          auth=(auth_id, auth_token),
      )
      print(response.json())
      ```

      ```javascript Node theme={null}
      const authId = process.env.PLIVO_AUTH_ID;
      const authToken = process.env.PLIVO_AUTH_TOKEN;
      const authHeader = 'Basic ' + Buffer.from(`${authId}:${authToken}`).toString('base64');
      const trunkId = '<trunk_id>';

      const response = await fetch(`https://api.plivo.com/v1/Account/${authId}/Zentrunk/Trunk/${trunkId}/`, {
        headers: { 'Authorization': authHeader },
      });
      console.log(await response.json());
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Console">
    1. Go to [SIP Trunking → Outbound Trunks](https://cx.plivo.com/sip-trunking)
    2. Click **Create New Outbound Trunk** and enter a name (e.g., `MyPlatform-Outbound`)
    3. Select the credentials list or IP ACL from Step 1
    4. Enable **Secure Trunking** if your platform supports TLS and SRTP (recommended)
    5. Click **Create Trunk**
    6. Copy your **Termination SIP Domain** (e.g., `XXXXXXXXXXXX.zt.plivo.com`)
  </Tab>
</Tabs>

### Step 3: Configure Your Platform

In your platform's outbound trunk settings, enter:

| Setting                      | Value                                                                                  |
| ---------------------------- | -------------------------------------------------------------------------------------- |
| SIP domain / termination URI | Your Termination SIP Domain from Step 2                                                |
| Username and password        | The credentials from Step 1 (if using credentials)                                     |
| Caller ID                    | A Plivo number you rent, or a [verified caller ID](/voice/concepts/verified-caller-id) |

<Warning>
  **Caller ID must be a Plivo number.** Outbound calls that present a non-Plivo number fail with hangup code 4190 (`unknown_caller_id`). See [Hangup codes](/voice-agents/sip-trunking/troubleshooting/hangup-codes).
</Warning>

<Tip>
  If your platform sends SIP OPTIONS pings for health checks, point them at the outbound trunk URI only, at most one ping every 10 to 15 seconds. Higher frequency may trigger blocking. See [Technical Specifications](/sip-trunking/concepts/technical-specifications).
</Tip>

***

## Troubleshooting

| Issue                              | Solution                                                                                                                                                                                   |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Inbound call doesn't connect       | Verify the trunk URI matches your platform's SIP endpoint exactly, including the `transport` parameter. Confirm the number's Application Type is `Zentrunk` and points at the right trunk. |
| Outbound authentication fails      | Credentials must match exactly on both sides. For IP ACLs, confirm the platform's current IP list; platforms occasionally add addresses.                                                   |
| Outbound calls fail immediately    | Check the caller ID is a Plivo number (hangup 4190). Check [debug logs](https://cx.plivo.com/sip-trunking) for the hangup code.                                                            |
| One-way or no audio on India calls | See [Calling in India](/voice-agents/sip-trunking/production/calling-in-india); hangup 4590 indicates a media anchoring violation.                                                         |

**Debug logs:** for inbound issues, check [Plivo logs](https://cx.plivo.com/sip-trunking) first; for outbound issues, check your platform's logs first. For error codes, see [Hangup codes](/voice-agents/sip-trunking/troubleshooting/hangup-codes).

***

## Related

* [API Reference](/voice-agents/sip-trunking/api/sip-trunking) - Create trunks, credentials, URIs, and IP ACLs programmatically
* [Technical Specifications](/sip-trunking/concepts/technical-specifications) - Codecs, ports, IP ranges, and supported SIP features
* [Your First Agent Call](/voice-agents/sip-trunking/getting-started/your-first-agent-call) - Quickstart with per-platform SIP URIs
