The Twilio provider integrates BuilderBot with Twilio’s programmable messaging service, enabling SMS and WhatsApp messaging through Twilio’s infrastructure.
Features
SMS messaging
WhatsApp messaging via Twilio
Media messages (MMS)
Reliable message delivery
Message status tracking
Webhook support
Multi-channel support
Enterprise-grade infrastructure
Prerequisites
Get Phone Number
Purchase a Twilio phone number with SMS/MMS capabilities
Get Credentials
From your Twilio Console, obtain:
Account SID
Auth Token
Twilio Phone Number
Configure Webhook
Set up webhook URL for incoming messages
Installation
npm install @builderbot/bot @builderbot/provider-twilio
Configuration
Basic Setup
import { createBot , createProvider , createFlow } from '@builderbot/bot'
import { TwilioProvider } from '@builderbot/provider-twilio'
import { MemoryDB } from '@builderbot/bot'
const provider = createProvider ( TwilioProvider , {
accountSid: 'YOUR_ACCOUNT_SID' ,
authToken: 'YOUR_AUTH_TOKEN' ,
vendorNumber: '+14155238886' , // Your Twilio number
port: 3000
})
const { handleCtx , httpServer } = await createBot ({
flow: adapterFlow ,
provider: provider ,
database: new MemoryDB (),
})
httpServer ( 3000 )
Environment Variables
TWILIO_ACCOUNT_SID=your_account_sid
TWILIO_AUTH_TOKEN=your_auth_token
TWILIO_PHONE_NUMBER=+14155238886
TWILIO_PUBLIC_URL=https://your-domain.com
PORT=3000
const provider = createProvider ( TwilioProvider , {
accountSid: process . env . TWILIO_ACCOUNT_SID ,
authToken: process . env . TWILIO_AUTH_TOKEN ,
vendorNumber: process . env . TWILIO_PHONE_NUMBER ,
publicUrl: process . env . TWILIO_PUBLIC_URL , // For media files
port: parseInt ( process . env . PORT ) || 3000
})
Configuration Options
interface TwilioProviderArgs {
accountSid : string // Required: Twilio Account SID
authToken : string // Required: Twilio Auth Token
vendorNumber : string // Required: Your Twilio phone number
publicUrl ?: string // Public URL for media hosting
name ?: string // Bot name (default: 'bot')
port ?: number // Server port (default: 3000)
writeMyself ?: string // Options: 'none', 'both', 'host'
}
Basic Usage
Sending Text Messages
import { addKeyword } from '@builderbot/bot'
const welcomeFlow = addKeyword ([ 'hi' , 'hello' ])
. addAnswer ( 'Hello! Welcome to our service' )
. addAnswer ( 'How can we help you today?' )
const mediaFlow = addKeyword ( 'media' )
// Send image from public URL
. addAnswer ( 'Here is an image:' , {
media: 'https://example.com/image.jpg'
})
// Send video
. addAnswer ( 'Check this video:' , {
media: 'https://example.com/video.mp4'
})
For local files, you need to provide a public URL. The provider can help expose local files via the /tmp endpoint, but this requires proper configuration of publicUrl.
Public URL Requirement
Twilio requires media to be accessible via public HTTPS URLs:
const provider = createProvider ( TwilioProvider , {
accountSid: process . env . TWILIO_ACCOUNT_SID ,
authToken: process . env . TWILIO_AUTH_TOKEN ,
vendorNumber: process . env . TWILIO_PHONE_NUMBER ,
publicUrl: 'https://your-domain.com' // Required for local files
})
Sending Local Files
When sending local files, the provider automatically creates a temporary public endpoint:
const localFileFlow = addKeyword ( 'file' )
. addAnswer ( 'Sending local file...' , {
media: './assets/document.pdf'
})
// Provider converts to: https://your-domain.com/tmp?path=encrypted_path
const sendMediaFlow = addKeyword ( 'image' )
. addAction ( async ( ctx , { provider }) => {
await provider . sendMedia (
ctx . from ,
'Check out this image!' ,
'https://example.com/image.jpg'
)
})
import { join } from 'path'
const receiveMediaFlow = addKeyword ( 'MEDIA' )
. addAction ( async ( ctx , { provider , flowDynamic }) => {
const filePath = await provider . saveFile ( ctx , {
path: join ( process . cwd (), 'downloads' )
})
await flowDynamic ( `File saved: ${ filePath } ` )
})
Advanced Features
Direct Twilio API Access
You can access the Twilio client directly:
const advancedFlow = addKeyword ( 'advanced' )
. addAction ( async ( ctx , { provider }) => {
await provider . send (
ctx . from ,
'Custom message' ,
{
statusCallback: 'https://your-domain.com/status' ,
provideFeedback: true
}
)
})
Message Options
const optionsFlow = addKeyword ( 'options' )
. addAction ( async ( ctx , { provider }) => {
await provider . send (
ctx . from ,
'Message with options' ,
{
statusCallback: 'https://your-domain.com/callback' ,
maxPrice: '0.05' ,
validityPeriod: 600 , // 10 minutes
forceDelivery: true
}
)
})
WhatsApp via Twilio
To use WhatsApp with Twilio:
const provider = createProvider ( TwilioProvider , {
accountSid: process . env . TWILIO_ACCOUNT_SID ,
authToken: process . env . TWILIO_AUTH_TOKEN ,
vendorNumber: 'whatsapp:+14155238886' , // Twilio WhatsApp number
publicUrl: process . env . TWILIO_PUBLIC_URL
})
Send messages to WhatsApp numbers:
await bot . sendMessage (
'whatsapp:+1234567890' ,
'Hello from WhatsApp!'
)
Webhook Configuration
Webhook Endpoints
The provider exposes these endpoints:
POST / - Home endpoint
POST /webhook - Receive incoming messages
GET /tmp - Serve local media files
Twilio Console Setup
Go to your Twilio phone number settings
Set “A MESSAGE COMES IN” webhook:
https://your-domain.com/webhook
HTTP POST
Save configuration
Ngrok for Development
For local development, use ngrok:
Then set the ngrok URL in Twilio and your config:
const provider = createProvider ( TwilioProvider , {
accountSid: process . env . TWILIO_ACCOUNT_SID ,
authToken: process . env . TWILIO_AUTH_TOKEN ,
vendorNumber: process . env . TWILIO_PHONE_NUMBER ,
publicUrl: 'https://your-subdomain.ngrok.io'
})
Event Handling
Ready Event
provider . on ( 'ready' , () => {
console . log ( 'Twilio provider is ready!' )
})
provider . on ( 'host' , ( host ) => {
console . log ( 'Connected with number:' , host . phone )
})
Error Handling
provider . on ( 'auth_failure' , ( error ) => {
console . error ( 'Twilio auth failed:' , error )
})
The provider automatically formats phone numbers:
// All these formats work:
await bot . sendMessage ( '+1234567890' , 'Hello' )
await bot . sendMessage ( '1234567890' , 'Hello' )
await bot . sendMessage ( 'whatsapp:+1234567890' , 'Hello' )
Best Practices
Implement status callbacks for delivery tracking
Handle failed messages gracefully
Set appropriate validity periods
Monitor Twilio console for delivery issues
Monitor message usage in Twilio console
Set maxPrice to prevent unexpected costs
Use WhatsApp when possible (lower cost)
Implement message queuing for bulk sends
Never commit credentials to version control
Use environment variables for all secrets
Validate webhook requests from Twilio
Use HTTPS in production
Troubleshooting
Verify Account SID and Auth Token are correct
Check credentials haven’t expired
Ensure account is active and funded
Verify webhook URL is publicly accessible
Check URL is configured in Twilio console
Test with ngrok for local development
Review Twilio webhook debugger
If you see a warning about local files, ensure:
publicUrl is set in configuration
Your server is publicly accessible
Port is open in firewall
HTTPS is configured (production)
Example: Complete Bot
import { createBot , createProvider , createFlow , addKeyword } from '@builderbot/bot'
import { TwilioProvider } from '@builderbot/provider-twilio'
import { MemoryDB } from '@builderbot/bot'
const welcomeFlow = addKeyword ([ 'hi' , 'hello' , 'start' ])
. addAnswer ( '👋 Hello! Welcome to our service' )
. addAnswer (
'How can we help you?' ,
{ capture: true },
async ( ctx , { flowDynamic }) => {
await flowDynamic ( `You said: ${ ctx . body } ` )
}
)
const mediaFlow = addKeyword ( 'image' )
. addAnswer ( 'Here is an image:' , {
media: 'https://example.com/image.jpg'
})
const main = async () => {
const adapterFlow = createFlow ([ welcomeFlow , mediaFlow ])
const adapterProvider = createProvider ( TwilioProvider , {
accountSid: process . env . TWILIO_ACCOUNT_SID ,
authToken: process . env . TWILIO_AUTH_TOKEN ,
vendorNumber: process . env . TWILIO_PHONE_NUMBER ,
publicUrl: process . env . TWILIO_PUBLIC_URL
})
const adapterDB = new MemoryDB ()
const { handleCtx , httpServer } = await createBot ({
flow: adapterFlow ,
provider: adapterProvider ,
database: adapterDB ,
})
httpServer ( 3000 )
}
main ()
Pricing Considerations
SMS: Varies by country (~$0.0075/message in US)
WhatsApp: Lower cost than SMS in most regions
MMS: Higher cost than SMS (~$0.02/message)
Check Twilio Pricing for details
Further Resources