Skip to main content

Why ngrok is Required

Twilio, Vonage, and Exotel use a two-step call setup:
  1. They send an HTTP POST webhook to your server when a call arrives
  2. They open a WebSocket to your server to stream bidirectional audio
Both connections come from the provider’s cloud to your machine. During local development your machine is not publicly reachable, so you need ngrok to create an HTTPS tunnel.
Twilio/Vonage/Exotel cloud


ngrok tunnel (https://xyz.ngrok.io)


localhost:8080  →  Nginx  →  assistant-api:9007
You need a single ngrok tunnel pointing to port 8080 (the Nginx gateway). All webhook and WebSocket traffic flows through Nginx and is proxied to assistant-api.

Prerequisites

ToolVersionInstall
ngrokv3+ngrok.com/download
Rapida stackrunningmake up-all

Step-by-Step Setup

1

Install and authenticate ngrok

# macOS (Homebrew)
brew install ngrok/ngrok/ngrok

# Linux
curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list
sudo apt update && sudo apt install ngrok
Sign in and set your authtoken (required for stable subdomains):
ngrok config add-authtoken <your-authtoken>
Get your authtoken at dashboard.ngrok.com/get-started/your-authtoken.
2

Start the tunnel

ngrok http 8080
ngrok outputs a forwarding URL like:
Forwarding  https://abc123.ngrok-free.app -> http://localhost:8080
Copy the https:// URL — this is your PUBLIC_ASSISTANT_HOST.
The free tier generates a random URL on each restart. To get a stable URL across restarts, use a paid ngrok plan with a reserved domain.
3

Update PUBLIC_ASSISTANT_HOST in assistant-api

Edit docker/assistant-api/.assistant.env:
# Replace with your ngrok hostname (without https://)
PUBLIC_ASSISTANT_HOST=abc123.ngrok-free.app
4

Update media URL in the UI config

Edit ui/src/configs/config.development.json:
{
    "connection": {
        "assistant": "http://localhost:8080",
        "web": "http://localhost:8080",
        "endpoint": "http://localhost:8080",
        "media": "https://abc123.ngrok-free.app",
        "socket": "localhost:4573",
        "sip": "localhost:5060"
    }
}
The media field is the public URL the browser and telephony providers use for WebSocket connections.
5

Restart assistant-api and the UI

make rebuild-assistant   # Picks up the new PUBLIC_ASSISTANT_HOST
If running the UI in development mode:
cd ui && yarn start:dev
6

Verify the tunnel is proxying correctly

curl https://abc123.ngrok-free.app/readiness/
# Expected: {"status":"ok"} or similar
You can also check the ngrok web inspector at http://localhost:4040 to see incoming requests in real time.

Configuring Twilio for Local Testing

With ngrok running, point your Twilio phone number’s webhook to:
POST https://abc123.ngrok-free.app/v1/talk/twilio/call/{your-assistant-id}
  1. Open Twilio Console → Phone Numbers → Active Numbers
  2. Select your number
  3. Under Voice Configuration, set:
FieldValue
A call comes inWebhook
URLhttps://abc123.ngrok-free.app/v1/talk/twilio/call/{assistantId}
HTTP MethodPOST
  1. Call the number — Twilio posts the webhook to ngrok, which forwards to your local assistant-api

Configuring Vonage for Local Testing

Point your Vonage Application’s Answer URL to:
POST https://abc123.ngrok-free.app/v1/talk/vonage/call/{your-assistant-id}
  1. Open Vonage Dashboard → Applications → select your app
  2. Under Capabilities → Voice → Answer URL, set the URL above
  3. Set Event URL to: https://abc123.ngrok-free.app/v1/talk/vonage/ctx/{contextId}/event

Configuring Exotel for Local Testing

In your Exotel App (applet), set the webhook URL to:
https://abc123.ngrok-free.app/v1/talk/exotel/call/{your-assistant-id}

Two Configurations Always Need Updating

When your ngrok URL changes (e.g., after a free-tier restart), update both of these:
FileFieldValue
docker/assistant-api/.assistant.envPUBLIC_ASSISTANT_HOSTabc123.ngrok-free.app (no https://)
ui/src/configs/config.development.jsonconnection.mediahttps://abc123.ngrok-free.app (with https://)
Then restart:
make rebuild-assistant
# restart UI if needed: cd ui && yarn start:dev

Using a random URL is inconvenient for team development since the webhook URL in Twilio/Vonage must be updated every time ngrok restarts. Options for a stable URL:
OptionDescription
ngrok reserved domainPaid ngrok plan — assign a fixed subdomain
ngrok static domainFree tier offers one free static domain: ngrok http --domain=your-name.ngrok-free.app 8080
Cloudflare TunnelFree alternative — cloudflared tunnel --url http://localhost:8080
With a static/reserved domain, you set the webhook URL in Twilio/Vonage once and never update it.

Troubleshooting

The Rapida stack is not running. Verify:
make status      # All containers should show "Up"
make logs-all    # Check for startup errors
PUBLIC_ASSISTANT_HOST is still set to the old ngrok URL or to localhost. Update it to the new ngrok hostname and run make rebuild-assistant.
The tunnel is not running. Start it again:
ngrok http 8080
And update both PUBLIC_ASSISTANT_HOST and connection.media with the new URL.
Twilio requires HTTPS. ngrok provides HTTPS automatically. Do not use the http:// version of the URL — always use the https://abc123.ngrok-free.app URL in Twilio’s console.

Next Steps