This tutorial walks you through sending SMS messages from a Laravel 10 or 11 application. By the end, you’ll be able to send SMS via Twilio, Vonage, or any provider using Laravel’s notification system.
Install the SDK for your chosen provider:
composer require twilio/sdk
---
For Vonage:
```bash
composer require vonage/client
---
## Step 2: Configure Environment Variables
Add your provider credentials to `.env`:
```env
# Twilio
TWILIO_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token
TWILIO_FROM=+15551234567
# Vonage (optional, for multi-provider setup)
VONAGE_KEY=your_api_key
VONAGE_SECRET=your_api_secret
VONAGE_FROM=15551234567
---
## Step 3: Create an SMS Service Class
Encapsulate the SMS sending logic in a dedicated service class:
```php
<?php
namespace App\Services;
use Twilio\Rest\Client;
class SmsService
{
protected Client $twilio;
public function __construct()
{
$this->twilio = new Client(
config('sms.drivers.twilio.sid'),
config('sms.drivers.twilio.token')
);
}
public function send(string $to, string $message): string
{
$message = $this->twilio->messages->create(
$to,
[
'from' => config('sms.drivers.twilio.from'),
'body' => $message,
]
);
return $message->sid;
}
}
---
## Step 4: Create a Notification
Laravel's notification system is the idiomatic way to send SMS:
```bash
php artisan make:notification WelcomeSms
---
Define the delivery channel:
```php
<?php
namespace App\Notifications;
use App\Services\SmsService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class WelcomeSms extends Notification implements ShouldQueue
{
use Queueable;
public function __construct(
public string $message
) {
$this->onQueue('sms');
}
public function via(object $notifiable): array
{
return ['sms'];
}
public function toSms(object $notifiable): SmsMessage
{
return new SmsMessage($this->message);
}
}
---
Create a custom `SmsMessage` class:
```php
<?php
namespace App\Notifications;
class SmsMessage
{
public function __construct(
public string $content
) {}
}
---
## Step 5: Register a Custom SMS Channel
Register the channel in `AppServiceProvider`:
```php
<?php
namespace App\Providers;
use App\Notifications\Channels\SmsChannel;
use App\Services\SmsService;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(SmsChannel::class, function ($app) {
return new SmsChannel($app->make(SmsService::class));
});
}
}
---
## Step 6: Send the Notification
Add a `routeNotificationForSms` method to your notifiable model:
```php
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
public function routeNotificationForSms(): ?string
{
return $this->phone_number;
}
}
---
Send the notification:
```php
use App\Notifications\WelcomeSms;
$user = User::find(1);
$user->notify(new WelcomeSms('Welcome to our platform! We're excited to have you.'));
---
## Using Laravel's Built-in Vonage Channel
Laravel ships with first-class Vonage support:
```php
public function via(object $notifiable): array
{
return ['vonage'];
}
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content("Your verification code is: {$this->code}");
}
---
## Queueing SMS for Better Performance
Always queue SMS sending to avoid blocking HTTP responses. The `ShouldQueue` interface handles this automatically:
```php
use Illuminate\Contracts\Queue\ShouldQueue;
class WelcomeSms extends Notification implements ShouldQueue
{
use Queueable;
}
---
Dispatch with the `sms` queue:
```php
$user->notify((new WelcomeSms('Hello!'))->onQueue('sms'));
---
For a deep dive, see our guide on [Laravel SMS notifications using queues](/blog/laravel-sms-notifications-queues).
## Testing SMS in Development
Use Laravel's `Notification::fake()` for deterministic tests:
```php
<?php
namespace Tests\Feature;
use App\Notifications\WelcomeSms;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class SmsNotificationTest extends TestCase
{
public function test_user_receives_welcome_sms(): void
{
Notification::fake();
$user = User::factory()->create();
$user->notify(new WelcomeSms('Welcome!'));
Notification::assertSentTo(
$user,
WelcomeSms::class,
function ($notification, $channels) {
return $notification->message === 'Welcome!';
}
);
}
}
---
### Using the `log` Driver for Development
Set a log-based SMS driver in your `.env` for local development:
```php
// config/sms.php
'drivers' => [
'log' => [
'channel' => env('SMS_LOG_CHANNEL', 'stack'),
],
],
---
```php
// SmsChannel for log driver
public function send(object $notifiable, Notification $notification): void
{
$message = $notification->toSms($notifiable);
Log::info('SMS would be sent', [
'to' => $notifiable->routeNotificationForSms(),
'message' => $message->content,
]);
}
---
## Full Example: Sending an Order Confirmation SMS
```php
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\VonageMessage;
use Illuminate\Notifications\Notification;
class OrderConfirmation extends Notification implements ShouldQueue
{
use Queueable;
public function __construct(
protected string $orderId,
protected string $total
) {}
public function via(object $notifiable): array
{
return ['vonage'];
}
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content("Order #{$this->orderId} confirmed for \${$this->total}. Thank you!")
->unicode();
}
public function toArray(object $notifiable): array
{
return [
'order_id' => $this->orderId,
'total' => $this->total,
];
}
}
---
Trigger it:
```php
$order = Order::find(1234);
$order->user->notify(new OrderConfirmation($order->id, $order->total));
---
## Next Steps
Now that you can send SMS, consider implementing:
- **OTP verification** — see our [Laravel OTP verification guide](/blog/laravel-otp-verification-sms)
- **Bulk campaigns** — chunk users and use job batching (covered in the [ultimate guide](/blog/ultimate-guide-laravel-sms-integration))
- **Two-way SMS** — handle incoming replies via webhooks
## Related Articles
- [Ultimate Guide to Laravel SMS Integration (2026)](/blog/ultimate-guide-laravel-sms-integration)
- [Laravel SMS Notifications Using Queues (Performance Guide)](/blog/laravel-sms-notifications-queues)
- [Laravel OTP Verification via SMS (Complete Guide)](/blog/laravel-otp-verification-sms)
- [Best SMS APIs for Laravel in 2026](/blog/best-sms-apis-for-laravel)