MSG91
Category: Notification — SMS
Package: @leadmetrics/provider-sms → Msg91Provider
External SDK: axios (direct REST API calls)
Purpose
MSG91 is the platform default SMS provider, targeting the Indian market. All tenants get SMS notifications from the platform’s MSG91 account out of the box. Tenants can bring their own MSG91 account for messages to arrive from their own registered sender ID (e.g. “ACMEPLMB” instead of “LEADMTX”).
MSG91 sender IDs must be pre-registered with TRAI (India’s telecom regulator). International SMS is not the primary use case — use Twilio for international.
What it sends
| Notification type | Trigger |
|---|---|
| HITL review request (SMS) | Activity reaches pending_approval |
| Budget warning (SMS) | Credits drop below 20% threshold |
| Report ready (SMS) | Monthly report generated |
| OTP / auth (future) | 2FA or login codes |
Config Structure
Platform default (env vars)
SMS_API_KEY=your_msg91_api_key
SMS_FROM=LEADMTX # 6-character TRAI-registered sender ID
SMS_API_BASE_URL=https://api.msg91.com/api/v5Tenant config (stored in notification_providers.config, encrypted)
interface Msg91Config {
apiKey: string; // MSG91 API key
senderId: string; // 6-character alphanumeric sender ID registered with TRAI
baseUrl: string; // usually "https://api.msg91.com/api/v5" — allow override for future API versions
}Integration Pattern
Provider class (packages/provider-sms/src/providers/msg91.ts)
MSG91 uses a simple REST API. The platform calls the sendotp or flow endpoints depending on the message type.
import axios from 'axios';
class Msg91Provider implements SmsProvider {
readonly name = 'msg91';
constructor(
private apiKey: string,
private senderId: string,
private baseUrl: string,
) {}
async send(message: SmsMessage): Promise<SmsSendResult> {
const response = await axios.post(
`${this.baseUrl}/flow/`,
{
sender: this.senderId,
mobiles: message.to, // E.164 format: "+919876543210"
message: message.body,
},
{
headers: {
'authkey': this.apiKey,
'Content-Type': 'application/json',
'Accept': 'application/json',
},
},
);
if (response.data.type !== 'success') {
throw new Error(`MSG91 send failed: ${response.data.message}`);
}
return {
messageId: response.data.request_id,
provider: 'msg91',
status: response.data.type,
};
}
async verify(): Promise<void> {
// MSG91 doesn't have a ping endpoint; call balance/account info as a connectivity check
const response = await axios.get(`${this.baseUrl}/balance`, {
headers: { authkey: this.apiKey },
});
if (response.status !== 200) {
throw new Error(`MSG91 verification failed: HTTP ${response.status}`);
}
}
}Phone number format
MSG91 accepts E.164 format. The to field in SmsMessage must be +91XXXXXXXXXX for Indian numbers. The notification system normalises phone numbers to E.164 from the tenant_users.phone field before dispatch.
DLT registration (India)
MSG91 requires DLT (Distributed Ledger Technology) registration for promotional and transactional SMS. The platform’s registered DLT template IDs must be set per message type. These are stored in the platform env config:
MSG91_DLT_TEMPLATE_HITL=1007xxxxxxxxxx
MSG91_DLT_TEMPLATE_BUDGET=1007xxxxxxxxxx
MSG91_DLT_TEMPLATE_REPORT=1007xxxxxxxxxxFor tenant accounts, the tenant’s DLT template IDs are stored in Msg91Config or as a separate table column.
Test Cases
Unit tests (packages/provider-sms/src/providers/msg91.test.ts)
| Test | Approach |
|---|---|
send() POSTs to correct MSG91 endpoint | Mock axios.post; assert URL and headers |
send() includes authkey, sender, mobiles, message | Assert request body fields |
send() returns messageId from request_id | Mock response { type: 'success', request_id: 'abc' } |
send() throws on type !== 'success' | Mock response { type: 'error', message: 'Invalid API Key' } |
send() throws on network error | Mock axios.post rejects; assert error propagated |
verify() calls balance endpoint | Mock axios.get; assert URL and authkey header |
verify() throws on non-200 | Mock 401; assert throws |
Integration tests
| Test | Approach |
|---|---|
| Send SMS against MSG91 sandbox | Use MSG91 test credentials; assert request_id returned |
| Platform default used when no tenant row | Seed no notification_providers row; assert Msg91Provider uses env vars |
| Tenant MSG91 used when verified | Seed verified msg91 row; assert Msg91Provider uses tenant apiKey |
Dev / staging
In dev mode, filterRecipientsForDev() replaces all to phone numbers with DEV_PHONE_OVERRIDE. No real SMS is sent to end users during development.
Sender ID Registration
To use the platform sender ID, the following must be registered on TRAI’s DLT portal:
| Field | Value |
|---|---|
| Entity name | Leadmetrics Technologies |
| Sender ID | LEADMTX |
| Category | Transactional |
| Templates | All 18 notification type templates |
Tenants must register their own sender IDs through their MSG91 account and DLT portal before using a custom sender.
Related
- Twilio Provider — alternative SMS provider for international numbers
- Notification Packages —
@leadmetrics/provider-smsstructure - Notification Providers — resolution pattern
- Notification Channels — SMS handler detail