Twilio Integration

Configure Twilio for global voice agent calls with WebSocket streaming.

2 min read

Twilio is the most widely-used cloud communications platform, offering excellent global coverage and robust APIs.

Why Twilio?#

  • Global Coverage: 180+ countries
  • Excellent Documentation: Best-in-class developer experience
  • Native WebSocket: First-class streaming support via Media Streams

Prerequisites#

  1. Twilio account (sign up at twilio.com)
  2. A phone number capable of voice calls
  3. 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"
  }
}

Need your workspace ID? See Finding Your Workspace ID.

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#

  1. Verify your domain has valid SSL certificate
  2. Check Twilio console for error logs
  3. Ensure WebSocket endpoint is publicly accessible

Audio Quality Issues#

  1. Verify μ-law encoding/decoding is correct
  2. Check for sample rate mismatches
  3. Monitor WebSocket latency

Call Not Initiating#

  1. Verify Account SID and Auth Token
  2. Check phone number format (E.164: +1234567890)
  3. Ensure account has sufficient balance

Next Steps#

Was this page helpful?