# SIP Trunks (/docs/overview/sip-trunks)

> For the complete documentation index, see [llms.txt](https://docs.tandemcx.ai/llms.txt). Any page on this site can be fetched as Markdown by appending `.md` to its URL.

<Callout type="info">
    **SIP Trunks is enabled per organization.** If **Admin → SIP Trunks** isn't in your sidebar,
    contact support to have it switched on.
</Callout>

A SIP trunk connects your own carrier to Tandem. You manage trunks on **Admin → SIP Trunks**.
Each trunk's numbers are also listed on **Admin → Phone Numbers**, where you can change how a
single number routes.

This page covers a trunk's **SIP credentials**, its **allowed source IPs**, where its calls
**route**, and its **Inbound SIP Headers**.

## SIP credentials

Every trunk you create has a SIP username and password. Your carrier or PBX authenticates with
them on each inbound call, and that is how Tandem tells which trunk, and which organization,
the call belongs to. You don't choose them: Tandem generates them when you create the trunk.

### Copy the credentials

1. On **Admin → SIP Trunks**, create the trunk.
2. The dialog switches to **SIP Trunk Credentials**. Copy the username and password.
3. Configure them on your carrier or PBX, then click **Done**.

The password is shown only this once. Tandem keeps no readable copy, so if you lose it you have
to rotate it.

### Rotate the password

1. Open **Admin → SIP Trunks** and select the trunk.
2. In **SIP Authentication**, click **Rotate Password**, then **Rotate** to confirm.
3. Copy the new password and configure it on your carrier or PBX.

The username stays the same. The old password stops working within a minute, so calls fail
until the carrier has the new one.

A trunk created before credentials were generated shows **Generate Credentials** instead. Until
you generate them, it is still identified by its source IP. Once it has credentials it no longer
is, so calls are refused until your carrier sends them. Have the carrier ready before you confirm.

## Allowed source IPs

**Allowed Source IPs**, under **Access Control**, limits where a trunk's credentials may be used
from. When the list is set, a call that authenticates with the right username and password but
comes from an address not on the list is refused. When it is empty, the credentials are accepted
from any address.

Enter IPv4 addresses (`203.0.113.10`) or CIDR ranges (`203.0.113.0/24`). IPv6 is not supported.

## Route a trunk's calls

Each number on a trunk can go to a workflow or directly to a voice agent. A number with no route
of its own uses the trunk's **Default Route**, which can also be a workflow or an agent.

### Set a number's route

1. Open **Admin → Phone Numbers** and click **Edit** on the trunk number's row. Or open **Admin → SIP
   Trunks**, select the trunk, and find the number in its phone number list.
2. Under **Routes to** (on a row in the trunk's number list, the **Workflow** and **Agent**
   toggle), choose **Workflow** or **Agent**, then pick the workflow or agent.
3. Click **Save**.

A number set to **Agent** can't be saved from its sidebar until an agent is picked.

To send a number back to the trunk's default route, clear the picker that is showing, whether it
is the workflow or the agent, then click **Save**. The number then shows **Workflow** with **Trunk
default**.

### Set the trunk's default route

1. Open **Admin → SIP Trunks** and select the trunk.
2. Under **Default Route**, choose **Workflow** or **Agent**, then pick one.
3. Click **Save**.

Calls to a number with no route of its own go to the default route. The **Create SIP Trunk**
dialog has the same **Default Route** choice. **Create** stays disabled while **Agent** is chosen
and no agent is picked.

### Attach a number from the agent

You can also route a trunk number to an agent from the agent's **Phone Numbers** card: check the
number to attach it. Unchecking a trunk number detaches it and returns it to its trunk's default
route. See [Voice agents](/docs/agents/voice-agents).

### Agents that can't answer

An agent with no published version appears in the picker but can't be chosen. See
[Versioning](/docs/agents/voice-agents/versioning).

## Inbound SIP headers

Your carrier or PBX can put custom headers on the INVITE it sends, such as an account id or the
queue a call came from. List those headers on the trunk, and Tandem reads them off every
inbound call on that trunk and sets each value to a variable you name.

The mapping belongs to the trunk, so it applies to every number on it. You cannot set a different
list for one number.

### Map a header to a variable

1. Open **Admin → SIP Trunks** and select the trunk.
2. In **Inbound SIP Headers**, click **Add Header**.
3. Enter the **SIP Header** name exactly as the carrier sends it, for example `X-Account-Id`.
4. Enter the **Variable** name to set, for example `account_id`.
5. Click **Save**.

The next call on the trunk uses the new list.

### Use the value

Where the call goes decides how you reference the value:

| The number routes to              | Reference                                                   |
| --------------------------------- | ----------------------------------------------------------- |
| A workflow                        | `{{account_id}}`                                            |
| A voice agent, directly           | `{{vars.account_id}}`                                       |
| A workflow that hands to an agent | Pass it in **Pass to agent** on the **AI Voice Agent** node |

When a voice agent the number routes to directly hands the call to a workflow, the header
variables go with it, under the names you chose. If the agent's handoff passes a value with the
same name, the agent's value is used.

A per-call value reaches an agent the same way **Pass to agent** values do. See
[Values for a single call](/docs/overview/secrets-and-variables#values-for-a-single-call).

### See a number's headers

Open a trunk number on **Admin → Phone Numbers**. Its **Inbound SIP Headers** section lists the
trunk's mappings read-only. Change them on the SIP Trunks page.

### Limits and defaults

- **Up to 10 headers** per trunk, with every header and variable name together using no more
  than 350 characters.
- **Header names** use letters, digits, `-`, `_` and `.`, up to 64 characters, and start with a
  letter or digit. SIP header names are case-insensitive, so `X-Queue` and `x-queue` count as the
  same header and can't both be listed.
- **Variable names** use lowercase letters, digits and `_`, up to 64 characters. Each header
  needs its own variable. `org`, `secrets`, `agent`, `vars` and `sys` are reserved.
- **Values are cut at 256 characters.**
- **A header the call doesn't carry leaves its variable unset.** The call is not refused.
- **Test calls from the workflow editor** have no SIP INVITE, so they set none of these variables.

Header values come from your carrier, or from whoever placed the call, so treat them as input
you have not checked. Don't use one to decide anything a caller shouldn't be able to choose.

## Troubleshooting

**Calls on the trunk are refused.** Check that the carrier sends the trunk's current username and
password, and that it sends from an address in **Allowed Source IPs** if you have set any.

**A variable is always empty.** The header has to arrive on the INVITE that reaches Tandem.
Check that your carrier or PBX sends it on this trunk and that nothing between them and Tandem
removes it. Check the spelling of the header name, too.

**Save is disabled.** A header row has an error, shown under the field. A row with both fields
empty is ignored on save. Save is also disabled when the **Default Route** is set to **Agent**
and no agent is picked.
