Guide

SMS API Integration Guide: PHP, Laravel, Node.js, Python & Flutter

12 min read

Complete developer guide to sending SMS via REST API — copy-paste examples for PHP, Laravel, Node.js, Python, and Flutter OTP integration.

PHPLaravelNode.jsPythonFlutterOTPREST API

Short answer: To send SMS via API, POST JSON to https://api.smsprovider.net/api/send-sms with yourapi_key, approved sender_id, Bangladesh phone number, and message text. Every language below follows the same REST contract — only the HTTP client differs.

SMS Provider uses a single REST endpoint for transactional SMS, OTP, and alerts in Bangladesh. This guide covers production-ready examples for PHP, Laravel,Node.js, Python, and a Flutter OTP flow where your backend holds the API key.

Prerequisites: Verified account, API key fromDashboard → API Key, approved sender ID, and sufficient balance. See the full API documentation for parameters and error codes.

How to Send SMS Using PHP

PHP is widely used for Bangladeshi e-commerce, billing, and OTP systems. The simplest approach iscURL with JSON — no extra packages required on most hosting.

  1. Store SMS_API_KEY in your environment or .env file — never commit it to Git.
  2. Validate the phone number before calling the API (must start with 01 and be 11 digits).
  3. POST to https://api.smsprovider.net/api/send-sms and persist the returned message_id.
  4. Handle 402 (low balance) and 429 (rate limit) with retry logic.
PHP — send SMS with cURL
php
<?php

function sendSms(string $phone, string $message, string $senderId = 'YourBrand'): array
{
    $payload = [
        'api_key' => getenv('SMS_API_KEY'),
        'sender_id' => $senderId,
        'phone' => $phone,
        'message' => $message,
    ];

    $ch = curl_init('https://api.smsprovider.net/api/send-sms');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Accept: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode($payload),
        CURLOPT_TIMEOUT => 15,
    ]);

    $response = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $data = json_decode($response, true) ?? [];

    if ($status === 200 && ($data['success'] ?? false)) {
        return ['ok' => true, 'message_id' => $data['message_id']];
    }

    return ['ok' => false, 'error' => $data['message'] ?? 'SMS request failed'];
}

// Send OTP
$result = sendSms('01712345678', 'Your verification code is 482910. Valid for 5 minutes.');

Laravel SMS API Guide

In Laravel, wrap the HTTP call in a dedicated service class. Use config() for credentials and Laravel's built-in Http facade for clean, testable code.

1. Configure credentials

config/services.php
php
# config/services.php
'sms' => [
    'endpoint' => env('SMS_ENDPOINT', 'https://api.smsprovider.net/api/send-sms'),
    'api_key' => env('SMS_API_KEY'),
    'sender_id' => env('SMS_SENDER_ID', 'YourBrand'),
],

2. Create an SmsService

app/Services/SmsService.php
php
<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class SmsService
{
    public function send(string $phone, string $message, ?string $senderId = null): string
    {
        $response = Http::acceptJson()
            ->timeout(15)
            ->post(config('services.sms.endpoint'), [
                'api_key' => config('services.sms.api_key'),
                'sender_id' => $senderId ?? config('services.sms.sender_id'),
                'phone' => $phone,
                'message' => $message,
            ]);

        if ($response->successful() && $response->json('success')) {
            return $response->json('message_id');
        }

        Log::warning('SMS failed', [
            'phone' => $phone,
            'status' => $response->status(),
            'body' => $response->json(),
        ]);

        throw new \RuntimeException($response->json('message', 'SMS delivery failed'));
    }
}

Inject SmsService into your auth controller. For OTP, generate the code server-side, send via SMS, and store in Cache::put() with a 300-second TTL. Rate-limit the/send-otp route to prevent abuse.

Node.js SMS API

Node.js fits microservices, serverless functions, and Express/Fastify backends. Use the nativefetch API (Node 18+) or axios in older versions.

  • Keep SMS_API_KEY in process environment — use AWS Secrets Manager or similar in production.
  • Return generic errors to clients; log detailed SMS API responses server-side only.
  • Respect the 60 requests/minute rate limit per API key.
Node.js — Express OTP endpoint
javascript
import 'dotenv/config';

const SMS_ENDPOINT = process.env.SMS_ENDPOINT ?? 'https://api.smsprovider.net/api/send-sms';

export async function sendSms(phone, message, senderId = 'YourBrand') {
  const response = await fetch(SMS_ENDPOINT, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
    },
    body: JSON.stringify({
      api_key: process.env.SMS_API_KEY,
      sender_id: senderId,
      phone,
      message,
    }),
  });

  const data = await response.json();

  if (!response.ok || !data.success) {
    throw new Error(data.message ?? `SMS failed (${response.status})`);
  }

  return data.message_id;
}

// Express route — always send OTP from your server, never from the app
app.post('/auth/send-otp', async (req, res) => {
  const otp = String(Math.floor(100000 + Math.random() * 900000));
  await storeOtp(req.body.phone, otp);
  const messageId = await sendSms(req.body.phone, `Your code is ${otp}. Expires in 5 min.`);
  res.json({ ok: true, message_id: messageId });
});

Python SMS API

Python integrations commonly run on Django, FastAPI, or Flask. The requests library is sufficient for synchronous OTP sends; use httpx for async FastAPI routes.

Python — send SMS with requests
python
import os
import requests

SMS_ENDPOINT = os.getenv("SMS_ENDPOINT", "https://api.smsprovider.net/api/send-sms")

def send_sms(phone: str, message: str, sender_id: str = "YourBrand") -> str:
    response = requests.post(
        SMS_ENDPOINT,
        json={
            "api_key": os.environ["SMS_API_KEY"],
            "sender_id": sender_id,
            "phone": phone,
            "message": message,
        },
        headers={"Accept": "application/json"},
        timeout=15,
    )
    data = response.json()

    if response.status_code == 200 and data.get("success"):
        return data["message_id"]

    raise RuntimeError(data.get("message", "SMS request failed"))

# Django view example
def send_otp_view(request):
    otp = f"{random.randint(100000, 999999):06d}"
    message_id = send_sms(request.POST["phone"], f"Your code is {otp}. Valid 5 minutes.")
    cache.set(f"otp:{request.POST['phone']}", otp, timeout=300)
    return JsonResponse({"ok": True, "message_id": message_id})

For high-volume batch sending, queue messages with Celery or Redis and process them with exponential backoff on 429 responses.

Flutter OTP SMS Tutorial

Flutter apps must never contain your SMS API key. Mobile binaries can be decompiled; exposing the key allows anyone to send SMS on your balance.

Recommended architecture

  1. User enters phone number in the Flutter app.
  2. App calls your backend (POST /auth/send-otp).
  3. Backend generates OTP, stores it in Redis/database, calls SMS Provider API.
  4. App receives success response and shows OTP input screen.
  5. User submits OTP → backend verifies against stored value.
Flutter — call your backend, not the SMS API
dart
// Flutter calls YOUR backend — never embed the SMS API key in the app.

// Dart (client)
Future<void> requestOtp(String phone) async {
  final res = await http.post(
    Uri.parse('https://your-api.com/auth/send-otp'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode({'phone': phone}),
  );
  if (res.statusCode != 200) throw Exception('Could not send OTP');
}

Optional: use SMS autofill on Android/iOS for better UX, but always validate OTP on the server. See our OTP best practices guide for security details.

Frequently asked questions

How do I send SMS using PHP?

Use PHP cURL or Guzzle to POST JSON to your SMS provider's /send-sms endpoint with api_key, sender_id, phone, and message. Store the API key in environment variables, validate Bangladesh phone format (01XXXXXXXXX), and log the returned message_id for delivery tracking.

Can I call the SMS API directly from Flutter?

No — never put your SMS API key in a Flutter or mobile app. Build a backend endpoint that generates the OTP, calls the SMS API server-side, and returns only a success/failure status to the app.

What phone number format does the SMS API accept?

Bangladesh mobile numbers in local format (01712345678) or international format (8801712345678). Invalid numbers return a 400 error before any balance is charged.

How do I send OTP SMS with Laravel?

Create an SmsService class using Laravel's HTTP client, store credentials in config/services.php, generate a 6-digit OTP in your controller, send it via the service, and store the OTP in cache or database with a 5-minute expiry.

Ready to integrate? Read the full API documentation, create a free account, or contact us on WhatsApp.