Getting Started
This guide walks you through running the adapter, configuring it, and pointing your Twilio app at it without making a single code change to your application.
Set up your Bandwidth account
You'll need a Bandwidth Account with Voice enabled, API Credentials, and a voice application before running the adapter.
- Don't have an account yet? Start a free trial of Bandwidth Build.
- Set up your API Credentials.
- Make sure you have a voice application ID.
Run the adapter
Clone the repository and install dependencies (Node.js 20+):
git clone https://github.com/Bandwidth/bw-voice-adapter.git
cd bw-voice-adapter
npm install
Start the adapter:
npm start # adapter listens on :3000
To run the test suite or typecheck:
npm test # automated tests
npm run typecheck
Configure
The adapter is configured entirely through environment variables. Two credential sets are in play: the Twilio-shaped credentials your app presents to the adapter, and the Bandwidth credentials the adapter uses to reach Bandwidth.
| Env var | Meaning |
|---|---|
PUBLIC_BASE_URL | Public HTTPS base of this adapter (how Bandwidth and your app reach it) |
CUSTOMER_VOICE_URL | Your Twilio voice webhook — where the adapter asks "what now?" for inbound calls |
ADAPTER_ACCOUNT_SID / ADAPTER_AUTH_TOKEN | What your Twilio SDK and webhook-signature validation use |
BW_ACCOUNT_ID | Your Bandwidth account ID |
BW_CLIENT_ID / BW_CLIENT_SECRET | Bandwidth OAuth2 client credentials (used to reach the Bandwidth Voice API) |
BW_APPLICATION_ID | Your Bandwidth Voice application ID |
WEBHOOK_USER / WEBHOOK_PASSWORD | Basic-auth credentials Bandwidth presents on inbound /bw/* webhooks; set the same values as the CallbackCreds on your Bandwidth Voice application |
Optional:
| Env var | Meaning |
|---|---|
HOST | Listen interface; defaults to 127.0.0.1. Set 0.0.0.0 to expose the adapter (containers/production) |
EGRESS_ALLOW_PRIVATE=1 | Allow outbound fetches to loopback/private ranges (local dev only) |
BW_ENVIRONMENT | test targets Bandwidth's test hosts; defaults to prod |
ADAPTER_LOG=1 | Enable request logging |
The adapter keeps call and recording state in memory and runs as a single instance. A recording must be listed before it can be fetched by SID on a fresh instance.
Point your app at the adapter
No application code changes — only configuration:
- Point your Twilio SDK / base URL at the adapter. Backend calls your app makes (
calls.create(), recording fetches) now resolve through the adapter's Twilio-compatible facade atPUBLIC_BASE_URL. - Point your TwiML webhooks at the adapter. The URLs your voice logic serves (inbound call handler,
Gatheractions) are what the adapter fetches as it translates each step. - Point a Bandwidth Voice application callback at
{PUBLIC_BASE_URL}/bw/initiate. This is how Bandwidth hands inbound calls to the adapter to begin translation. The Bandwidth Voice application'sCallbackCredsmust matchWEBHOOK_USER/WEBHOOK_PASSWORD, or the adapter will reject the callbacks with401.
Run your existing app unchanged. Its calls now flow over Bandwidth's network.
Verify before you cut over
Before pointing production traffic at the adapter, run a pre-flight check to see which features map cleanly and which need attention:
npm run preflight -- examples/full-pv-app
This prints a migration-complexity score and a per-feature works-as-is / heads-up / blocker breakdown. Swap in a path to your own app to check your real TwiML.
For a walkthrough of migration patterns, the REST facade, callbacks, and the Migration Preflight playground, see the use cases guide.