# SIP Trunking

> Connect carriers to your workspace: bring your own SIP trunk or use a managed trunk.

A **trunk** moves phone calls in and out of your workspace. A trunk is a named
SIP/RTP profile. It tells the voice gateway where your carrier is, how to
authenticate, which codecs to offer, and what to do with an inbound call.
Set up a trunk once per carrier. Calls then flow to your AI agents, IVR flows,
and human queues.

You have two ways to connect:

  - **Bring your own trunk** — Point your existing carrier's SBC at your workspace. You keep your numbers,
    your contract, and your rates. You only re-home the signalling.
  - **Managed trunk** — Provision a number and carrier connectivity from inside FirstByte. You
    configure nothing on your side. The number lands in your inventory, ready
    to bind.

## Your inbound SIP endpoint

Every workspace gets its **own** SIP endpoint. FirstByte provisions it
automatically at onboarding:

```
<workspace-id>.sip.firstbyte.fast    (SIP signalling, UDP/TCP/TLS :5060)
```

Carriers send calls **to** you at this endpoint. The gateway reads the leftmost
DNS label of each inbound INVITE and resolves it to your tenant. This isolates
calls per workspace, with no cross-tenant extension collisions. Find your
`<workspace-id>` under **Admin → Trunks** on [agent.firstbyte.fast](https://agent.firstbyte.fast).

> **NOTE:**
> Browser and app callers use a separate per-workspace WebRTC endpoint,
> `<workspace-id>.webrtc.firstbyte.fast` — see [Transport to Web & Apps](/modalities/voice/transport-web/overview).
> This page covers the phone-network (PSTN/SIP) side.

## Bring your own SIP trunk

Use this option when you already have a carrier or on-prem PBX and want to keep
it. You tell the gateway where the far end is. The gateway acts as a
back-to-back user agent (B2BUA) between your carrier and the runtime. The
gateway has a built-in registrar, so you do **not** need a separate
registration server.

  1. **Name the trunk and set a channel limit**
Give the trunk a stable **Trunk ID** and a friendly **Display Name**. The
    Trunk ID is a short handle that you reference everywhere, for example
    `INT-KA-SBC09`. Set the **Channel Limit** — the maximum concurrent calls
    that this trunk carries (default `50`). Match the limit to your carrier
    contract. The gateway rejects calls above the limit, so a limit that is
    too low silently drops traffic at peak.

  2. **Point at the carrier or SBC**
Enter the location of your carrier's session border controller:
    - The **SBC IP**, or the **Gateway IP** for a direct peer.
    - The **SIP Domain** used in the `From` header and registration (often the SBC host).
    - The local **Source Port** (default `5060`).
    - The far-end **Destination Port** that your carrier assigned.
    - An **Outbound Proxy** (`host:port`), if the carrier routes through one.
    > **NOTE:**
> Inbound INVITEs from a configured trunk peer bypass the workspace's
>     registrar ACL. The gateway matches the trunk by source IP (and by the
>     dialed DID). Your carrier does not need to register or
>     digest-authenticate to reach you, unless you require it below.

  3. **Add credentials (only if your carrier requires registration)**
Some carriers expect you to **register** before you place calls. If yours
    does, enable **Require SIP REGISTER**. Set a **SIP Username**, a
    **SIP Password**, and **Register Expires** in seconds (default `3600`).
    When you save, the trunk registers immediately. Its status chip turns
    **connected**, or **error** if the carrier rejects the credentials.
    > **WARNING:**
> SIP passwords are **sealed at rest**. The system never returns them when
>     you read a trunk back. To rotate a credential, save the trunk again with
>     the new value.

  4. **Fill in your own network addresses and realm**
Enter your side of the connection: **Internal SIP IP** / **External SIP IP**
    and **Internal RTP IP** / **External RTP IP**. The carrier sees the
    *external* (public) addresses in your SIP and SDP. The *internal* addresses
    are the bind addresses for traffic that stays inside your network. This
    split makes the trunk work behind NAT.

    Set the **Realm** to describe the far end. Use **Internal** for your own
    PBX or extensions. Use **External** for a PSTN/SIP carrier (per-minute
    billing applies). Use **AI Vendor** when the trunk is an AI-agent leg.

  5. **Choose codecs and media mode**
List **Codec Preferences** in priority order (default `PCMU, PCMA, OPUS`).
    The first codec that both sides support wins. On the wire, phone legs are
    almost always G.711 (µ-law `PCMU` / A-law `PCMA`). The gateway transcodes
    to the internal audio format for the runtime. See
    [Codecs](/modalities/voice/transport-telephony/codecs) for the full matrix.

    Leave **Media Mode** on **Proxy** (the default) unless you have a specific
    reason to change it. Proxy anchors media at the gateway. This is the safe,
    NAT-friendly choice.
    > **NOTE:**
> **Direct** media is a preview. Even when you select it, the runtime
>     currently anchors (proxies) the RTP media. Keep new trunks on **Proxy**.

  6. **Pick your SIP compliance headers**
Choose an outbound identity mode. **Full** adds the caller-identity headers
    that carriers expect from a regulated edge: `Remote-Party-ID`,
    `P-Asserted-Identity`, and `P-Access-Network-Info`. **Full** is the
    recommended default. **Minimal** suppresses all three.
    > **WARNING:**
> A few carriers silently drop calls when the customer edge asserts identity.
>     If your outbound calls only return *100 Trying* and then time out,
>     switch to **Minimal**.

  7. **Save and confirm**
Save the trunk. It appears in the list with a live status chip:
    **connected**, **error**, or **disconnected**. The list also shows live
    health: answer ratio, average call duration, and an estimated MOS from the
    media plane. Click a trunk to edit any section or to remove it. In-flight
    calls keep running until they hang up naturally.

After the trunk is up, register the numbers (DIDs) that callers dial. Bind each
number to this trunk — see [Number Provisioning](/modalities/voice/transport-telephony/number-provisioning).

## Managed trunk

If you do not want to run a carrier relationship, provision a number and its
connectivity from inside FirstByte. Under **Admin → Trunks**, choose the
managed option. Pick a number from the catalog. The number lands in your
inventory, ready to bind. You do not fill in an SBC, credentials, or network
addresses.

> **NOTE:**
> The self-serve number catalog is currently an early-access demo with limited
> inventory. Production carrier coverage (multi-region DID search across Twilio,
> Telnyx, and Bandwidth) is rolling out. The number-allocation and inbound-routing
> paths behind the catalog are fully live. If the catalog does not list a number
> that you need, bring it in as a bring-your-own DID and route it over a BYO trunk.

## Inbound routing

`inbound_rule` decides what happens when a call arrives on the trunk. New trunks
default to **reject** until you set one of the handlers:

| Rule                | What it does                                                        |
| ------------------- | ------------------------------------------------------------------ |
| Reject              | Decline the call. Optionally, play a clip first, then hang up.      |
| Play & hangup       | Play an announcement, then release the call.                        |
| Notify & hangup     | Fire a webhook, then release the call.                              |
| Handle with AI      | Bridge the call to an AI agent (over the QUIC or WebSocket bridge). |

You can also route the trunk into an IVR/ACD program. To do this, bind the
trunk to a skill or a VDN instead of a single agent — see
[Inbound Calls](/modalities/voice/transport-telephony/inbound)
and [PBX & ACD](/modalities/voice/transport-telephony/pbx-acd).

## Field reference & raw RPC

The console form maps 1:1 onto the trunk record. The key fields:

- **`channel_limit`** (`uint32`, default `50`) — The maximum concurrent calls on the trunk.
- **`internal_sip_ip / external_sip_ip`** (`string`) — Your private bind address, and the public address advertised in SIP (NAT).
- **`internal_rtp_ip / external_rtp_ip`** (`string`) — The same split, for the RTP media plane.
- **`sip_username / sip_password`** (`string`) — Registrar credentials, used when registration is required. Sealed at rest.
- **`register_expires_sec`** (`uint32`, default `3600`) — The REGISTER `Expires` value when the trunk registers with the carrier.
- **`media_mode`** (`string`, default `proxy`) — `proxy` anchors media at the gateway. `direct` is a preview.
- **`realm`** (`string`) — `internal`, `external`, or `ai_vendor`.
- **`compliance_headers`** (`string`) — The outbound identity mode: full (asserts identity) or minimal.
- **`inbound_rule`** (`int32`) — Reject / play & hangup / notify & hangup / handle with AI.

> **TIP:**
> Do you want to automate trunk provisioning? The full DTO — `AddTrunk`,
> `UpdateTrunk`, `GetTrunk`, `RemoveTrunk` — and its raw over-QUIC RPC envelope
> are documented in [Trunks](/admin/trunks).

## Next steps

  - **[Number provisioning](/modalities/voice/transport-telephony/number-provisioning)** — Register DIDs and bind each to a trunk, agent, or flow.
  - **[Inbound calls](/modalities/voice/transport-telephony/inbound)** — Route incoming calls to AI agents, IVR flows, and queues.
  - **[Codecs](/modalities/voice/transport-telephony/codecs)** — G.711 on the wire, Opus for apps, and how transcoding works.
  - **[Outbound calls](/modalities/voice/transport-telephony/outbound)** — Originate calls and run paced campaigns over your trunks.
