SMS Gateway DocumentationCellular v2.0
Enterprise Cellular SMS Gateway

SIM-Powered OTP &
Transactional SMS Engine.

Eliminate expensive 3rd-party aggregator markups (৳0.35 - ৳0.50 per SMS). SwapnoPay turns your Android device and carrier SIM cards (GP, Banglalink, Robi, Teletalk) into a secure, ultra-low-latency, zero-cost cellular SMS dispatch engine for websites, e-commerce, and mobile apps.

Start integrating

Platform Mechanism & Architecture

SwapnoPay's cellular gateway bridges cloud HTTP REST APIs with physical Android handset SIM hardware over resilient WebSockets and background polling.

sim_card Zero Aggregator Surcharges

Unlike SMS aggregators that charge ৳0.30 to ৳0.55 per message, SwapnoPay dispatches via your Android phone's unlimited carrier SMS bundles (e.g. 1000 SMS for ৳25), slashing communication costs by 95%+.

sync_alt Dual-Channel Push Bridge

Incoming API requests immediately fire real-time WebSocket events (sms_gateway_dispatch) to your connected Android phone. If connectivity flutters, the device polls /device/pending automatically.

security Cryptographic OTP Lifecycle

Built-in CSPRNG 4-8 digit numeric code generation, configurable TTL expiry (default 5 mins), automatic background garbage cleanup, and 5-attempt anti-brute-force lockout protection.

System Sequence & Flowchart

End-to-end cellular dispatch pipeline from external website request to Android SIM transmission and delivery receipt.

┌────────────────────┐          ┌──────────────────────┐          ┌────────────────────────┐          ┌────────────────────┐
│  Client Website /  │          │   SwapnoPay Backend  │          │ Merchant Android Phone │          │  Customer Mobile   │
│   E-Commerce App   │          │ (REST API + WS Core) │          │  (Cellular SIM Worker) │          │  (End-User Device) │
└─────────┬──────────┘          └──────────┬───────────┘          └───────────┬────────────┘          └─────────┬──────────┘
          │                                │                                  │                                 │
          │ 1. POST /send-otp or /send     │                                  │                                 │
          │    (x-api-key: sp_gw_m_...)    │                                  │                                 │
          ├───────────────────────────────>│                                  │                                 │
          │                                │ 2. Cryptographic Code Gen        │                                 │
          │                                │    Enqueue Job (QUEUED)          │                                 │
          │                                │                                  │                                 │
          │ 3. 200 OK (otp_id, job_id)     │                                  │                                 │
          │<───────────────────────────────┤                                  │                                 │
          │                                │ 4. WS 'sms_gateway_dispatch'     │                                 │
          │                                ├─────────────────────────────────>│                                 │
          │                                │    (Fallback: GET /pending)      │                                 │
          │                                │                                  │ 5. SmsManager.sendTextMessage() │
          │                                │                                  ├────────────────────────────────>│
          │                                │                                  │    via Carrier SIM (GP/Robi/BL) │
          │                                │                                  │                                 │
          │                                │ 6. POST /device/status (SENT)    │                                 │
          │                                │<─────────────────────────────────┤                                 │
          │                                │                                  │                                 │
          │ 7. Webhook: 'sms.status_update'│                                  │                                 │
          │<───────────────────────────────┤                                  │                                 │
          │                                │                                  │                                 │
          │ 8. POST /verify-otp (phone,code)                                  │                                 │
          ├───────────────────────────────>│                                  │                                 │
          │                                │ 9. Check single-use, TTL,        │                                 │
          │                                │    & attempts (<=5)              │                                 │
          │ 10. 200 OK (verified: true)    │                                  │                                 │
          │<───────────────────────────────┤                                  │                                 │
          │                                │                                  │                                 │
          

Aggregators vs. SwapnoPay Cellular SIM

Why modern Bangladeshi businesses are shifting from predatory aggregator markups to in-house cellular SIM dispatch.

Feature Metric Traditional SMS Aggregators SwapnoPay Cellular Gateway
Cost Per SMS ৳0.35 – ৳0.65 per SMS ৳0.00 (Flat Carrier Bundle: ~৳0.02)
Regulatory Bureaucracy Requires trade license, BTRC approvals & weeks of verification Zero approval waiting. Plug-and-play in 30 seconds.
Carrier Coverage Restricted by gateway routing filters All BD networks: Grameenphone, Robi, Banglalink, Teletalk
Delivery Latency 3 – 15 seconds (queued via aggregators) 1 – 3 seconds direct cellular transmission
Data Privacy Customer phone numbers stored on third-party aggregator clouds 100% self-hosted merchant privacy & direct SIM dispatch

Authentication & Request Headers

Authenticate all external requests with your dedicated Merchant Gateway API Key.

Header Name Type Description
x-api-key string Your unique gateway key starting with sp_gw_m_<merchant_id>_...
Authorization string Alternative bearer token format: Bearer <API_KEY>
Content-Type string Must be set to application/json.

Core API Endpoints Reference

RESTful endpoints for OTP generation, verification, arbitrary notification broadcasts, and device telemetry.

POST /v1/sms-gateway/send-otp

Generates a cryptographically random numeric OTP, configures expiration TTL, saves it to the memory registry, and dispatches the SMS to the connected Android device via WebSockets.

Request Body Parameters:
FieldTypeDefaultDescription
phonestringRequiredRecipient Bangladeshi phone number (e.g. 01712963652).
purposestring"Verification"Action context (e.g. "Login", "Order #1029", "Withdrawal").
expiryMinutesnumber5OTP validity duration in minutes.
lengthnumber6Digit length for the code (between 4 and 8).
templatestringBengali DefaultCustom template string. Replaces {code} or {otp}.
{
  "phone": "01712963652",
  "purpose": "Customer Login Verification",
  "expiryMinutes": 5,
  "length": 6,
  "template": "Your SwapnoPay verification code is: {code}. Valid for 5 minutes. Never share this."
}
Response (200 OK):
{
  "ok": true,
  "otp_id": "otp_a4f891b2c3d4e5f6",
  "job_id": "job_99812e4f01bc4a77",
  "phone": "01712963652",
  "purpose": "Customer Login Verification",
  "expires_in_seconds": 300,
  "message": "OTP queued for SIM dispatch"
}
POST /v1/sms-gateway/verify-otp

Validates the code entered by the user. Enforces strict single-use consumption and automatic invalidation after 5 unsuccessful attempts.

{
  "phone": "01712963652",
  "code": "582914",
  "purpose": "Customer Login Verification"
}
Success Response (200 OK):
{
  "ok": true,
  "verified": true,
  "phone": "01712963652",
  "purpose": "Customer Login Verification",
  "message": "OTP verified successfully"
}
Incorrect Code Response (400 Bad Request):
{
  "ok": false,
  "verified": false,
  "error": "Incorrect OTP code",
  "remaining_attempts": 4
}
POST /v1/sms-gateway/send

Broadcasts custom transactional notifications such as order shipping tracking, receipt confirmations, and account security alerts via your phone's SIM.

{
  "phone": "01712963652",
  "message": "Dear Tanvir, your order #ORD-9812 has been packed and handed to Pathao Courier. Tracking: https://track.example.com/9812",
  "priority": "HIGH",
  "webhook_url": "https://merchant.example.com/webhooks/sms-delivery"
}
Response (200 OK):
{
  "ok": true,
  "job_id": "job_c18091ab42ef7a",
  "phone": "01712963652",
  "status": "QUEUED",
  "message": "Message queued for SIM cellular dispatch"
}
GET /v1/sms-gateway/stats

Inspect real-time gateway throughput, check if your Android handset is online via live heartbeat telemetry, and monitor queue depth.

{
  "ok": true,
  "merchant_id": "00000000-0000-0000-0000-000000000001",
  "device_online": true,
  "stats": {
    "queued": 0,
    "sent": 1420,
    "failed": 2,
    "total_handled": 1422,
    "active_otps": 3
  }
}

phone_android Android Handset Protocol Endpoints

These endpoints are utilized by the SwapnoPay Android background service when operating in polling mode or reporting carrier transmission status.

GET /v1/sms-gateway/device/pending?merchant_id={id}

Fetches up to 20 queued SMS jobs and atomically sets their status to IN_PROGRESS.

POST /v1/sms-gateway/device/status

Reports transmission outcome (SENT or FAILED). Automatically invokes developer webhook_url if specified.

⚠️ Gateway Error Codes Reference
Error Code HTTP Status Description & Suggested Action
Unauthorized 401 Missing or invalid x-api-key header. Check your merchant portal settings.
Valid phone number is required 400 Recipient phone number must be a valid 11-digit Bangladeshi mobile format.
No active OTP request found 404 No pending OTP code exists for this number, or it was already verified.
OTP has expired 410 The OTP TTL window elapsed. Prompt user to request a fresh OTP code.
Incorrect OTP code 400 Supplied code does not match. Displays remaining attempts (out of 5).
Too many incorrect attempts 429 Anti-bruteforce trigger. Maximum 5 attempts exceeded; OTP code immediately invalidated.

Delivery Status Webhook Callbacks

Receive asynchronous HTTP delivery receipts directly to your server once the Android cellular SIM transmits the message.

When dispatching messages with a webhook_url specified, SwapnoPay immediately delivers an HTTP POST callback to your endpoint when the Android carrier network confirms dispatch:

{
  "event": "sms.status_update",
  "job_id": "job_c18091ab42ef7a",
  "phone": "01712963652",
  "status": "SENT",
  "sent_at": 1773919283120,
  "error": null
}

Webhook Handler Example (Node.js Express):

app.post('/webhooks/sms-delivery', (req, res) => {
  const { event, job_id, phone, status, sent_at, error } = req.body;

  if (event === 'sms.status_update') {
    if (status === 'SENT') {
      console.log(`[SMS Delivered] Job: ${job_id} to ${phone} at ${new Date(sent_at).toISOString()}`);
    } else {
      console.error(`[SMS Failed] Job: ${job_id} failed with error: ${error}`);
    }
  }

  // Acknowledge receipt to avoid retries
  res.status(200).json({ received: true });
});

Production SDK Code Examples

Copy-paste production integrations in cURL, Node.js, Python, PHP, and Kotlin.

terminal cURL (Shell / Terminal)
# 1. Request OTP Dispatch
curl -X POST https://pay.swapnopay.top/v1/sms-gateway/send-otp \
  -H "Content-Type: application/json" \
  -H "x-api-key: sp_gw_m_000000000001_live_secret" \
  -d '{
    "phone": "01712963652",
    "purpose": "Website Login",
    "expiryMinutes": 5,
    "length": 6
  }'

# 2. Verify User OTP
curl -X POST https://pay.swapnopay.top/v1/sms-gateway/verify-otp \
  -H "Content-Type: application/json" \
  -H "x-api-key: sp_gw_m_000000000001_live_secret" \
  -d '{
    "phone": "01712963652",
    "code": "582914"
  }'
🟢 Node.js (Axios / Fetch)
const axios = require('axios');

const SMS_API = axios.create({
  baseURL: 'https://pay.swapnopay.top/v1/sms-gateway',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'sp_gw_m_000000000001_live_secret'
  }
});

// 1. Dispatch OTP
async function sendUserOtp(phone) {
  const { data } = await SMS_API.post('/send-otp', {
    phone,
    purpose: 'Password Reset',
    expiryMinutes: 5,
    length: 6,
    template: 'Your verification code is {code}. Never share it with anyone.'
  });
  return data;
}

// 2. Verify OTP
async function verifyUserOtp(phone, code) {
  try {
    const { data } = await SMS_API.post('/verify-otp', { phone, code });
    return data.verified === true;
  } catch (err) {
    console.error('OTP Check failed:', err.response?.data?.error);
    return false;
  }
}
code Python (Requests / FastAPI)
import requests

BASE_URL = "https://pay.swapnopay.top/v1/sms-gateway"
HEADERS = {
    "Content-Type": "application/json",
    "x-api-key": "sp_gw_m_000000000001_live_secret"
}

def send_otp(phone: str) -> dict:
    resp = requests.post(f"{BASE_URL}/send-otp", headers=HEADERS, json={
        "phone": phone,
        "purpose": "Account Activation",
        "expiryMinutes": 5,
        "length": 6
    })
    return resp.json()

def verify_otp(phone: str, code: str) -> bool:
    resp = requests.post(f"{BASE_URL}/verify-otp", headers=HEADERS, json={
        "phone": phone,
        "code": code
    })
    return resp.json().get("verified", False)
code PHP (cURL / Laravel)
<?php
function sendSwapnoPayOtp($phone) {
    $ch = curl_init('https://pay.swapnopay.top/v1/sms-gateway/send-otp');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'x-api-key: sp_gw_m_000000000001_live_secret'
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'phone' => $phone,
        'purpose' => 'Checkout Verification',
        'expiryMinutes' => 5,
        'length' => 6
    ]));
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode($res, true);
}
?>
phone_android Kotlin (Android OkHttp)
val client = OkHttpClient()
val payload = JSONObject().apply {
    put("phone", "01712963652")
    put("purpose", "App Security Pin Reset")
    put("expiryMinutes", 5)
    put("length", 6)
}

val request = Request.Builder()
    .url("https://pay.swapnopay.top/v1/sms-gateway/send-otp")
    .addHeader("Content-Type", "application/json")
    .addHeader("x-api-key", "sp_gw_m_000000000001_live_secret")
    .post(payload.toString().toRequestBody("application/json".toMediaType()))
    .build()

client.newCall(request).execute().use { response ->
    val responseBody = response.body?.string()
    println("Gateway Response: $responseBody")
}

Android Background Service & Dual-SIM Setup

Configuring your dedicated Android dispatch device for 24/7 autonomous transmission and battery optimization bypass.

battery_saver Battery Optimization Whitelist

To prevent Android OS (specifically Samsung OneUI, Xiaomi MIUI, and Android 14+ Doze Mode) from freezing background sockets, navigate to:

Settings > Apps > SwapnoPay > Battery > Unrestricted

The app also requests REQUEST_IGNORE_BATTERY_OPTIMIZATIONS upon device pairing.

sim_card_download Dual-SIM Subscription Selection

The cellular gateway leverages Android's SubscriptionManager to dynamically route through SIM 1 or SIM 2 based on carrier bundle balance:

val smsManager = SmsManager.getSmsManagerForSubscriptionId(subId)

Set your preferred default SIM slot inside the SwapnoPay Android app settings.