MSG91 Node

Send SMS, OTP, WhatsApp messages, voice OTPs, and emails via MSG91 — India's most popular messaging API. Use it for order confirmations, OTP verification flows, bulk campaign messages, and transactional alerts.

Prerequisites

  • A MSG91 account at msg91.com
  • Auth Key from MSG91 Dashboard → API → Auth Key
  • DLT registration for all commercial SMS (mandatory for India — see DLT note below)
  • Approved SMS templates on DLT portal (Jio DLT, Vodafone DLT, etc.)
  • For WhatsApp operations: an integrated WhatsApp Business number on MSG91
DLT Registration Required. All commercial SMS in India (promotional, transactional, and OTP) requires TRAI DLT registration. Register your sender ID, templates, and entity on the Jio DLT or Vodafone DLT portal before sending. Your flowId must correspond to an approved DLT template.

Credentials

FieldDescriptionWhere to find it
Auth KeyYour MSG91 API authentication keyMSG91 Dashboard → API → Auth Key
  1. Go to Settings → Credentials
  2. Click Add Credential
  3. Select MSG91
  4. Paste your Auth Key
  5. Click Save

Operations

Send SMS (Template)

Send a DLT-approved template SMS using a flow ID.

NameTypeRequiredDefaultDescription
mobilestringYesPhone number with country code, e.g. 919876543210
senderIdstringYes6-character DLT-approved sender ID, e.g. NODEBS
flowIdstringYesMSG91 flow ID linked to a DLT-approved template
smsVariablesJSONNoTemplate variables as JSON, e.g. {"VAR1": "500", "VAR2": "ORD-123"}
jsonOutput
{
  "msg91": {
    "operation": "SEND_SMS",
    "requestId": "9123456789",
    "status": "success",
    "mobile": "919876543210"
  }
}

Send Transactional SMS

Send a plain-text transactional message using route 4 (transactional) or route 8 (OTP).

NameTypeRequiredDefaultDescription
mobilestringYesPhone number with country code
senderIdstringYes6-character DLT-approved sender ID
messagestringYesSMS message text
routenumberYes44 = transactional, 8 = OTP

Send Bulk SMS

Send personalized template SMS to multiple numbers in one API call.

NameTypeRequiredDefaultDescription
senderIdstringYes6-character DLT-approved sender ID
flowIdstringYesMSG91 flow ID for the DLT template
bulkDataJSON arrayYesArray of objects: [{"mobile":"91...", "VAR1":"...", "VAR2":"..."}]
jsonOutput
{
  "msg91": {
    "operation": "SEND_BULK_SMS",
    "requestId": "9123456789",
    "count": 50,
    "status": "success"
  }
}

Schedule SMS

Schedule a template SMS to be sent at a future time.

NameTypeRequiredDefaultDescription
mobilestringYesPhone number with country code
senderIdstringYes6-character sender ID
flowIdstringYesFlow ID for template
smsVariablesJSONNoTemplate variables
scheduleTimestringYesSchedule time in YYYY-MM-DD HH:mm:ss format (IST)

Send OTP

Send a one-time password to a mobile number. MSG91 generates the OTP automatically and sends it directly to the user.

NameTypeRequiredDefaultDescription
mobilestringYesPhone number with country code, e.g. 919876543210
otpTemplateIdstringYesDLT-approved OTP template ID from MSG91 Dashboard
otpLengthnumberYes6Number of digits: 4, 5, or 6
otpExpirynumberYes10Minutes before OTP expires
jsonOutput
{
  "msg91": {
    "operation": "SEND_OTP",
    "status": "success",
    "mobile": "919876543210",
    "message": "OTP sent successfully",
    "timestamp": "2026-04-01T10:00:00.000Z"
  }
}
OTP is never returned in output — MSG91 sends it directly to the user's phone for security. To verify it, use the Verify OTP operation with {{body.otp}} from your form or webhook input.

Verify OTP

Verify an OTP entered by the user. Returns {{msg91.verified}} as true or false. Use an If / Else node immediately after to gate access.

NameTypeRequiredDefaultDescription
mobilestringYesSame phone number used in Send OTP
otpValuestringYesOTP entered by user — typically {{body.otp}} from form submission
jsonOutput
{
  "msg91": {
    "operation": "VERIFY_OTP",
    "verified": true,
    "mobile": "919876543210"
  }
}
Use an If / Else node after Verify OTP checking {{msg91.verified}} equals true. The TRUE branch proceeds with account creation; the FALSE branch returns an error message.
textOTP Verification Workflow
Webhook Trigger (user submits phone)
→ MSG91 — Send OTP
    mobile:          {{body.mobile}}
    otpTemplateId:   abc123def456
    otpLength:       6
    otpExpiry:       10
→ HTTP Response: {"message": "OTP sent"}

───────── (second workflow) ─────────

Webhook Trigger (user submits OTP)
→ MSG91 — Verify OTP
    mobile:   {{body.mobile}}
    otpValue: {{body.otp}}
→ If / Else: {{msg91.verified}} equals true
  TRUE  → Create account → Send welcome SMS
  FALSE → HTTP Response: {"error": "Invalid OTP. Try again."}

Resend OTP

Resend the OTP via SMS text or voice call.

NameTypeRequiredDefaultDescription
mobilestringYesPhone number with country code
retryTypestringYes"text" to resend via SMS, "voice" to call the number

Invalidate OTP

Immediately expire the active OTP for a mobile number. Use this after a successful verification or on logout.

NameTypeRequiredDefaultDescription
mobilestringYesPhone number with country code

Send WhatsApp (Template)

Send a pre-approved WhatsApp template message via MSG91's integrated WhatsApp Business API.

NameTypeRequiredDefaultDescription
mobilestringYesRecipient phone with country code
integratedNumberstringYesYour MSG91 integrated WhatsApp number
whatsappTemplatestringYesApproved template name
whatsappLangstringYesenTemplate language code, e.g. en, hi, mr
whatsappParamsJSON arrayNoTemplate variable values: ["Rahul", "ORD-123", "₹500"]
jsonOutput
{
  "msg91": {
    "operation": "SEND_WHATSAPP",
    "messageId": "msg_OFj67X3s9kH5rA",
    "status": "success",
    "mobile": "919876543210"
  }
}

Send WhatsApp Media

Send an image, video, document, or audio file via WhatsApp.

NameTypeRequiredDefaultDescription
mobilestringYesRecipient phone with country code
integratedNumberstringYesYour integrated WhatsApp number
mediaTypestringYesimage · video · document · audio
mediaUrlstringYesPublic URL of the media file
mediaCaptionstringNoCaption shown below the media

Send Voice OTP

Deliver an OTP via automated voice call. Useful as a fallback when SMS is not delivered.

NameTypeRequiredDefaultDescription
mobilestringYesPhone number with country code
otpTemplateIdstringYesVoice OTP template ID
otpLengthnumberYes6OTP digit length: 4, 5, or 6
otpExpirynumberYes10Minutes before OTP expires

Send Email

Send a transactional email via MSG91's email service.

NameTypeRequiredDefaultDescription
toEmailstringYesRecipient email address
subjectstringYesEmail subject line
emailBodystringYesHTML or plain-text email body
fromEmailstringYesSender email address
fromNamestringNoSender display name
jsonOutput
{
  "msg91": {
    "operation": "SEND_EMAIL",
    "status": "success",
    "toEmail": "rahul@example.com"
  }
}

Get Balance

Check remaining SMS credits in your MSG91 account.

jsonOutput
{
  "msg91": {
    "operation": "GET_BALANCE",
    "balance": 4850,
    "type": "SMS"
  }
}

Get Report

Fetch delivery report for a previously sent SMS using its request ID.

NameTypeRequiredDefaultDescription
requestIdstringYesRequest ID from a previous Send SMS operation — use {{msg91.requestId}}
jsonOutput
{
  "msg91": {
    "requestId": "9123456789",
    "reports": [
      { "mobile": "919876543210", "status": "delivered", "deliveredAt": "..." }
    ]
  }
}

Complete Workflow Examples

Post-Payment Order Confirmation SMS

Use case: Automatically send an order confirmation SMS after a Razorpay payment is captured.

textWorkflow
Razorpay Trigger (event: payment.captured)
→ MSG91 — Send SMS
    mobile:       {{razorpayTrigger.payload.payment.entity.contact}}
    senderId:     NODEBS
    flowId:       your_dlt_flow_id
    smsVariables: {
      "VAR1": "{{razorpayTrigger.payload.payment.entity.notes.customerName}}",
      "VAR2": "{{razorpayTrigger.payload.payment.entity.id}}"
    }

OTP Login Flow

Use case: Allow users to log in to your app using phone number OTP.

textWorkflow
Webhook Trigger (POST /send-otp, body: { mobile })
→ MSG91 — Send OTP
    mobile:        {{body.mobile}}
    otpTemplateId: abc123
    otpLength:     6
    otpExpiry:     10
→ HTTP Response: {"message": "OTP sent to your number"}

─────── Second workflow ───────

Webhook Trigger (POST /verify-otp, body: { mobile, otp })
→ MSG91 — Verify OTP
    mobile:   {{body.mobile}}
    otpValue: {{body.otp}}
→ If / Else: {{msg91.verified}} equals true
  TRUE  → Set Variable: userId = {{body.mobile}}
          → HTTP Response: {"token": "...", "message": "Login successful"}
  FALSE → HTTP Response: {"error": "Invalid OTP"}

Common Issues & Solutions

IssueCauseSolution
SMS not delivered (DND numbers)Number is on Do Not Disturb registryUse route 4 (transactional) for order updates — DND does not apply
Flow ID errorDLT template not approved or wrong flow IDVerify template approval in MSG91 Dashboard → DLT Templates
OTP verification always failsOTP expired or wrong mobile number usedEnsure same mobile is used in Send and Verify. Shorten otpExpiry if needed
Balance is 0Account ran out of SMS creditsRecharge at MSG91 Dashboard or set up auto-recharge
  • Razorpay Trigger — trigger MSG91 SMS on payment events
  • If / Else — gate access based on {{msg91.verified}}
  • WhatsApp — send WhatsApp messages directly via Meta API
  • Shiprocket — pair with Shiprocket AWB in SMS content