Twilio Setup Guide
Twilio is the global telephony provider for KaiVox — handling voice calls, inbound SMS, and WhatsApp messages for non-Indian numbers. Configuration is platform-level: one set of credentials handles all tenants.
Architecture note: Twilio credentials are set in
.env at the platform level. Individual tenants are identified by their {slug} in the webhook URL — not by separate Twilio accounts. One Twilio account, many tenants.Environment Variables
| Key | Where to Find | Required |
|---|---|---|
TWILIO_ACCOUNT_SID | Twilio Console → Account Info (starts with AC…) | ✅ Yes |
TWILIO_AUTH_TOKEN | Twilio Console → Account Info | ✅ Yes |
TWILIO_FROM_NUMBER | Twilio Console → Phone Numbers → your purchased number | ✅ Yes (for outbound SMS/WhatsApp) |
.env example
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token_here
TWILIO_FROM_NUMBER=+12025551234
Webhook URLs
Configure these URLs in the Twilio Console under your phone number settings. Replace {slug} with the tenant's slug.
| Webhook | Method | URL |
|---|---|---|
| Voice — Answer | POST | https://kaivoxai.com/api/twilio/{slug}/answer |
| Voice — Gather (Input) | POST | https://kaivoxai.com/api/twilio/{slug}/gather |
| Voice — Status Callback | POST | https://kaivoxai.com/api/twilio/{slug}/status |
| Inbound SMS | POST | https://kaivoxai.com/api/twilio/{slug}/sms |
| Inbound WhatsApp | POST | https://kaivoxai.com/api/twilio/{slug}/whatsapp |
All webhook endpoints are CSRF-exempt. Twilio does not send CSRF tokens. The routes are registered under
routes/api.php which bypasses CSRF middleware automatically.Voice Call Setup
-
Purchase a Twilio phone number In the Twilio Console, go to Phone Numbers → Manage → Buy a Number. Choose a country and number type. You can also use KaiVox's built-in DID Marketplace (Phase 16) which purchases and configures Twilio numbers automatically.
-
Configure the Voice webhook In Twilio Console → Phone Numbers → click your number. Under "Voice & Fax", set:
- A Call Comes In: Webhook →
POST https://kaivoxai.com/api/twilio/{slug}/answer - Call Status Changes:
POST https://kaivoxai.com/api/twilio/{slug}/status
- A Call Comes In: Webhook →
-
Save and test Call the Twilio number. KaiVox AI should answer with the tenant's greeting.
SMS Inbound Webhook Setup
-
Open phone number settings in Twilio Console Navigate to Phone Numbers → your number.
-
Set the Messaging webhook Under "Messaging", set:
- A Message Comes In: Webhook →
POST https://kaivoxai.com/api/twilio/{slug}/sms
- A Message Comes In: Webhook →
-
Verify in KaiVox Send an SMS to the number. It should appear in the tenant's unified inbox under Messages.
WhatsApp Inbound Webhook Setup
Twilio WhatsApp requires either a Twilio Sandbox (for testing) or an approved WhatsApp Business Account (for production). The sandbox is free and ready to use immediately.
-
Enable Twilio WhatsApp Sandbox In Twilio Console, go to Messaging → Try it out → Send a WhatsApp message. Follow the instructions to join the sandbox from your WhatsApp.
-
Set the sandbox webhook In the sandbox settings, set:
- When a message comes in:
POST https://kaivoxai.com/api/twilio/{slug}/whatsapp
- When a message comes in:
-
Production WhatsApp Apply for a WhatsApp Business Account in Twilio. Once approved, configure the same webhook URL on your approved WhatsApp number.
What KaiVox Does With Inbound SMS/WhatsApp
When an inbound message arrives:
- The tenant is resolved from the
{slug}in the URL - The sender's phone number is looked up in the
customerstable — created if new - The message is stored in the
messagestable withchannel = smsorchannel = whatsapp - The
inbound_smsorinbound_whatsappautomation trigger fires — any matching rules execute - The message appears in the tenant's unified inbox at Messages in the sidebar
Outbound SMS — SmsService
KaiVox sends outbound SMS via App\Services\SmsService which wraps the Twilio SDK. Used for:
- Appointment booking confirmations
- 24-hour appointment reminders
- Missed-call follow-up messages
- Review request messages
- Manual SMS from the CRM (Customers page)
- Automation rule actions (
send_sms)
How SmsService sends a message
// From any controller or service:
app(SmsService::class)->send(
tenant: $tenant,
to: '+919876543210',
message: 'Your appointment is confirmed for 2pm tomorrow.'
);
Outbound WhatsApp — WhatsAppService
App\Services\WhatsAppService works identically to SmsService but prefixes the to-number with whatsapp: for Twilio routing. The TWILIO_FROM_NUMBER must be a WhatsApp-enabled number.
Call Flow (Twilio)
Caller dials Twilio number
↓
Twilio POST → /api/twilio/{slug}/answer
↓
KaiVox returns TwiML — <Gather> with <Say> greeting
↓
Caller speaks
↓
Twilio POST → /api/twilio/{slug}/gather (with SpeechResult)
↓
KaiVox: sends to OpenAI → gets response → returns TwiML with <Say>
↓
[Continues until hangup]
↓
Twilio POST → /api/twilio/{slug}/status (CallStatus=completed)
↓
KaiVox: saves call log, runs sentiment, triggers automations
Troubleshooting Twilio
| Problem | Likely Cause | Fix |
|---|---|---|
| Call goes to voicemail | Webhook URL not set or wrong | Check Twilio Console → Phone Number → Voice webhook URL |
| SMS not received in inbox | Messaging webhook not configured | Set Messaging webhook URL in Twilio Console |
| WhatsApp message not received | Sandbox join not completed | Ask sender to join sandbox first (send "join <code>" to Twilio sandbox number) |
| Outbound SMS fails | Invalid TWILIO_FROM_NUMBER | Ensure number is in E.164 format: +12025551234 |
| 401 Unauthorized in logs | Wrong TWILIO_AUTH_TOKEN | Copy token fresh from Twilio Console — it may have rotated |