149 countries · crypto-native · no KYC

Send SMS with Laravel: HTTP Client, Queued Jobs, and Webhooks

$0.035/msg from sub-100ms median 98.6% delivered
Send SMS with Laravel: HTTP Client, Queued Jobs, and Webhooks — smsroute
$0.004
per SMS from
149
countries
60s
to first message
6
crypto rails
To send SMS with Laravel you don't need a package. The framework ships with everything the job requires. The HTTP client makes the API call. Queued jobs handle retries and burst control. Routes receive webhooks. Using them means your SMS layer behaves like the rest of a Laravel app: testable, queueable, observable, instead of a bolted-on integration. We target SMSRoute endpoints below (a no-KYC SMS API with crypto billing using BTC, ETH, USDT, XMR, LTC, SOL, so first send is minutes), but the patterns transfer to any provider. SMSRoute's published route pages list delivery from $0.004/message (premium direct-carrier corridors up to $0.035) with sub-100ms median submission and ~98.6% delivered success (smsroute.cc route pages, 2026). For the authoritative reference, see the IETF idempotency-key draft.

Laravel already has the right tools

What tools does Laravel provide for sending SMS?

Laravel's built-in HTTP Client, Queued Jobs, and Webhooks are all you need to integrate SMSRoute's no-KYC SMS API. No extra packages required. With crypto billing and coverage across 149 countries, you can send your first message in minutes after signing up with just an email.

To send SMS with Laravel you don't need a package — the framework ships with everything the job requires. The HTTP client makes the API call. Queued jobs handle retries and burst control. Routes receive webhooks. Using them means your SMS layer behaves like the rest of a Laravel app — testable, queueable, observable — instead of a bolted-on integration. We target SMSRoute endpoints below (a no-KYC SMS API with crypto billing — BTC, ETH, USDT, XMR, LTC, and SOL — so first send is minutes), but the patterns transfer to any provider. SMSRoute's published route pages list delivery from $0.004/message (premium direct-carrier corridors up to $0.035) with sub-100ms median submission and ~98.6% delivered success (smsroute.cc route pages, 2026). For the authoritative reference, see the IETF idempotency-key draft.

Laravel feature SMS job it does Why
HTTP client (Http::) The send call Built-in timeout, retry, and fake for tests
Queued jobs (ShouldQueue) Retries + off-request sending $tries/$backoff for free; never block a web request
Job rate limiting Stay under provider throughput Smooths bursts, avoids 429s and carrier flags
Routes (api.php) DLR + inbound webhooks Signature-verify then update idempotently
Http::fake() Offline testing Full coverage, zero per-commit spend
// app/Services/Sms.php
use Illuminate\Support\Facades\Http;

class Sms
{
    public function send(string $to, string $text): array
    {
        $res = Http::withToken(config('services.sms.key'))
            ->timeout(10)                     // never hang a request
            ->post('https://api.smsroute.cc/sms/send', [
                'to' => $to, 'from' => 'YourSender', 'message' => $text,
            ]);
        $res->throw();                        // 4xx/5xx -> exception
        return $res->json();                  // generic response object
    }
}

The key comes from config() (backed by an env var), never a literal. The integration-patterns discipline every language shares. And ->timeout(10) is set, because an SMS send blocking a web request is a worse failure than a clean exception. For example, set `SMS_ROUTE=log` in `.env` and add `'sms_route' => env('SMS_ROUTE')` to `config/services.php`.

Queued jobs handle retries and bursts

How do queued jobs improve SMS delivery reliability?

Laravel's queued jobs automatically retry failed SMS sends and handle traffic bursts without blocking your app. Combined with SMSRoute's adaptive multi-route delivery and automatic failover, your messages reach 149 countries reliably. Failed messages are automatically credited back to your balance.

Laravel already has the right tools — comparison diagram

Don't send SMS inline in a controller. Dispatch a job: it moves the send off the request path, gives you Laravel's built-in retry and backoff, and lets the queue throttle bursts under the provider's throughput ceiling. This solves retries and rate limiting at once.

class SendSmsJob implements ShouldQueue
{
    public int $tries = 3;
    public array $backoff = [1, 2, 4];        // seconds, per attempt

    public function __construct(public string $to, public string $text) {}

    public function handle(Sms $sms): void
    {
        $sms->send($this->to, $this->text);   // exception -> auto retry
    }

    public function retryUntil(): \DateTime
    {
        return now()->addSeconds(30);         // cap total time for OTP
    }
}

DLR webhooks as routes

How do DLR webhooks work for SMS delivery tracking?

SMSRoute sends real-time delivery reports (DLR) to your Laravel webhook routes. Simply define a route in your web.php file to receive delivery status updates. This gives you instant visibility into message delivery across 149 countries, with automatic retries and refunds for any failures.

Delivery receipts arrive on a route you expose. Verify the signature, then update state idempotently. The DLR handling and webhook security patterns, expressed in Laravel.

// routes/api.php
Route::post('/sms/dlr', function (Request $r) {
    // verify HMAC signature before trusting anything
    if (! Sms::verify($r->getContent(), $r->header('X-Signature'))) {
        abort(401);
    }
    $dlr = $r->json();
    DeliveryStatus::updateOrCreate(          // idempotent on message id
        ['message_id' => $dlr['id']],
        ['status' => $dlr['status']]
    );
    return response()->noContent();          // ack fast
});

updateOrCreate keyed on the message id gives you idempotency for free. Duplicate and out-of-order DLRs (both normal) resolve to one row. Verify the signature *before* touching the database, so a forged callback never reaches your logic.

Testing with Laravel's HTTP fake

How can I test SMS sending in Laravel without real messages?

Use Laravel's HTTP fake to intercept SMSRoute API calls during testing. Assert that the correct payload was sent to the right endpoint, then verify your queued jobs and webhook handlers work correctly. This lets you build and test your entire SMS workflow without spending any crypto.

Laravel's Http::fake() makes offline testing trivial. No per-commit spend, full coverage of the send and retry paths.

Http::fake([
    'smsroute.cc/*' => Http::response(['id' => 'test_123', 'status' => 'queued'], 200),
]);

(new Sms)->send('+15551234567', 'test');
Http::assertSent(fn ($req) => $req['to'] === '+15551234567');

Assert on response shape and that the right request went out. Fake a 500-then-200 sequence to prove the job retries once and succeeds. Use a fake signature to test the webhook route rejects forgeries. Keep one real send to your own phone as a pre-release smoke test. The full method is in the test-numbers guide. Wire E.164 normalization at your form-request layer, and the Laravel SMS integration is production-shaped end to end.

FAQ

How do I send an SMS in Laravel?
Use the built-in HTTP client — Http::withToken(...)->timeout(10)->post(...) to your provider's endpoint with the key from config(). No package is required. Wrap it in a small service class, and for production dispatch it through a queued job rather than sending inline in a controller.
Should I use a queued job for sending SMS in Laravel?
Yes. A queued SendSmsJob moves the send off the web-request path, gives you Laravel's built-in retry ($tries) and backoff for free, and lets you throttle the worker under the provider's throughput ceiling. Use retryUntil() to cap total time for OTP sends so they don't retry for minutes.
How do I handle SMS delivery webhooks in Laravel?
Expose a POST route, verify the provider's HMAC signature on the raw body before trusting anything (abort 401 on mismatch), then use updateOrCreate keyed on the message id to update delivery status idempotently, and return a fast no-content response. Verify before any database write so forged callbacks never reach your logic.
How do I test Laravel SMS code without sending real messages?
Use Http::fake() to stub the provider endpoint offline, then assert on the request sent and the response handling. Fake a 500-then-200 sequence to test job retries, use a fake signature to confirm your webhook rejects forgeries, and keep just one real send to your own phone as a pre-release smoke test.

Send your first SMS in 5 minutes

No KYC. Pay with BTC, ETH, USDT, XMR, LTC, and SOL. Live routes to 149 countries.

Get an API key →