Getting Started
This guide walks you through running the translator, 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 translator.
- 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 translator
Clone the repository and install dependencies (Node.js 20+):
git clone https://github.com/Bandwidth/migration-toolkit.git
cd migration-toolkit
npm install
Start the translator:
npm start # translator listens on :3000
To run the test suite or typecheck:
npm test # automated tests
npm run typecheck
Configure
The translator is configured entirely through environment variables. Two credential sets are in play: the Twilio-shaped credentials your app presents to the translator, and the Bandwidth credentials the translator uses to reach Bandwidth.
| Env var | Meaning |
|---|---|
PUBLIC_BASE_URL | Public HTTPS base of the translator (how Bandwidth and your app reach it) |
CUSTOMER_VOICE_URL | Your Twilio voice webhook — where the translator 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 translator (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 translator 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 translator
No application code changes — only configuration:
- Point your Twilio SDK / base URL at the translator. Backend calls your app makes (
calls.create(), recording fetches) now resolve through the translator's Twilio-compatible facade atPUBLIC_BASE_URL. - Point your TwiML webhooks at the translator. The URLs your voice logic serves (inbound call handler,
Gatheractions) are what the translator 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 translator to begin translation. The Bandwidth Voice application'sCallbackCredsmust matchWEBHOOK_USER/WEBHOOK_PASSWORD, or the translator 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 translator, run a Compatibility Check to see which features map cleanly and which need attention:
npm run compatibility-check -- 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 Compatibility Check playground, see the use cases guide.