kaydee123/msg91-php
PHP 8.0–8.5 client for MSG91 SMS & OTP: send single/bulk and template-based SMS, DLT-compliant messaging for India, send/verify/resend OTP (text/voice), fluent chainable API, strong error handling, framework-agnostic.
A PHP client library for MSG91 SMS and OTP services. Compatible with PHP 8.0 through 8.5.
Install the package via Composer:
composer require kaydee123/msg91-php
First, you need to get your MSG91 Auth Key from your MSG91 Dashboard.
<?php
require 'vendor/autoload.php';
use Kaydee123\Msg91\Msg91Client;
// Initialize the client
$client = new Msg91Client('YOUR_AUTH_KEY');
The package provides a fluent, chainable interface for easy and intuitive usage:
Send SMS using Template (Recommended):
$response = $client->sms()
->template('YOUR_TEMPLATE_ID')
->variables(['number' => '3', 'date' => '22-12-2025'])
->numbers('919876543210')
->send();
Send SMS to Multiple Recipients with Variables:
$response = $client->sms()
->template('YOUR_TEMPLATE_ID')
->numbers(['919876543210', '919876543211'])
->variables(['number' => '3', 'date' => '22-12-2025'])
->send();
Send SMS with Individual Recipient Variables:
$response = $client->sms()
->template('YOUR_TEMPLATE_ID')
->recipients([
['mobiles' => '919876543210', 'number' => '3', 'date' => '22-12-2025'],
['mobiles' => '919876543211', 'number' => '5', 'date' => '23-12-2025'],
])
->send();
Send DLT SMS (Promotional):
$response = $client->sms()
->promotional()
->sender_id('YOUR_SENDER_ID')
->mobiles("9876543210,9876543211")
->dlt_template_id("YOUR_DLT_TEMPLATE_ID")
->message("Your promotional message here")
->send();
// Country code 91 is automatically added
Send DLT SMS (Transactional):
$response = $client->sms()
->transactional()
->sender_id('YOUR_SENDER_ID')
->mobiles("9876543210")
->dlt_template_id("YOUR_DLT_TEMPLATE_ID")
->message("Your transactional message here")
->send();
// Country code 91 is automatically added
Send OTP (Template ID required, especially for India):
// Template ID is mandatory for Indian numbers (91) due to DLT compliance
$response = $client->otp()
->template('YOUR_OTP_TEMPLATE_ID')
->number('919876543210')
->send();
Send OTP with Custom Options:
$response = $client->otp()
->template('YOUR_OTP_TEMPLATE_ID')
->number('919876543210')
->length(6) // OTP length (optional)
->expiry(10) // Expiry in minutes (optional)
->send();
Send Custom OTP:
$response = $client->otp('123456')
->template('YOUR_OTP_TEMPLATE_ID')
->number('919876543210')
->send();
Verify OTP:
$response = $client->otp('565656')
->number('919876543210')
->verify();
Retry/Resend OTP:
// Retry as text SMS
$response = $client->otp()
->number('919876543210')
->viaText()
->retry();
// Retry as voice call
$response = $client->otp()
->number('919876543210')
->viaVoice()
->retry();
// Or use resend (text by default)
$response = $client->otp()
->number('919876543210')
->resend();
DLT (Distributed Ledger Technology) is mandatory for sending commercial SMS in India. TRAI requires all SMS messages to be DLT-compliant.
The recommended approach is to register your SMS templates with MSG91, which includes the DLT template ID. Once registered, you can use the template-based methods above, and MSG91 will automatically handle DLT compliance:
// Using template-based SMS (v5 API) - DLT handled automatically
$response = $client->sms()
->template('YOUR_MSG91_TEMPLATE_ID') // This template includes DLT template ID
->variables(['var1' => 'value1'])
->numbers('919876543210')
->send();
Important: For Indian mobile numbers (country code 91), a Template ID is mandatory when sending OTP due to DLT compliance requirements. The package will automatically validate this requirement and throw an error if template ID is missing for Indian numbers.
// ✅ Correct - Template ID provided for India
$response = $client->otp()
->template('YOUR_DLT_TEMPLATE_ID') // Required for India
->number('919876543210') // Indian number (starts with 91)
->send();
// ❌ Will throw error - Template ID missing for Indian number
$response = $client->otp()
->number('919876543210') // Indian number
->send(); // Missing template() - will throw InvalidArgumentException
Note: The template ID must be a DLT-registered template in your MSG91 dashboard. For non-Indian numbers, template ID is still required by MSG91 v5 API, but the DLT compliance validation is specific to India.
$client = new Msg91Client('YOUR_AUTH_KEY', [
'base_url' => 'https://control.msg91.com/api/', // Custom base URL (default)
'timeout' => 60, // Request timeout in seconds
'debug' => true, // Enable debug logging
]);
If you receive error code 400 when sending OTP, it usually means:
Invalid Template ID: The template_id you're using might not be a valid OTP template or might not be approved in your MSG91 dashboard.
Template Not Approved: The template might be pending approval or rejected.
Wrong Template Type: You might be using a Flow template ID instead of an OTP template ID.
DLT Compliance Issues (India): For Indian numbers, the template must be DLT-compliant.
Example Error Handling:
try {
$response = $client->otp()
->template('YOUR_TEMPLATE_ID')
->number('919876543210')
->send();
} catch (\Kaydee123\Msg91\Exceptions\ApiException $e) {
if ($e->getStatusCode() === 400) {
echo "Error 400: " . $e->getMessage();
echo "\nPlease verify your template_id is correct and is an OTP template.";
// Check response data for more details
print_r($e->getResponse());
}
}
This error occurs when sending SMS to Indian numbers without a DLT template ID.
dlt_template_id when using the DLT SMS method.This error indicates an invalid sender ID or missing DLT entity ID.
For more error codes, refer to MSG91 Error Codes Documentation.
The package provides custom exception classes for better error handling:
use Kaydee123\Msg91\Exceptions\Msg91Exception;
use Kaydee123\Msg91\Exceptions\ApiException;
try {
$response = $client->sms()
->template('YOUR_TEMPLATE_ID')
->to('919876543210')
->send();
} catch (ApiException $e) {
// API-specific errors
echo "API Error: " . $e->getMessage();
echo "Status Code: " . $e->getStatusCode();
print_r($e->getResponse());
} catch (Msg91Exception $e) {
// General MSG91 errors
echo "Error: " . $e->getMessage();
} catch (\Exception $e) {
// Other errors
echo "Unexpected error: " . $e->getMessage();
}
template($templateId) - Set template ID for template-based SMS (required)numbers($mobiles) - Set recipient mobile number(s) - string or array (alias for to())to($mobile) - Set recipient mobile number(s) - string or arrayvariables(array $variables) - Set multiple template variables (optional)variable($key, $value) - Set a single template variable (optional)recipients(array $recipients) - Set recipients with individual variables (array of objects)promotional() - Set route to promotional (route 1)transactional() - Set route to transactional (route 4, default)sender_id($id) - Set sender ID (alias for from(), required for DLT SMS)mobiles($mobiles) - Set mobiles for DLT SMS - comma-separated string or arraydlt_template_id($id) - Set DLT Template ID (alias for dltTemplateId(), India only)message($message) - Set SMS message content (required for DLT SMS)short_url($url) - Set short URL (optional, default: '0')short_url_expiry($expiry) - Set short URL expiry (optional, default: '0')send() - Send the SMStemplate($templateId) - Set template ID (required)number($mobile) - Set mobile number (alias for to())to($mobile) - Set mobile numberlength($digits) - Set OTP length/digits (optional, alias for digits(), default: 4)expiry($minutes) - Set OTP expiry in minutes (optional, alias for expiresInMinutes(), default: 1)digits($digits) - Set number of OTP digits (default: 4)expiresInMinutes($minutes) - Set OTP expiry in minutes (default: 1)variable($key, $value) - Set a template variable (optional)variables(array $variables) - Set multiple template variables (optional)viaText() - Set retry type to textviaVoice() - Set retry type to voicesend() - Send OTPverify($otp) - Verify OTP coderetry() - Retry/resend OTPresend() - Resend OTP (text by default)'4' - Transactional SMS (default)'1' - Promotional SMSCommon country codes:
'91' - India (default)'1' - USA/Canada'44' - UK'61' - AustraliaFor a complete list, refer to MSG91 documentation.
This package is tested and compatible with:
The package includes comprehensive PHPUnit tests. To run the tests:
# Install dependencies
composer install
# Run all tests
vendor/bin/phpunit
# Run tests with coverage
vendor/bin/phpunit --coverage-text
For testing across multiple PHP versions, see the Testing Guide.
Contributions are welcome! Please feel free to submit a Pull Request.
This package is open-sourced software licensed under the MIT license.
For MSG91 API documentation, visit https://docs.msg91.com/
For issues related to this package, please open an issue on GitHub.
How can I help you explore Laravel packages today?