Skip to main content

SendSMSCommand

Overview

SendSMSCommand sends SMS notifications to mobile numbers with support for both direct message text and template-based rendering. It integrates with configured SMS providers (Infobip, Credit Siwtch, etc.) and automatically handles template rendering when templateId is provided.

When to Use

Use SendSMSCommand for:

  • Sending OTP (One-Time Password) codes
  • Transaction alerts and notifications
  • Account balance inquiries
  • Appointment reminders
  • Template-based promotional messages
  • Automated SMS workflows in business processes

Don't use for:

  • Email notifications (use SendMailCommand)
  • Long-form content (SMS has character limits)
  • Real-time chat (use appropriate messaging API)

Syntax

Basic SMS (Direct Message)

var result = doCmd('SendSMSCommand', {
Data: {
messageBody: 'Your OTP code is 123456. Valid for 10 minutes.',
mobileNumber: '+2348012345678'
}
});

Template-Based SMS

var result = doCmd('SendSMSCommand', {
Data: {
templateId: 'OTP_SMS',
context: {
otpCode: '123456',
validityMinutes: 10,
customerName: context.customerName
},
mobileNumber: '+2348012345678',
providerCode: 'TWILLIO'
}
});

JSON Configuration

{
"commandName": "SendSMSCommand",
"parameters": {
"Data": {
"mobileNumber": "+2348012345678",
"messageBody": "Your transaction of NGN 50,000 was successful. Balance: NGN 125,000",
"providerCode": "AFRICAS_TALKING"
}
}
}

Parameters

Data Object

ParameterTypeRequiredDescription
mobileNumberstring✅ YesRecipient mobile number (E.164 format recommended)
messageBodystringConditionalSMS text content (required if no templateId)
templateIdstringConditionalTemplate ID from HtmlTemplateDefinition table (required if no messageBody)
contextobjectNoData for template rendering (used with templateId)
providerCodestringNoSMS provider code (defaults to tenant configuration)

How It Works

1. Direct Message Flow

SendSMSCommand → SMS Provider API → Mobile Network → Recipient

2. Template-Based SMS Flow

SendSMSCommand
├─> Fetch HtmlTemplateDefinition (by templateId)
├─> RenderHtmlCommand (template + context)
├─> Strip HTML tags from rendered output
├─> Generated text becomes messageBody
└─> SMS Provider API → Mobile Network → Recipient

Note: When using templateId, the system:

  1. Fetches the template from HtmlTemplateDefinition table
  2. Renders the template using RenderHtmlCommand with provided context
  3. Strips all HTML tags to get plain text
  4. Sends the resulting text as SMS

Return Value

Success Response

{
"isSuccessful": true,
"message": "SMS sent successfully",
"statusCode": 200,
"data": {
"statusCode": 200,
"transactionId": "SMS-2024-001",
"transactionRef": "Infobip-MSG-12345",
"responseCode": "0000"
}
}

Error Response

{
"isSuccessful": false,
"message": "Failed to send SMS: Invalid mobile number",
"statusCode": 400,
"data": {
"statusCode": 400,
"error": "Invalid phone number format"
}
}

Examples

Example 1: Simple OTP SMS

// Send OTP code
var otpCode = generateOTP(); // Returns: "456789"

var result = doCmd('SendSMSCommand', {
Data: {
messageBody: `Your OTP is ${otpCode}. Valid for 10 minutes. Do not share this code.`,
mobileNumber: context.customerPhone
}
});

if (result.isSuccessful) {
logger.info('OTP sent successfully: ' + result.data.transactionId);

// Store OTP for verification
doCmd('InsertTableCommand', {
Data: {
table: 'tblOTPLog',
values: {
CustomerId: context.customerId,
OTPCode: otpCode,
Phone: context.customerPhone,
SentDate: new Date(),
ExpiryDate: new Date(Date.now() + 10 * 60000), // 10 minutes
TransactionRef: result.data.transactionId
}
}
});
}

Example 2: Template-Based OTP SMS

// Use pre-defined SMS template
var result = doCmd('SendSMSCommand', {
Data: {
templateId: 'OTP_SMS_TEMPLATE',
context: {
bankName: 'ABC Bank',
otpCode: context.otpCode,
validityMinutes: 10,
purpose: 'login verification'
},
mobileNumber: context.customerPhone
}
});

// Template OTP_SMS_TEMPLATE in HtmlTemplateDefinition:
// {{bankName}}: Your OTP for {{purpose}} is {{otpCode}}. Valid for {{validityMinutes}} minutes. Do not share.
//
// Rendered output:
// ABC Bank: Your OTP for login verification is 123456. Valid for 10 minutes. Do not share.

Example 3: Transaction Alert

// Send transaction notification
var result = doCmd('SendSMSCommand', {
Data: {
templateId: 'TRANSACTION_ALERT',
context: {
transactionType: 'Debit',
amount: formatCurrency(context.amount),
balance: formatCurrency(context.newBalance),
reference: context.transactionRef,
date: formatDate(new Date())
},
mobileNumber: context.customerPhone
}
});

// Template TRANSACTION_ALERT:
// {{transactionType}} Alert: {{amount}} on {{date}}.
// Balance: {{balance}}.
// Ref: {{reference}}

Example 4: Account Balance Inquiry Response

// Respond to balance inquiry with template
var result = doCmd('SendSMSCommand', {
Data: {
templateId: 'BALANCE_INQUIRY_RESPONSE',
context: {
customerName: context.customerName,
accountNumber: maskAccountNumber(context.accountNumber),
availableBalance: formatCurrency(context.availableBalance),
ledgerBalance: formatCurrency(context.ledgerBalance),
timestamp: new Date().toLocaleString()
},
mobileNumber: context.customerPhone
}
});

// Template BALANCE_INQUIRY_RESPONSE:
// Dear {{customerName}},
// Acct: {{accountNumber}}
// Available: {{availableBalance}}
// Ledger: {{ledgerBalance}}
// As at {{timestamp}}

Example 5: Appointment Reminder

// Send appointment reminder with specific provider
var result = doCmd('SendSMSCommand', {
Data: {
templateId: 'APPOINTMENT_REMINDER',
context: {
customerName: context.customerName,
appointmentDate: context.appointmentDate,
appointmentTime: context.appointmentTime,
branchName: context.branchName,
purpose: context.appointmentPurpose
},
mobileNumber: context.customerPhone,
providerCode: 'TWILLIO' // Specify provider
}
});

// Template APPOINTMENT_REMINDER:
// Hi {{customerName}}, reminder: Your {{purpose}} appointment is on {{appointmentDate}} at {{appointmentTime}} at {{branchName}} branch.

Example 6: Loan Approval Notification

// Notify customer of loan approval
var result = doCmd('SendSMSCommand', {
Data: {
templateId: 'LOAN_APPROVAL_SMS',
context: {
customerName: context.customerFirstName,
loanAmount: formatCurrency(context.approvedAmount),
interestRate: context.interestRate + '%',
tenure: context.tenureMonths + ' months',
monthlyPayment: formatCurrency(context.monthlyInstallment)
},
mobileNumber: context.customerPhone
}
});

// Template LOAN_APPROVAL_SMS:
// Congratulations {{customerName}}! Your loan of {{loanAmount}} has been approved.
// Rate: {{interestRate}}, Tenure: {{tenure}}, Monthly: {{monthlyPayment}}.
// Check your email for details.

Example 7: Multi-Step Workflow with Template

// Complete OTP verification workflow
function sendOTPAndVerify(customerId, purpose) {
// 1. Generate OTP
var otpCode = Math.floor(100000 + Math.random() * 900000).toString();

// 2. Get customer details
var customer = doCmd('RetrieveCustomerByIdQuery', {
Data: { id: customerId }
});

if (!customer.isSuccessful) {
throw new Error('Customer not found');
}

// 3. Send OTP via SMS using template
var smsResult = doCmd('SendSMSCommand', {
Data: {
templateId: 'OTP_VERIFICATION_SMS',
context: {
customerName: customer.data.firstName,
otpCode: otpCode,
purpose: purpose,
validityMinutes: 10,
supportPhone: '+234800123456'
},
mobileNumber: customer.data.phoneNumber
}
});

if (smsResult.isSuccessful) {
// 4. Store OTP in database
doCmd('InsertTableCommand', {
Data: {
table: 'tblOTPVerification',
values: {
CustomerId: customerId,
OTPCode: otpCode,
Purpose: purpose,
PhoneNumber: customer.data.phoneNumber,
CreatedDate: new Date(),
ExpiryDate: new Date(Date.now() + 10 * 60000),
IsUsed: false,
SMSTransactionId: smsResult.data.transactionId
}
}
});

return {
success: true,
otpId: smsResult.data.transactionId
};
}

return {
success: false,
error: smsResult.message
};
}

Integration with RenderHtmlCommand

How Template Rendering Works

When you provide templateId, the system automatically:

  1. Fetches Template: Retrieves template from HtmlTemplateDefinition
  2. Renders with Context: Calls RenderHtmlCommand internally
  3. Strips HTML: Removes any HTML tags (in case template has formatting)
  4. Sends SMS: Uses the plain text as message body

Manual Template Rendering (Optional)

// If you need to see rendered output before sending
var htmlResult = doCmd('RenderHtmlCommand', {
Data: {
template: 'Hi {{name}}, your balance is {{balance}}',
data: {
name: 'John',
balance: 'NGN 50,000'
}
}
});

// Then send as SMS
var smsResult = doCmd('SendSMSCommand', {
Data: {
messageBody: htmlResult.data.html,
mobileNumber: '+2348012345678'
}
});

Provider Configuration

Supported Providers

Provider CodeProvider NameNotes
TWILLIOInfobipInternational SMS
AFRICAS_TALKINGCredit SiwtchPan-African coverage
TERMIITermiiNigerian SMS provider
CUSTOMCustom ProviderConfigured in tenant settings

Using Specific Provider

// Override default provider
var result = doCmd('SendSMSCommand', {
Data: {
messageBody: 'Test message',
mobileNumber: '+2348012345678',
providerCode: 'TWILLIO' // Use Infobip instead of default
}
});

Default Provider

If providerCode is not specified, the system uses the provider configured in tenant settings:

Configuration Key: SMSProvider
Default Value: TWILLIO

Use Cases

1. Two-Factor Authentication (2FA)

doCmd('SendSMSCommand', {
Data: {
templateId: '2FA_OTP',
context: { code: '123456', app: 'Internet Banking' },
mobileNumber: context.phone
}
});

2. Transaction Notifications

doCmd('SendSMSCommand', {
Data: {
templateId: 'DEBIT_ALERT',
context: {
amount: 'NGN 5,000',
balance: 'NGN 45,000'
},
mobileNumber: context.phone
}
});

3. Account Statements via SMS

doCmd('SendSMSCommand', {
Data: {
templateId: 'MINI_STATEMENT',
context: {
transactions: lastThreeTransactions
},
mobileNumber: context.phone
}
});

4. Marketing Campaigns

doCmd('SendSMSCommand', {
Data: {
templateId: 'PROMO_OFFER',
context: {
customerName: 'John',
offerDetails: '20% off on loans'
},
mobileNumber: context.phone
}
});

Error Handling

Common Errors

ErrorCauseSolution
"mobileNumber is required"Missing phone numberProvide mobileNumber parameter
"messageBody or templateId required"Missing both fieldsProvide either messageBody or templateId
"Invalid phone number format"Malformed numberUse E.164 format: +234XXXXXXXXXX
"Template not found"Invalid templateIdCheck HtmlTemplateDefinition table
"Provider not configured"Invalid providerCodeVerify provider configuration
"SMS credits exhausted"No SMS creditsTop up SMS credits with provider
"Number blacklisted"Recipient opted outRemove from SMS list

Error Handling Example

try {
var result = doCmd('SendSMSCommand', {
Data: {
templateId: 'OTP_SMS',
context: { otpCode: '123456' },
mobileNumber: context.customerPhone
}
});

if (!result.isSuccessful) {
logger.error('SMS failed: ' + result.message);

// Retry with different provider
if (result.message.includes('Provider not available')) {
result = doCmd('SendSMSCommand', {
Data: {
templateId: 'OTP_SMS',
context: { otpCode: '123456' },
mobileNumber: context.customerPhone,
providerCode: 'AFRICAS_TALKING' // Fallback provider
}
});
}

// If SMS fails, try email as backup
if (!result.isSuccessful) {
doCmd('SendMailCommand', {
Data: {
subject: 'Your OTP Code',
email: [context.customerEmail],
message: '<p>Your OTP is 123456</p>'
}
});
}
}
} catch (error) {
logger.error('SMS error: ' + error.message);
}

Best Practices

1. Phone Number Validation

function isValidPhoneNumber(phone) {
// E.164 format: +[country code][number]
return /^\+[1-9]\d{1,14}$/.test(phone);
}

if (!isValidPhoneNumber(context.phone)) {
throw new Error('Invalid phone number format');
}

2. Message Length Optimization

// SMS has 160-character limit for single message
// Keep messages concise
var message = `OTP: ${otpCode}. Valid ${minutes}min.`; // Good
// vs
var message = `Dear valued customer, your one-time password is ${otpCode}...`; // Too long

3. Template Organization

  • Store reusable SMS templates in HtmlTemplateDefinition
  • Use consistent naming: {MODULE}_{TYPE}_SMS
  • Keep templates under 160 characters for single SMS
  • Example: OTP_SMS, TRANSACTION_ALERT_SMS, BALANCE_INQUIRY_SMS

4. Context Preparation

// Prepare clean context
var smsContext = {
name: context.customerName || 'Customer',
amount: formatCurrency(context.amount),
code: context.otpCode.toString(),
time: new Date().toLocaleTimeString()
};

5. Rate Limiting

// Check if customer hasn't received too many SMS recently
var recentSMS = doCmd('GetFullTableQuery', {
Data: {
table: 'tblSMSLog',
filter: `CustomerId = ${context.customerId} AND SentDate > '${last5Minutes}'`
}
});

if (recentSMS.data.rows.length >= 3) {
throw new Error('Too many SMS requests. Please try again later.');
}

6. Audit Trail

// Log all SMS sent
if (result.isSuccessful) {
doCmd('InsertTableCommand', {
Data: {
table: 'tblSMSLog',
values: {
CustomerId: context.customerId,
PhoneNumber: context.phone,
MessageType: 'OTP',
SentDate: new Date(),
TransactionId: result.data.transactionId,
Provider: providerCode
}
}
});
}

Performance Tips

  1. Template Caching: Templates are cached after first load
  2. Provider Selection: Choose geographically appropriate provider
  3. Async Processing: SMS sending is asynchronous
  4. Bulk SMS: For multiple recipients, consider batch API
  5. Message Length: Keep under 160 characters to avoid split messages

Character Limits

SMS TypeCharacter LimitNotes
Standard SMS160 charactersGSM-7 encoding
Unicode SMS70 charactersFor special characters/emojis
Concatenated SMS153 chars per partAutomatically split by provider

API Endpoint

POST /api/bpm/execute-command
{
"commandName": "SendSMSCommand",
"parameters": {
"Data": {
"mobileNumber": "+2348012345678",
"messageBody": "Your OTP is 123456"
}
}
}

Configuration

Provider Settings

Configure SMS providers in tenant configuration:

  • Provider API Keys
  • Provider URLs
  • Character encoding
  • Delivery reports
  • Fallback providers

Template Storage

SMS templates are stored in:

  • HtmlTemplateDefinition table
  • Template Type: SMS
  • Plain text or simple HTML (stripped during sending)

Version History

  • v2.0: Added templateId support with automatic RenderHtmlCommand integration
  • v1.5: Added providerCode parameter for multi-provider support
  • v1.0: Initial release with basic SMS functionality

See Also