Skip to Content
ProvidersTwilio

Twilio

Category: Notification — SMS
Package: @leadmetrics/provider-smsTwilioProvider
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)

TestApproach
send() calls client.messages.create with correct paramsMock Twilio SDK; assert from, to, body
send() returns messageId as Twilio SIDMock response { sid: 'SMxxxx', status: 'queued' }
send() throws when errorCode present in responseMock response { errorCode: 21211, errorMessage: 'Invalid To' }
send() throws on SDK-level error (network, auth)Mock messages.create throws; assert propagated
verify() fetches account infoMock accounts.fetch; assert called with correct SID
verify() throws on invalid credentialsMock accounts.fetch throws 401; assert propagated

Integration tests

TestApproach
Send SMS via Twilio test credentialsUse Twilio test account SID/token; send to Twilio test number +15005550006
Invalid to-number returns error codeSend to +15005550001 (Twilio’s invalid number test); assert error thrown
Tenant Twilio used when verifiedSeed 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 numberBehaviour
+15005550006Valid — message succeeds
+15005550001Invalid number — 21211 error
+15005550007Blacklisted — 21610 error
+15005550008Cannot receive SMS — 21612 error

Set TWILIO_ACCOUNT_SID=ACtest... and TWILIO_AUTH_TOKEN=test... in CI.


© 2026 Leadmetrics — Internal use only