Twilio Integration
Twilio is the most widely-used cloud communications platform, offering excellent global coverage and robust APIs.
Why Twilio?
- Global Coverage: 180+ countries
- Reliable Infrastructure: 99.95% uptime SLA
- Excellent Documentation: Best-in-class developer experience
- Native WebSocket: First-class streaming support via Media Streams
Prerequisites
- Twilio account (sign up at twilio.com)
- A phone number capable of voice calls
- Account SID and Auth Token
Configuration
Environment Variables
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token_here
TWILIO_PHONE_NUMBER=+1234567890
TwiML Configuration
For inbound calls, configure your Twilio phone number's webhook to return TwiML that connects to your WebSocket:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Connect>
<Stream url="wss://your-domain.com/agent/{agentId}/user/{userId}/">
<Parameter name="agentId" value="{agentId}"/>
</Stream>
</Connect>
</Response>
Call Flows
Inbound Call Flow
1. Caller dials your Twilio number
↓
2. Twilio requests TwiML from your webhook
↓
3. Your server returns TwiML with <Stream> element
↓
4. Twilio connects WebSocket to specified URL
↓
5. Bidirectional audio streaming begins
↓
6. Voice agent handles conversation
Outbound Call Flow
1. POST /make-call with agent_id, phone_number
↓
2. TwilioMakeCall() builds TwiML with WebSocket URL
↓
3. POST to Twilio API to initiate call
↓
4. Twilio dials recipient
↓
5. On answer, Twilio connects to WebSocket
↓
6. Voice agent handles conversation
API Reference
Make Outbound Call
POST /make-call
Content-Type: application/json
{
"agent_id": "123",
"phone_number": "+1234567890",
"workspace_id": "ws_456",
"call_provider": "twilio",
"variables": {
"customer_name": "John Doe",
"order_id": "ORD-12345"
}
}
Response:
{
"status": "success",
"call_sid": "CAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
WebSocket Message Format
Twilio uses camelCase for message fields:
Connected Message:
{
"event": "connected",
"protocol": "Call",
"version": "1.0.0"
}
Start Message:
{
"event": "start",
"sequenceNumber": "1",
"start": {
"streamSid": "MZxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"callSid": "CAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"accountSid": "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"tracks": ["inbound"],
"customParameters": {
"agentId": "123"
}
},
"streamSid": "MZxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Media Message (from Twilio):
{
"event": "media",
"sequenceNumber": "2",
"media": {
"track": "inbound",
"chunk": "1",
"timestamp": "5",
"payload": "base64_encoded_mulaw_audio..."
},
"streamSid": "MZxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Media Response (to Twilio):
{
"event": "media",
"streamSid": "MZxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"media": {
"payload": "base64_encoded_mulaw_audio..."
}
}
Clear Buffer:
{
"event": "clear",
"streamSid": "MZxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Audio Specifications
| Parameter | Value |
|---|---|
| Sample Rate | 8000 Hz |
| Channels | Mono |
| Encoding | μ-law (mulaw) |
| Chunk Size | ~20ms per frame |
Audio Conversion
Twilio uses μ-law encoding. Convert to/from Linear PCM:
// μ-law to Linear PCM
func mulawToLinear(mulaw byte) int16 {
mulaw = ^mulaw
sign := (mulaw & 0x80) >> 7
exponent := (mulaw & 0x70) >> 4
mantissa := mulaw & 0x0F
sample := ((int16(mantissa) << 3) + 0x84) << exponent
sample -= 0x84
if sign == 1 {
return -sample
}
return sample
}
Recording
Enable call recording in your TwiML or API call:
payload.Set("Record", "true")
payload.Set("RecordingStatusCallback", "https://your-domain.com/api/webhooks/telephony/twilio")
Status Webhooks
Configure status callback URL to receive call events:
POST /api/webhooks/telephony/twilio
Content-Type: application/x-www-form-urlencoded
CallSid=CAxxxxxxxxx&
CallStatus=completed&
Duration=120&
RecordingUrl=https://api.twilio.com/...
Pricing
| Region | Outbound/min | Inbound/min |
|---|---|---|
| US/Canada | $0.014 | $0.0085 |
| UK | $0.045 | $0.0085 |
| India | $0.025 | $0.0085 |
Prices as of 2024. Check Twilio Pricing for current rates.
Troubleshooting
WebSocket Not Connecting
- Verify your domain has valid SSL certificate
- Check Twilio console for error logs
- Ensure WebSocket endpoint is publicly accessible
Audio Quality Issues
- Verify μ-law encoding/decoding is correct
- Check for sample rate mismatches
- Monitor WebSocket latency
Call Not Initiating
- Verify Account SID and Auth Token
- Check phone number format (E.164: +1234567890)
- Ensure account has sufficient balance
Next Steps
- Exotel Integration - Alternative for India
- STT Configuration - Optimize speech recognition
- Latency Optimization - Reduce response time