Skip to content
Devix Open Source

Guide

Getting started

composer require devix-labs/laravel-sms
php artisan vendor:publish --tag=sms-config
php artisan sms:cost "Your verification code is 1234"
  Encoding ........................................... GSM_7BIT
  Length ........................................... 30 septets
  Parts ..................................................... 1
  Left in this part ....................................... 130

The thing that costs money

An SMS is 160 characters only if every character is in the GSM 03.38 alphabet. One that is not — a curly quote out of a word processor, an emoji, a single Arabic letter — and the whole message is sent as UCS-2 and the limit drops to 70.

A 160-character message that was one part becomes three. You are billed for three. On every send. Until somebody notices.

php artisan sms:cost "It’s ready — collect any time"
  Encoding ............................................. UTF16
  Parts .................................................... 1

  WARN  Unicode, because of: ’ —
  INFO  Replacing ’ — would make it GSM_7BIT and 1 part.

Nine characters are in the alphabet but cost two septets, because they are reached through an escape: ^ { } \ [ ~ ] | and €. A message of 159 characters with one { in it is two parts.

Set 'sanitise' => true — it is on by default — and the substitutable characters are replaced before the message goes anywhere.

php artisan sms:cost "Your order has shipped" --rate=0.028 --count=50000
  Total for 50,000 recipients .......................... 1,400.00

Sending one

use Devix\Sms\Sender;

$sender->send('0300-1234567', 'Your code is 1234.');

The number is normalised to E.164 against the country in your config, so 0300-1234567 reaches the gateway as +923001234567. Arabic-Indic digits are digits.

As a notification

public function via($notifiable): array
{
    return ['devix-sms'];
}

public function toSms($notifiable): string
{
    return "Your verification code is {$this->code}.";
}
public function routeNotificationForDevixSms(): string
{
    return $this->phone;
}

Sender IDs

An alphanumeric sender ID is eleven characters, and in the UAE, Saudi Arabia, Pakistan, India, Turkey and several other places it has to be registered with the operator before anything sent from it is delivered at all.

Both of those are normally discovered in a delivery report, after a campaign.

use Devix\Sms\SenderId;

SenderId::problems('DEVIXTECHNOLOGIES');   // ['too-long']
SenderId::problems('12345');               // ['all-digits']
SenderId::problems('DEVIX', 'AE');         // ['needs-registration']

Anything that would be rejected outright stops the send. needs-registration is advice — this package cannot know what you have registered, so it does not pretend to.

Gateways

'default' => env('SMS_GATEWAY', 'log'),

log writes the message where you can read it. array remembers it for your tests. http is a gateway you describe rather than install:

'jazz' => [
    'driver' => 'http',
    'url' => 'https://api.example.pk/sendsms',
    'method' => 'GET',
    'params' => [
        'to' => ':to_plain',
        'message' => ':text',
        'sender' => ':from',
        'type' => ':encoding',
        'api_key' => env('SMS_KEY'),
    ],
    'unicode_value' => '2',
    'text_value' => '0',
    'success' => ['contains' => 'OK'],
],

There is effectively nothing on Packagist for Pakistani operators — developifynet/telenor-php has 224 downloads in its lifetime — and writing a class per gateway means a package has to exist for every gateway. This way it is five lines you can check against the operator's own documentation without reading any PHP.

We have not run these against live accounts, and say so. What is guaranteed is everything up to the request: the counting, the encoding flag, the number, the sender ID. Use the array driver to assert exactly what your application would send.

Where to go next

Updated 15 Sep 2026