Twilio
Category: Notification — SMS
Package: @leadmetrics/provider-sms → TwilioProvider
External SDK: twilio
Purpose
Twilio is the tenant-configurable SMS provider for international markets. While MSG91 is the platform default optimised for India, tenants serving international clients (or Indian tenants with their own Twilio account) can use Twilio for SMS delivery. Messages arrive from the tenant’s own Twilio phone number, giving them full control over their SMS identity.
There is no platform Twilio default — the platform uses MSG91 as the SMS default. Twilio is only used when a tenant has configured and verified it.
Config Structure
Tenant config (stored in notification_providers.config, encrypted)
interface TwilioConfig {
accountSid: string; // Twilio Account SID (ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
authToken: string; // Twilio Auth Token
fromNumber: string; // E.164 Twilio number, e.g. "+61412345678" or "+14155552671"
// Must be a purchased Twilio number or verified caller ID
}Integration Pattern
Provider class (packages/provider-sms/src/providers/twilio.ts)
import twilio from 'twilio';
class TwilioProvider implements SmsProvider {
readonly name = 'twilio';
private client: twilio.Twilio;
constructor(
private accountSid: string,
private authToken: string,
private fromNumber: string,
) {
this.client = twilio(accountSid, authToken);
}
async send(message: SmsMessage): Promise<SmsSendResult> {
const result = await this.client.messages.create({
from: this.fromNumber,
to: message.to, // E.164, e.g. "+919876543210"
body: message.body,
});
if (result.errorCode) {
throw new Error(`Twilio error ${result.errorCode}: ${result.errorMessage}`);
}
return {
messageId: result.sid,
provider: 'twilio',
status: result.status, // 'queued' | 'sent' | 'delivered' | 'failed'
};
}
async verify(): Promise<void> {
// Verify credentials by fetching account info
await this.client.api.accounts(this.accountSid).fetch();
}
}Message status
Twilio returns a status of queued at dispatch time. Final delivery status (delivered, failed) arrives via Twilio’s status callback webhook. The platform logs the initial queued status in notification_dispatch_log. Delivery tracking via webhooks is a future enhancement.
Twilio Messaging Services vs Direct Numbers
The platform uses direct phone numbers (fromNumber) rather than Messaging Services. Messaging Services offer features like sticky sender (same number for the same recipient) and geographic routing, but require extra setup. Tenants can upgrade to a Messaging Service by configuring fromNumber with a Messaging Service SID (MGxxxxxxx) — Twilio’s SDK accepts either.
Test Cases
Unit tests (packages/provider-sms/src/providers/twilio.test.ts)
| Test | Approach |
|---|---|
send() calls client.messages.create with correct params | Mock Twilio SDK; assert from, to, body |
send() returns messageId as Twilio SID | Mock response { sid: 'SMxxxx', status: 'queued' } |
send() throws when errorCode present in response | Mock response { errorCode: 21211, errorMessage: 'Invalid To' } |
send() throws on SDK-level error (network, auth) | Mock messages.create throws; assert propagated |
verify() fetches account info | Mock accounts.fetch; assert called with correct SID |
verify() throws on invalid credentials | Mock accounts.fetch throws 401; assert propagated |
Integration tests
| Test | Approach |
|---|---|
| Send SMS via Twilio test credentials | Use Twilio test account SID/token; send to Twilio test number +15005550006 |
| Invalid to-number returns error code | Send to +15005550001 (Twilio’s invalid number test); assert error thrown |
| Tenant Twilio used when verified | Seed verified twilio row; assert TwilioProvider uses tenant credentials |
Twilio test credentials
Twilio provides sandbox test credentials and magic numbers for CI/testing without real SMS:
| Magic number | Behaviour |
|---|---|
+15005550006 | Valid — message succeeds |
+15005550001 | Invalid number — 21211 error |
+15005550007 | Blacklisted — 21610 error |
+15005550008 | Cannot receive SMS — 21612 error |
Set TWILIO_ACCOUNT_SID=ACtest... and TWILIO_AUTH_TOKEN=test... in CI.
Related
- MSG91 Provider — platform default SMS (India)
- Notification Packages —
@leadmetrics/provider-smsstructure - Notification Providers — resolution pattern
- Notification Channels — SMS handler detail