Muhammad Yasir Amin

Loading websiteโ€ฆ

More from Muhammad Yasir Amin

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Subscribe on YouTube

How to Send SMS in Laravel 13 with Twilio

๐Ÿ› ๏ธ Laravel Tutorials4 min read

How to Send SMS in Laravel 13 with Twilio

Muhammad Yasir Amin

Muhammad Yasir Amin

Senior Full Stack Engineerโ€ขNov 12, 2026
How to Send SMS in Laravel 13 with Twilio

To send an SMS in Laravel 13 with Twilio, install the twilio/sdk package, store your Account SID, Auth Token and sender number in .env, and call $client->messages->create() from a service class. This guide shows the full setup, how to validate phone numbers, how to handle Twilio errors, and what limits apply to trial accounts.

Targets: Laravel 13 (PHP 8.3 to 8.5) and the official Twilio PHP SDK.

Step 1: Create a Twilio account and get credentials

In the Twilio Console you need three values: the Account SID, the Auth Token and a Twilio phone number that can send SMS (or a Messaging Service SID). Trial accounts can only message phone numbers that you have verified in the console, and trial messages carry a prefix that says the message was sent from a trial account.

Step 2: Install the SDK

Code
composer require twilio/sdk

Step 3: Add the settings

Code
TWILIO_SID=your-account-sid
TWILIO_AUTH_TOKEN=your-auth-token
TWILIO_FROM=+15005550006
JavaScript
'twilio' => [
    'sid' => env('TWILIO_SID'),
    'token' => env('TWILIO_AUTH_TOKEN'),
    'from' => env('TWILIO_FROM'),
],

Add the array to config/services.php. The number above is a placeholder in E.164 format; use your own Twilio number. Never commit the Auth Token.

Step 4: Create the SMS service

JavaScript
<?php

namespace App\Services;

use RuntimeException;
use Twilio\Exceptions\TwilioException;
use Twilio\Rest\Client;

class SmsService
{
    public function __construct(private ?Client $client = null)
    {
        $this->client ??= new Client(
            config('services.twilio.sid'),
            config('services.twilio.token')
        );
    }

    public function send(string $to, string $body): string
    {
        try {
            $message = $this->client->messages->create($to, [
                'from' => config('services.twilio.from'),
                'body' => $body,
            ]);
        } catch (TwilioException $e) {
            report($e);

            throw new RuntimeException('The SMS could not be sent.');
        }

        return $message->sid;
    }
}

The method returns the message SID, which you can store to look the message up later. Taking the client through the constructor lets tests pass a fake client.

Step 5: Validate the phone number

Twilio expects numbers in E.164 format: a plus sign, the country code and the number, up to 15 digits in total. Validate that before calling the API:

JavaScript
<?php

namespace App\Http\Controllers;

use App\Services\SmsService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use RuntimeException;

class SmsController extends Controller
{
    public function send(Request $request, SmsService $sms): JsonResponse
    {
        $data = $request->validate([
            'to' => ['required', 'regex:/^\+[1-9][0-9]{7,14}$/'],
            'message' => ['required', 'string', 'max:500'],
        ]);

        try {
            $sid = $sms->send($data['to'], $data['message']);
        } catch (RuntimeException $e) {
            return response()->json(['message' => $e->getMessage()], 502);
        }

        return response()->json(['sid' => $sid]);
    }
}
CSS
Route::post('/sms/send', [SmsController::class, 'send'])->middleware(['auth', 'throttle:5,1']);

A throttle matters here because every SMS costs money and attackers abuse open SMS endpoints.

Step 6: Send a test message

Code
php artisan tinker
CSS
app(\App\Services\SmsService::class)->send('+923001234567', 'Hello from Laravel 13');

Use a verified number if you are on a trial. The call returns a SID that starts with SM.

How do I test it without sending SMS?

Bind a fake service in the container so the controller never reaches Twilio:

JavaScript
$this->mock(\App\Services\SmsService::class, function ($mock) {
    $mock->shouldReceive('send')->once()->with('+923001234567', 'Hi')->andReturn('SM123');
});

$this->actingAs(\App\Models\User::factory()->create())
    ->postJson('/sms/send', ['to' => '+923001234567', 'message' => 'Hi'])
    ->assertOk()
    ->assertJson(['sid' => 'SM123']);

Should I send SMS from a queue?

For anything that is not an instant one-off, yes. Dispatch a queued job so a slow Twilio response does not hold up the web request and failed jobs can retry. The job calls the same SmsService.

Common mistakes

  • Number without the plus sign or country code: Twilio rejects it. Validate E.164.
  • Unverified recipient on a trial account: the request fails until the number is verified or the account is upgraded.
  • Sender number not SMS-capable: pick a number that supports SMS in the destination country.
  • Leaking the Auth Token: keep it in .env and rotate it if it was ever exposed.
  • No rate limit: an open endpoint can burn your balance quickly.

FAQ

Can I use a Messaging Service instead of a number?

Yes. Pass messagingServiceSid in the options instead of from.

How do I know if the SMS was delivered?

The create call only confirms that Twilio accepted the message. For delivery status, configure a status callback URL or look up the message by SID.

Is there a Laravel notification channel for Twilio?

There is a community notification channel, but the SDK approach above has fewer dependencies and works the same way for simple cases.

References

Article Index & Topic Tags
LaravelApiTwilioSms

YouTube Channel

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Muhammad Yasir Amin
Available for Contracts
Author & Solutions Architect

Senior Full Stack Engineer

Independent Senior Full Stack Engineer working on Laravel, React and Next.js applications, APIs and delivery workflows.

Laravel & PHP ApplicationsReact & Next.js InterfacesREST APIs & IntegrationsDatabase Queries & DebuggingDocker Development WorkflowsClear Scope & Handover
Discuss Your Next Step

What Does Your Application Need Next?

Share your current system, the problem you want to solve and what a useful result looks like. We can identify the right starting point and agree on a practical scope.

Technical Audit

Find the Next Useful Fix

Application Development

Scoped, Reviewable Milestones

Ongoing Support

Agreed Capacity and Priorities

Share your goals, current stack and requirements before the call.