Search by

devriyad / giosms

riyadMunauwar

Official PHP SDK for GioSMS — Send SMS easily from any PHP or Laravel application.

v1.0.1 2026-02-14 14:39 UTC

This package is auto-updated.

Last update: 2026-09-14 16:10:14 UTC


README

Latest Version on Packagist PHP Version License

The official PHP SDK for GioSMS — a fast, reliable SMS gateway for Bangladesh. Works with Laravel 9+ (zero config, auto-discovery) and any standalone PHP 8.1+ project.

Table of Contents

Requirements

  • PHP 8.1 or higher
  • Guzzle 7.x (installed automatically via Composer)
  • A GioSMS account and API token from api.giosms.com

Installation

composer require devriyad/giosms

That's it. Guzzle is pulled in automatically if you don't already have it.

Setup — Laravel

Zero config. The service provider and facade are auto-discovered. No need to edit config/app.php.

Step 1: Add credentials to .env

GIOSMS_TOKEN=your-api-token-here
GIOSMS_SENDER_ID=MyBrand
# GIOSMS_SSL_VERIFY=false  # uncomment for local dev without SSL
Variable Required Description
GIOSMS_TOKEN Yes Your API bearer token from the GioSMS dashboard
GIOSMS_SENDER_ID No Default sender ID (max 16 chars). Can be overridden per request.
GIOSMS_BASE_URL No API base URL. Default: https://api.giosms.com/api/v1
GIOSMS_TIMEOUT No Request timeout in seconds. Default: 30
GIOSMS_SSL_VERIFY No SSL certificate verification. Default: true. Set false for local dev.

Step 2 (Optional): Publish the config file

php artisan vendor:publish --tag=giosms-config

This creates config/giosms.php if you need to customize anything beyond .env variables.

Step 3: Start sending

use GioSMS\Facades\GioSMS;

GioSMS::send([
    'to'      => '8801712345678',
    'message' => 'Hello from GioSMS!',
]);

Setup — Standalone PHP (Without Laravel)

For any PHP project that doesn't use Laravel — plain PHP, Symfony, CodeIgniter, Slim, etc.

Option A: Pass config directly

<?php

require __DIR__ . '/vendor/autoload.php';

use GioSMS\GioSMS;

$sms = new GioSMS([
    'token'     => 'your-api-token-here',
    'sender_id' => 'MyBrand',    // optional default sender ID
    'timeout'   => 30,           // optional, seconds (default: 30)
    // 'ssl_verify' => false,    // uncomment for local dev without SSL
]);

// Send an SMS
$result = $sms->send([
    'to'      => '8801712345678',
    'message' => 'Hello from GioSMS!',
]);

print_r($result);

Option B: Use a .env file (recommended for production)

If you want to keep secrets out of your code, use the popular vlucas/phpdotenv package:

composer require vlucas/phpdotenv

Create a .env file in your project root:

GIOSMS_TOKEN=your-api-token-here
GIOSMS_SENDER_ID=MyBrand

Then load it in your code:

<?php

require __DIR__ . '/vendor/autoload.php';

use Dotenv\Dotenv;
use GioSMS\GioSMS;

// Load .env file
$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();

$sms = new GioSMS([
    'token'     => $_ENV['GIOSMS_TOKEN'],
    'sender_id' => $_ENV['GIOSMS_SENDER_ID'] ?? null,
]);

$result = $sms->send([
    'to'      => '8801712345678',
    'message' => 'Hello from GioSMS!',
]);

print_r($result);

Note: Add .env to your .gitignore so your API token is never committed to version control.

Constructor Parameters

Key Type Required Default Description
token string Yes — Your GioSMS API bearer token
sender_id string No null Default sender ID. Can be overridden per request.
base_url string No https://api.giosms.com/api/v1 API base URL
timeout int No 30 HTTP request timeout in seconds
ssl_verify bool No true SSL certificate verification. Set false for local dev without SSL.

Usage

All examples below use the Laravel Facade syntax. For standalone PHP, replace GioSMS::method(...) with $sms->method(...) where $sms is your new GioSMS([...]) instance.

Send Single SMS

use GioSMS\Facades\GioSMS;

$result = GioSMS::send([
    'to'        => '8801712345678',
    'message'   => 'Your order has been shipped!',
    'sender_id' => 'ShopName',      // optional, overrides default
    'type'      => 'transactional', // optional, defaults to 'transactional'
]);

echo $result['data']['message_id']; // "msg_abc123def456"
echo $result['data']['cost'];       // 0.25

Parameters

Key Type Required Description
to string Yes Phone number with country code (e.g. 8801712345678)
message string Yes Message body. Max 1000 characters.
sender_id string No Override default sender ID. Max 16 characters.
type string No otp, transactional, or promotional. Default: transactional

Send OTP (High Priority)

OTP messages are processed in the highest priority queue for the fastest possible delivery.

$result = GioSMS::otp([
    'to'      => '8801712345678',
    'message' => 'Your verification code is 9182. Valid for 5 minutes.',
]);

The type is automatically set to otp — you don't need to specify it.

Send Bulk SMS

Send the same message to multiple phone numbers at once. Pass to as an array — the SDK handles the comma-separated conversion.

$result = GioSMS::bulk([
    'to' => [
        '8801712345678',
        '8801812345678',
        '8801912345678',
    ],
    'message'   => 'Flash sale! 50% off today only.',
    'sender_id' => 'MyBrand',
    'type'      => 'promotional', // optional, defaults to 'promotional'
]);

// Track this batch
echo $result['data']['batch_id'];          // "batch_m1abc_7kR4xWz9pQ2n"
echo $result['data']['total_recipients'];  // 3
echo $result['data']['total_cost_reserved']; // 0.75

Send to Contacts

Send to contacts stored in your GioSMS account by their IDs.

$result = GioSMS::toContacts([
    'contact_ids' => [1, 2, 3, 45, 67],
    'message'     => 'Hello from GioSMS!',
    'sender_id'   => 'MyBrand',
    'type'        => 'transactional', // optional, defaults to 'transactional'
]);

Send to Groups

Send to all contacts in one or more groups. Duplicate phone numbers across groups are automatically deduplicated by the API.

// With a message body
$result = GioSMS::toGroups([
    'group_ids' => [1, 2],
    'message'   => 'Monthly newsletter is here!',
]);

// Or with a pre-approved template
$result = GioSMS::toGroups([
    'group_ids'   => [1, 2],
    'template_id' => 5,
    'sender_id'   => 'MyBrand',
]);

Provide either message or template_id, not both.

Check Delivery Status

$result = GioSMS::status([
    'message_id' => 'msg_abc123def456',
]);

echo $result['data']['status'];       // "delivered"
echo $result['data']['delivered_at'];  // "2026-02-10T12:00:03+00:00"

Status flow: queued → submitted → delivered or failed

Check Balance & Cost Estimate

// Check balance
$result = GioSMS::balance();

echo $result['data']['balance'];            // 1250.50
echo $result['data']['currency'];           // "BDT"
echo $result['data']['rates']['masking'];   // 0.50
echo $result['data']['rates']['non_masking']; // 0.25

// Estimate cost for a specific message
$result = GioSMS::balance([
    'message' => 'Hello World',
]);

echo $result['data']['estimate']['sms_count'];              // 1
echo $result['data']['estimate']['encoding'];               // "gsm"
echo $result['data']['estimate']['cost_non_masking'];       // 0.25
echo $result['data']['estimate']['can_send_count_masking']; // 2501

Batch Tracking

// Get report for a specific batch
$result = GioSMS::batch([
    'batch_id' => 'batch_m1abc_7kR4xWz9pQ2n',
]);

echo $result['data']['status'];       // "completed" or "processing"
echo $result['data']['total_sent'];   // 4900
echo $result['data']['total_failed']; // 88

// If still processing, live_stats will be present:
// $result['data']['live_stats']['delivered']
// $result['data']['live_stats']['pending']

// List all active (in-progress) batches
$result = GioSMS::activeBatches();

echo $result['data']['count']; // number of active batches

// Get batch history (most recent first)
$result = GioSMS::batchHistory();                  // default: 20 records
$result = GioSMS::batchHistory(['limit' => 50]);   // up to 100

Health Check

Check if the GioSMS API is up. This endpoint requires no authentication.

$result = GioSMS::health();

echo $result['status'];  // "ok"
echo $result['version']; // "v1"

Error Handling

The SDK throws specific exceptions for each error type. All exceptions extend GioSMSException, so you can catch them broadly or specifically.

use GioSMS\Facades\GioSMS;
use GioSMS\Exceptions\AuthenticationException;
use GioSMS\Exceptions\InsufficientBalanceException;
use GioSMS\Exceptions\ValidationException;
use GioSMS\Exceptions\RateLimitException;
use GioSMS\Exceptions\GioSMSException;

try {
    $result = GioSMS::send([
        'to'      => '8801712345678',
        'message' => 'Hello!',
    ]);
} catch (AuthenticationException $e) {
    // 401 — Your API token is invalid or missing
    // Fix: Check GIOSMS_TOKEN in your .env
} catch (InsufficientBalanceException $e) {
    // 402 — Not enough balance to send this message
    // Fix: Top up your GioSMS account
} catch (ValidationException $e) {
    // 400/422 — Invalid request parameters
    // Fix: Check required fields (to, message, sender_id)
} catch (RateLimitException $e) {
    // 429 — Too many requests
    // Fix: Slow down or use bulk() for multiple numbers
} catch (GioSMSException $e) {
    // Catch-all for any other API/network error (404, 500, timeouts, etc.)
    echo $e->getMessage(); // Human-readable error from the API
    echo $e->getCode();    // HTTP status code
}

Standalone PHP — same approach:

use GioSMS\GioSMS;
use GioSMS\Exceptions\GioSMSException;

$sms = new GioSMS(['token' => 'your-token', 'sender_id' => 'MyBrand']);

try {
    $sms->send([
        'to'      => '8801712345678',
        'message' => 'Hello!',
    ]);
} catch (GioSMSException $e) {
    echo "SMS failed: " . $e->getMessage();
}

Laravel Dependency Injection

Instead of using the Facade, you can type-hint GioSMS anywhere Laravel resolves dependencies — controllers, jobs, commands, etc.

use GioSMS\GioSMS;
use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function store(Request $request, GioSMS $sms): JsonResponse
    {
        $order = Order::create($request->validated());

        $sms->send([
            'to'      => $order->phone,
            'message' => "Order #{$order->id} confirmed! Total: ৳{$order->total}",
        ]);

        return response()->json($order, 201);
    }
}

In a queued job:

use GioSMS\GioSMS;

class SendOrderConfirmation implements ShouldQueue
{
    public function __construct(
        private Order $order,
    ) {}

    public function handle(GioSMS $sms): void
    {
        $sms->send([
            'to'      => $this->order->phone,
            'message' => "Order #{$this->order->id} has been shipped!",
            'type'    => 'transactional',
        ]);
    }
}

Reference

All Methods at a Glance

Method Description Returns
send(array $params) Send single SMS Message data with message_id
otp(array $params) Send OTP (high priority) Message data with message_id
bulk(array $params) Send to multiple numbers Batch data with batch_id
toContacts(array $params) Send to contact IDs Batch data with batch_id
toGroups(array $params) Send to group IDs Batch data with batch_id
status(array $params) Get delivery status Status data
balance(array $params) Check balance / estimate cost Balance and rates data
batch(array $params) Get batch report Batch stats with live progress
activeBatches() List active batches Array of active batches
batchHistory(array $params) Get batch history Array of past batches
health() API health check Status and version

SMS Types & Priority

Type Value Queue Priority Best For
OTP otp 🔴 Highest One-time passwords, verification codes
Transactional transactional 🟡 Medium Order confirmations, alerts, notifications
Promotional promotional 🟢 Low Marketing campaigns, offers, newsletters

Default type is transactional for send(), otp(), and toContacts(), and promotional for bulk() and toGroups().

Encoding & Character Limits

Encoding Single SMS Multipart (per part) Triggered By
GSM 7-bit 160 chars 153 chars Latin-only text
Unicode (UCS-2) 70 chars 67 chars Bengali, Arabic, emoji, etc.

Encoding is detected automatically by the API based on your message content. No configuration needed.

HTTP Status Codes & Exceptions

HTTP Code Exception Class Meaning
200 — Success
202 — Accepted — SMS queued for delivery
400 ValidationException Bad request — check your parameters
401 AuthenticationException Invalid or missing API token
402 InsufficientBalanceException Not enough balance
404 GioSMSException Resource not found (wrong message_id, batch_id, etc.)
422 ValidationException Validation error
429 RateLimitException Rate limit exceeded
500 GioSMSException Server error — try again later

License

MIT — see LICENSE for details.

Built with ❤️ by Riyad Munauwar