SMS and WhatsApp through a Twilio number or Messaging Service.
Install
Terminal
npx shadcn@latest add @tendkit/channel-twilioIt lands in lib/support/channels/. Import twilioChannel from there.
Set up
Get a number
Buy a number, or connect a WhatsApp sender, in the Twilio Console.
Point incoming messages at your webhook
Under "A message comes in", set the channel's webhook URL with POST, and pass the exact same URL as
webhookUrl: Twilio signs it character for character.Create an API key
Account → API keys. Pass it as apiKeySid and apiKeySecret; keep authToken for webhook signatures.
Configure
lib/support/index.ts
twilioChannel({
id: "whatsapp",
accountSid: process.env.TWILIO_ACCOUNT_SID!,
authToken: process.env.TWILIO_AUTH_TOKEN!,
apiKeySid: process.env.TWILIO_API_KEY_SID!,
apiKeySecret: process.env.TWILIO_API_KEY_SECRET!,
from: "whatsapp:+14155550133", // or "+14155550133" for SMS
webhookUrl: "https://acme.com/api/webhooks/support/whatsapp",
})Options
| Name | Type | Description |
|---|---|---|
id* | string | Stable channel id, stored on every ticket and used in the webhook URL. Never change it. |
accountSid* | string | "AC…". |
authToken* | string | The primary Auth Token. Twilio signs webhooks with it. |
apiKeySid / apiKeySecret | string | An API key for REST calls; recommended over the Auth Token. |
from* | string | The number: "+14155550133" for SMS, "whatsapp:+14155550133" for WhatsApp. |
messagingServiceSid | string | Send through a Messaging Service instead of from. |
webhookUrl* | string | The exact public URL configured in Twilio. |
statusCallbackUrl | string | Where delivery updates go. Defaults to webhookUrl. |
address | string | Shown to agents. Defaults to from without the whatsapp: prefix. |
Behaviour
- SMS: no attachments, 1,600 characters, billed per segment. Two-way SMS isn't available in every country; check Twilio's guidelines for yours.
- WhatsApp: replies are allowed for 24 hours after the customer's last message. After that the composer explains why it can't send.