A modern, flexible Laravel package for integrating any SMS gateway with REST API support
gr8shivam/laravel-sms-api is a Laravel package for a modern, flexible laravel package for integrating any sms gateway with rest api support.
It currently has 101 GitHub stars and 40.199 downloads on Packagist (latest version 4.1.0).
Install it with composer require gr8shivam/laravel-sms-api.
Discover more Laravel packages by gr8shivam
or browse all Laravel packages to compare alternatives.
Last updated
A modern, flexible Laravel package for integrating any SMS gateway that provides a REST API. Perfect for Laravel 10+ applications with full support for notifications, multiple gateways, and modern authentication methods.
composer require gr8shivam/laravel-sms-api
php artisan vendor:publish --provider="Gr8Shivam\SmsApi\SmsApiServiceProvider"
This creates config/sms-api.php in your application.
Edit config/sms-api.php and add your SMS provider credentials (see Configuration below).
use Gr8Shivam\SmsApi\SmsApiFacade as SmsApi;
// Simple usage
SmsApi::sendMessage("9876543210", "Hello from Laravel!");
// Or using helper
smsapi("9876543210", "Hello from Laravel!");
SmsApi::sendMessage(["9876543210", "9876543211"], "Hello everyone!");
$response = SmsApi::sendMessage("9876543210", "Hello!")
->response();
$statusCode = SmsApi::sendMessage("9876543210", "Hello!")
->getResponseCode();
$isSuccess = SmsApi::sendMessage("9876543210", "Hello!")
->isSuccessful(); // Returns true for 2xx status codes
Open config/sms-api.php after publishing.
return [
// Default country code (added to numbers automatically)
'country_code' => env('SMS_API_COUNTRY_CODE', '91'),
// Default gateway to use
'default' => env('SMS_API_DEFAULT_GATEWAY', 'your_gateway'),
// HTTP client timeouts
'timeout' => env('SMS_API_TIMEOUT', 30),
'connect_timeout' => env('SMS_API_CONNECT_TIMEOUT', 10),
// Optional message validation
'validation' => [
'enabled' => env('SMS_API_VALIDATION_ENABLED', false),
'max_length' => env('SMS_API_MAX_LENGTH', 1000),
],
];
For simple GET/POST requests:
'your_gateway' => [
'method' => 'POST', // GET, POST, PUT, PATCH, DELETE
'url' => 'https://api.smsgateway.com/send',
'params' => [
'send_to_param_name' => 'mobile', // Your provider's "to" param name
'msg_param_name' => 'message', // Your provider's "message" param name
'others' => [
'api_key' => env('SMS_GATEWAY_KEY'),
'sender_id' => env('SMS_SENDER_ID'),
],
],
'headers' => [
'Accept' => 'application/json',
],
'add_code' => true, // Automatically add country code
],
For JSON requests with complex structures:
'advanced_gateway' => [
'method' => 'POST',
'url' => 'https://api.provider.com/v2/send',
'params' => [
'send_to_param_name' => 'recipient',
'msg_param_name' => 'text',
'others' => [
'priority' => 'high',
'ttl' => 3600,
],
],
'headers' => [
'Authorization' => 'Bearer ' . env('SMS_API_TOKEN'),
'Content-Type' => 'application/json',
],
'json' => true, // Send as JSON payload
'jsonToArray' => true, // Send single number as array: ["9876543210"]
'wrapper' => 'data', // Wrap payload in {"data": {...}}
'wrapperParams' => [
'campaign_id' => 'welcome_sms',
],
'add_code' => true,
],
Result payload example:
{
"data": [
{
"recipient": ["919876543210"],
"text": "Your message",
"campaign_id": "welcome_sms"
}
],
"priority": "high",
"ttl": 3600
}
'gateway' => [
'headers' => [
'Authorization' => 'Bearer ' . env('SMS_API_TOKEN'),
],
],
In .env:
SMS_API_TOKEN=your_bearer_token_here
'gateway' => [
'headers' => [
'X-API-Key' => env('SMS_API_KEY'),
],
],
'gateway' => [
'headers' => [
'Authorization' => 'Basic ' . base64_encode(env('SMS_USERNAME') . ':' . env('SMS_PASSWORD')),
],
],
'gateway' => [
'params' => [
'others' => [
'api_key' => env('SMS_API_KEY'),
],
],
],
json (boolean)Send parameters as JSON payload instead of query string or form data.
'json' => true,
jsonToArray (boolean)When json is true, controls whether a single mobile number is sent as:
true: ["9876543210"] (array)false: "9876543210" (string)'jsonToArray' => false,
wrapper (string)Wraps the JSON request in a named object. Required by some providers.
'wrapper' => 'sms', // Creates: {"sms": [{...}]}
wrapperParams (array)Adds parameters inside the wrapper (separate from regular params).
'wrapperParams' => [
'campaign' => 'summer_sale',
'priority' => 1,
],
add_code (boolean)Automatically prepend country code to phone numbers.
'add_code' => true, // 9876543210 becomes 919876543210
The smsapi() helper provides the most convenient way to send SMS.
// Quick send
smsapi("9876543210", "Welcome to our platform!");
// Or
smsapi()->sendMessage("9876543210", "Welcome!");
smsapi("9876543210", "Your OTP is 1234", [
'template_id' => 'OTP_TEMPLATE',
'priority' => 'high'
]);
smsapi("9876543210", "Hello", [], [
'X-Custom-Header' => 'value',
'X-Request-ID' => uniqid()
]);
smsapi()->gateway('backup_gateway')
->sendMessage("9876543210", "Message via backup gateway");
smsapi()->countryCode('1') // USA
->sendMessage("5551234567", "Hello from USA!");
$recipients = ["9876543210", "9876543211", "9876543212"];
smsapi($recipients, "Bulk message to all!");
smsapi()->addWrapperParams([
'campaign' => 'newsletter',
'tracking_id' => '12345'
])
->sendMessage("9876543210", "Newsletter message");
smsapi()
->gateway('primary_gateway')
->countryCode('91')
->addWrapperParams(['campaign' => 'promo'])
->sendMessage("9876543210", "Promotional offer!", [
'template_id' => 'PROMO_123'
]);
The facade provides the same functionality with explicit imports.
use Gr8Shivam\SmsApi\SmsApiFacade as SmsApi;
// Basic usage
SmsApi::sendMessage("9876543210", "Hello!");
// With gateway selection
SmsApi::gateway('gateway_name')
->sendMessage("9876543210", "Hello!");
// With country code
SmsApi::countryCode('44') // UK
->sendMessage("7911123456", "Hello from UK!");
// Bulk SMS
SmsApi::sendMessage(
["9876543210", "9876543211"],
"Bulk message"
);
// Get response
$response = SmsApi::sendMessage("9876543210", "Test")
->response();
// Get status code
$code = SmsApi::sendMessage("9876543210", "Test")
->getResponseCode();
// Check success
$success = SmsApi::sendMessage("9876543210", "Test")
->isSuccessful();
Laravel SMS API integrates seamlessly with Laravel's notification system.
In your User model (or any Notifiable model):
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for SMS API channel
*/
public function routeNotificationForSmsApi()
{
return $this->phone; // Return the phone number column
}
}
php artisan make:notification WelcomeNotification
namespace App\Notifications;
use Illuminate\Notifications\Notification;
use Gr8Shivam\SmsApi\Notifications\SmsApiChannel;
use Gr8Shivam\SmsApi\Notifications\SmsApiMessage;
class WelcomeNotification extends Notification
{
public function via($notifiable)
{
return [SmsApiChannel::class];
}
public function toSmsApi($notifiable)
{
return (new SmsApiMessage)
->content("Welcome {$notifiable->name}!");
}
}
$user = User::find(1);
$user->notify(new WelcomeNotification());
With Parameters:
public function toSmsApi($notifiable)
{
return (new SmsApiMessage)
->content("Your OTP is: {$this->otp}")
->params([
'template_id' => 'OTP_VERIFY',
'priority' => 'high'
]);
}
With Headers:
public function toSmsApi($notifiable)
{
return (new SmsApiMessage)
->content($this->message)
->params(['campaign' => 'marketing'])
->headers(['X-Campaign-ID' => '12345']);
}
Unicode Message:
public function toSmsApi($notifiable)
{
return (new SmsApiMessage)
->content("เคจเคฎเคธเฅเคคเฅ! Welcome")
->unicode();
}
Using Static Constructor:
public function toSmsApi($notifiable)
{
return SmsApiMessage::create("Hello {$notifiable->name}!")
->addParam('template_id', 'WELCOME_001')
->addHeader('X-Priority', 'high');
}
Return String (Shorthand):
public function toSmsApi($notifiable)
{
return "Welcome to our platform!"; // Automatically converted to SmsApiMessage
}
Use send_sms() for operations where you want to catch exceptions:
if (send_sms("9876543210", "Hello!")) {
echo "SMS sent successfully!";
} else {
echo "SMS failed. Error logged.";
}
$sms = smsapi()->sendMessage("9876543210", "Hello!");
// Get raw response
$response = $sms->response();
// Get status code
$code = $sms->getResponseCode();
// Check if successful
if ($sms->isSuccessful()) {
// 2xx status code
}
$message = new SmsApiMessage("Your message here");
// Get message length
$length = $message->length();
// Check if empty
if ($message->isEmpty()) {
// Handle empty message
}
// Estimate SMS segments (for cost calculation)
$segments = $message->estimateSegments(); // Returns 1, 2, 3...
// Get preview
$preview = $message->preview(50); // First 50 characters
Enable validation in config:
'validation' => [
'enabled' => true,
'max_length' => 1000,
],
Then validate:
try {
$message->validate();
} catch (\InvalidArgumentException $e) {
// Handle validation error
}
$gateway = $user->isPremium() ? 'premium_gateway' : 'basic_gateway';
smsapi()->gateway($gateway)
->sendMessage($user->phone, "Relevant message");
// .env
SMS_API_DEFAULT_GATEWAY=twilio
SMS_API_COUNTRY_CODE=1
SMS_API_TIMEOUT=60
TWILIO_ACCOUNT_SID=your_sid
TWILIO_AUTH_TOKEN=your_token
TWILIO_FROM_NUMBER=+15551234567
// Array of numbers
$recipients = User::where('notify_sms', true)
->pluck('phone')
->toArray();
smsapi($recipients, "Important announcement!");
All requests and responses are automatically logged using Laravel's logging system:
// Check logs/laravel.log for:
// [INFO] SMS Gateway Response Code: 200
// [INFO] SMS Gateway Response Body: {...}
// [ERROR] SMS Gateway Response Code: 400
// [ERROR] SMS Gateway Response Body: {...}
'twilio' => [
'method' => 'POST',
'url' => 'https://api.twilio.com/2010-04-01/Accounts/' . env('TWILIO_ACCOUNT_SID') . '/Messages.json',
'params' => [
'send_to_param_name' => 'To',
'msg_param_name' => 'Body',
'others' => [
'From' => env('TWILIO_FROM_NUMBER'),
],
],
'headers' => [
'Authorization' => 'Basic ' . base64_encode(env('TWILIO_ACCOUNT_SID') . ':' . env('TWILIO_AUTH_TOKEN')),
],
'add_code' => true,
],
Usage:
smsapi()->gateway('twilio')->sendMessage("5551234567", "Hello from Twilio!");
'msg91' => [
'method' => 'POST',
'url' => 'https://control.msg91.com/api/v2/sendsms',
'params' => [
'send_to_param_name' => 'to',
'msg_param_name' => 'message',
'others' => [
'authkey' => env('MSG91_AUTH_KEY'),
'sender' => env('MSG91_SENDER_ID'),
'route' => '4',
'country' => '91',
],
],
'json' => true,
'wrapper' => 'sms',
'add_code' => false,
],
Usage:
smsapi()->gateway('msg91')->sendMessage("9876543210", "Hello from MSG91!");
'aws_sns' => [
'method' => 'POST',
'url' => 'https://sns.us-east-1.amazonaws.com/',
'params' => [
'send_to_param_name' => 'PhoneNumber',
'msg_param_name' => 'Message',
'others' => [
'Action' => 'Publish',
],
],
'headers' => [
'Authorization' => 'AWS4-HMAC-SHA256 ...', // Use AWS SDK for proper signing
],
'add_code' => true,
],
'nexmo' => [
'method' => 'POST',
'url' => 'https://rest.nexmo.com/sms/json',
'params' => [
'send_to_param_name' => 'to',
'msg_param_name' => 'text',
'others' => [
'api_key' => env('NEXMO_API_KEY'),
'api_secret' => env('NEXMO_API_SECRET'),
'from' => env('NEXMO_FROM'),
],
],
'json' => true,
'add_code' => true,
],
'generic_api' => [
'method' => 'POST',
'url' => 'https://api.smsprovider.com/v1/send',
'params' => [
'send_to_param_name' => 'to',
'msg_param_name' => 'message',
'others' => [
'sender' => 'YourApp',
],
],
'headers' => [
'Authorization' => 'Bearer ' . env('SMS_BEARER_TOKEN'),
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => true,
'add_code' => true,
],
composer test
use Gr8Shivam\SmsApi\Tests\AbstractTestCase;
use Gr8Shivam\SmsApi\SmsApiFacade as SmsApi;
class MyFeatureTest extends AbstractTestCase
{
/** @test */
public function it_sends_sms()
{
$this->mockSmsGateway(200, 'Success');
$response = SmsApi::sendMessage("9876543210", "Test");
$this->assertEquals(200, $response->getResponseCode());
$this->assertTrue($response->isSuccessful());
}
}
See CHANGELOG.md for version history and breaking changes.
Latest Version: 4.0.0
storage/logs/laravel.logphp artisan tinker
>>> smsapi()->sendMessage("YOUR_NUMBER", "Test")->response();
$sms = smsapi()->sendMessage("9876543210", "Test");
dd([
'code' => $sms->getResponseCode(),
'response' => $sms->response(),
'success' => $sms->isSuccessful()
]);
php artisan config:clear
php artisan cache:clear
.env, never hardcode$user->notify(new WelcomeNotification()); // Use ShouldQueue trait
estimateSegments()Developed by Shivam Agarwal
MIT License - see LICENSE file for details.
If this package helps you, please give it a star on GitHub!
Made with โค๏ธ for the Laravel community