Vapi Integration
This guide will walk you through connecting your Bandwidth phone numbers to Vapi over SIP trunking, so a real PSTN caller can talk to a Vapi assistant, and so your assistant can place calls back out to the PSTN. You already have Bandwidth Voice; Vapi is the add-on that answers and drives the conversation.
Like our ElevenLabs integration and unlike Pipecat or Cartesia, this one is configuration only. There is no application to write or host: Vapi orchestrates speech-to-text, the LLM, and text-to-speech on its side, and Bandwidth carries the call.
This integration uses SIP trunking on Bandwidth's Universal Platform, not Programmable Voice or Media Streaming. Signaling runs over UDP and, once a call is established, RTP media flows between Bandwidth and Vapi — Bandwidth is the carrier, Vapi is the voice-agent endpoint.
Vapi is a third-party platform. Bandwidth has no affiliation with Vapi, and Vapi's endpoints and configuration options can change without notice. Bandwidth supports the trunking side of this integration; questions about your Vapi assistant, credential, or dashboard are between you and Vapi.
What you'll need
- A Bandwidth Universal Platform account with:
- SIP trunking enabled on your account
- At least one phone number
- Access to create Voice Configuration Packages (Bandwidth App or the Voice Configuration API)
- The signaling (Orig/Term) IP address of your Bandwidth trunk — see Find your Bandwidth signaling IP below
- For outbound calling, an account enabled for SIP credentials — see Configure outbound calls
- A Vapi account with an assistant you want to answer calls
How it works
Inbound calls are routed by a Bandwidth Voice Configuration Package to a Vapi SIP endpoint that is scoped to your Vapi SIP trunk credential. Vapi accepts the call by recognizing your Bandwidth trunk's source IP address.
Two details make this work, and both are easy to miss:
- Vapi identifies the destination trunk from the subdomain (
{credential_id}.sip.vapi.ai) and the destination number from the SIP request-URI user part. Bandwidth sends the dialed number in E.164 format with a leading+, which is what Vapi expects. - Vapi authorizes inbound calls by source IP address. If Bandwidth's signaling IP is not registered on your Vapi credential, Vapi will not accept the call — see Troubleshooting.
Find your Bandwidth signaling IP
Vapi needs to know which IP address your calls will arrive from, and it rejects calls from anywhere else. This is your trunk's signaling IP, and it isn't a platform-wide value: Bandwidth assigns a distinct address per zone, and a different one per product (standard SIP, SIP over TLS, SIP Auth, SIP Registrar).
In the Bandwidth App, go to Account → Trunk Group Configurations. Your signaling IPs are published there once your trunk groups are deployed. This guide uses standard SIP over UDP, so you want the standard SIP (Orig/Term) signaling IP rather than the TLS, SIP Auth, or Registrar address. If you can't find it, contact Bandwidth Support.
The signaling IP is the only address Vapi needs. Each SBC also has a pool of media IP addresses that carry RTP audio, and those don't need to be registered.
Do not guess this value or reuse an address from another account. If it doesn't match the address your calls actually originate from, Vapi will reject every inbound call.
If your trunk group is migrated to a different SBC, its signaling IP changes and the gateway on your Vapi credential goes stale: inbound calls start failing even though nothing changed on your side. If a working integration stops accepting calls after a maintenance event, check this value first.
Configure inbound calls (in Bandwidth)
To send calls that arrive on your Bandwidth number to your Vapi assistant, create a Voice Configuration Package that routes the number to your Vapi SIP endpoint.
First, get your Vapi SIP trunk credential ID. Create a byo-sip-trunk credential in Vapi (see Complete setup in Vapi) and note the id it returns. Your inbound endpoint is:
| Vapi region | Endpoint |
|---|---|
| US | {credential_id}.sip.vapi.ai |
| EU | {credential_id}.sip.eu.vapi.ai |
Then, in the Bandwidth App:
- Go to Service Management → Voice Configuration and click Create New. For a full walkthrough of this screen, see the Create a Voice Configuration Package guide.
- Package Name: a unique name you'll recognize (e.g.
vapi-agent). - Route type: select Route to Domain Name.
- FQDN: your endpoint from the table above.
- Package Name: a unique name you'll recognize (e.g.
- Assign the phone number that should reach your assistant to this Voice Configuration Package.
- Confirm the number has inbound voice service activated.
If you'd rather configure this over the API, the same route is an FQDN endpoint on the package's origination route plan:
{
"name": "vapi-agent",
"originationRoutePlan": {
"routes": [
{
"priority": 1,
"name": "vapi",
"endpoints": [
{
"endpoint": "{credential_id}.sip.vapi.ai",
"type": "FQDN",
"weight": 100
}
]
}
]
}
}
POST that to https://api.bandwidth.com/v2/accounts/{accountId}/voiceConfigurationPackages, then assign your number to the returned voiceConfigurationPackageId.
Complete setup in Vapi
With Bandwidth routing configured, create the SIP trunk credential and import your number. Follow Vapi's SIP trunking documentation and supply the values below.
Create a SIP trunk credential
Register your Bandwidth signaling IP as a gateway so Vapi accepts calls from your trunk:
curl -X POST https://api.vapi.ai/credential \
-H "Authorization: Bearer $VAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "byo-sip-trunk",
"name": "Bandwidth",
"gateways": [
{
"ip": "<your-bandwidth-signaling-ip>",
"port": 5060,
"netmask": 32,
"inboundEnabled": true
}
]
}'
A few things to note:
- The
ipvalue must be a numeric IPv4 address. Vapi rejects a hostname here when inbound is enabled. - Note the
idreturned by this call. That's the{credential_id}in your Bandwidth FQDN. - If your trunks are deployed across more than one SBC, add a gateway entry for each signaling IP, or widen
netmaskto cover the range. A single/32that misses one of your SBCs produces calls that fail intermittently. - If your Vapi organization is hosted in the EU, create the credential and phone number against
https://api.eu.vapi.aiinstead, and use the.sip.eu.vapi.aiendpoint.
Import your phone number
Link your Bandwidth number to the credential and the assistant that should answer:
curl -X POST https://api.vapi.ai/phone-number \
-H "Authorization: Bearer $VAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "byo-phone-number",
"number": "+19195551234",
"numberE164CheckEnabled": true,
"credentialId": "<credential-id>",
"assistantId": "<assistant-id>"
}'
The number must be in E.164 format with a leading +. You can also import the number and assign an assistant from the Vapi dashboard.
Test inbound calls
Call your Bandwidth phone number. Your Vapi assistant should answer and begin the conversation.
Configure outbound calls
Everything above covers inbound. Outbound is the reverse — your assistant placing a call through Bandwidth — and it uses a different authorization model. Rather than Vapi trusting your source IP, Bandwidth authenticates Vapi using SIP digest credentials issued against a Bandwidth SIP realm.
Your account must be enabled for SIP credentials before you can create a realm. If realm creation fails with this account isn't enabled for SIP credentials, contact Bandwidth Support and ask them to enable SipCredentialSettings.
Create a realm and SIP credential (in Bandwidth)
A realm is the SIP authentication domain your credentials belong to. Bandwidth generates its hostname for you — something like myrealm-a1b2c3.auth.bandwidth.com.
With the Bandwidth CLI:
# Create the realm, then note the id and hostname it returns
band sip realm create --name vapi --default=false --wait
# Create a digest credential on it, identifying the realm by id or hostname
printf '%s' "$SIP_PASSWORD" | band sip credential create \
--realm <realm-id> \
--username vapi-agent \
--password-stdin
You can do the same in the Bandwidth App under Account → SIP Credentials, where Manage Realms creates the realm and the main screen adds credentials to it. See How to set up SIP Registration for a walkthrough, including the digest hashing details.
Keep three values for the next step: the realm hostname, the username, and the password.
The phone number you use as the caller ID should belong to the same account as the realm. A number from a different account can be rejected by ANI validation.
Create an outbound SIP trunk credential (in Vapi)
Point a Vapi credential at your realm hostname and give it the digest credentials:
curl -X POST https://api.vapi.ai/credential \
-H "Authorization: Bearer $VAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "byo-sip-trunk",
"name": "Bandwidth outbound",
"gateways": [
{
"ip": "<your-realm-hostname>",
"port": 5060,
"inboundEnabled": false,
"outboundEnabled": true
}
],
"outboundAuthenticationPlan": {
"authUsername": "vapi-agent",
"authPassword": "<your-sip-password>"
}
}'
Two things to note:
- The gateway takes the realm hostname, not an IP address. Vapi only requires a numeric IPv4 when
inboundEnabledis true, so an outbound-only gateway can use the FQDN. authUsernameis the bare SIP username. Do not append the realm to it.
Then import the number you want to originate from, exactly as you did for inbound, using this credential's id as the credentialId.
Place a test call
curl -X POST https://api.vapi.ai/call \
-H "Authorization: Bearer $VAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumberId": "<your-phone-number-id>",
"assistantId": "<your-assistant-id>",
"customer": { "number": "+19195551234" }
}'
The destination should ring, with your Bandwidth number as the caller ID, and your assistant should start talking when the call is answered.
Inbound and outbound are configured independently. Inbound needs a gateway entry with your numeric signaling IP and inboundEnabled: true; outbound needs one with the realm hostname and inboundEnabled: false. A single Vapi credential can hold more than one gateway entry, so one credential can cover both directions — confirm the combined configuration behaves the way you expect on your own account before relying on it in production.
Troubleshooting
| Symptom | Likely cause | What to check |
|---|---|---|
| Call does not connect, and Vapi shows no record of it | Vapi does not recognize your source IP, so it challenges the call with 401 Unauthorized and a digest challenge that Bandwidth has no credentials to answer | Confirm the gateway ip on your Vapi credential matches your trunk's signaling (Orig/Term) IP exactly, with inboundEnabled: true. This is the most common failure. |
Caller hears a failure and Bandwidth reports 550 Server Failure | Usually a downstream symptom of the 401 above rather than a separate problem | Fix the gateway IP first, then retest before investigating Bandwidth-side routing. |
| Calls connect sometimes and fail other times | Your trunks are deployed across more than one SBC, and only one address is registered | Check Account → Trunk Group Configurations for every signaling IP your trunks use and add a gateway entry for each, or widen the netmask. |
| A working integration stops accepting calls | Your trunk group was migrated to a different SBC, so its signaling IP changed | Re-check Account → Trunk Group Configurations and update the gateway ip on your Vapi credential to match. |
| Inbound calls never leave Bandwidth | Voice Configuration Package misrouted, or the number isn't assigned | Confirm the package uses Route to Domain Name with your {credential_id}.sip.vapi.ai FQDN, that the number is assigned to that package, and that inbound voice is activated on the number. |
| Vapi receives the call but rejects the destination | Wrong endpoint or region | Confirm the FQDN's {credential_id} matches the credential you imported the number against, and that the region matches (.sip.vapi.ai vs .sip.eu.vapi.ai). |
Outbound calls fail with 500 Server Internal Error | Bandwidth can't attribute the call to an account — usually no SIP credential on the request, or the account isn't enabled for SIP credentials | Confirm the realm and credential exist, that outboundAuthenticationPlan is set on the Vapi credential, and that the gateway points at the realm hostname. |
Outbound calls rejected with 403 or repeated 407 | Credential or realm mismatch | Check that authUsername is the bare username with no realm appended, that the password matches, and that the gateway hostname is the realm's exact hostname. |
| Outbound connects but the caller ID is rejected | The originating number isn't owned by the same account as the realm | Use a number on the same account as the realm and credential. |
FAQ
Do I need to write or host any code? No. This integration is entirely configuration: a Voice Configuration Package on Bandwidth and a SIP trunk credential plus an imported number on Vapi.
Why does Vapi need my Bandwidth IP address? Vapi authorizes inbound SIP traffic by source IP. Registering your trunk's signaling IP as a gateway is what lets Vapi trust and accept calls from your Bandwidth trunk instead of challenging them.
Can my Vapi assistant place outbound calls through Bandwidth? Yes — see Configure outbound calls. Outbound authenticates with SIP digest credentials against a Bandwidth SIP realm rather than by IP address, so it needs a realm and credential in addition to your inbound setup.
Why does outbound use credentials when inbound uses an IP address? They're enforced by different sides. Vapi decides whether to accept your inbound calls, and it matches on source IP. Bandwidth decides whether to accept Vapi's outbound calls, and Vapi originates from shared infrastructure — so a credential, which identifies your account regardless of source IP, is the appropriate control.
Should I use this or Programmable Voice? Use this guide when you want Vapi to own the whole conversation with no application to host. If you want to build and control the audio pipeline yourself, use Pipecat or Cartesia with Programmable Voice and Media Streaming instead.
Resources
- Create a Voice Configuration Package — Bandwidth
- How to set up SIP Registration — Bandwidth realms and SIP credentials
- Vapi SIP trunking documentation — Vapi
- Vapi SIP networking and firewall configuration — Vapi
- Vapi SIP trunk credential troubleshooting — Vapi