📡 SMS Gateway API Documentation

Complete guide to sending SMS messages programmatically using your Android device as a gateway. Includes webhook support for real-time delivery tracking.

REST API Webhooks Real-time Tracking 10,000 SMS/day E-commerce Home Automation

📋 Overview

SMS Gateway Master transforms your Android device into a professional SMS gateway. Send SMS messages via a simple REST API and receive real-time delivery updates through webhooks.

How It Works

  1. Your application sends an HTTP request to our API
  2. We validate your API key and subscription status
  3. A push notification (FCM) is sent to your Android device
  4. The app receives the notification and sends the SMS via Android SmsManager
  5. SMS status updates are sent to your webhook URL in real-time
  6. All message details are stored locally on your device (privacy-first)
💡 Key Benefits
  • Use your existing phone number and carrier
  • No third-party SMS provider fees
  • Complete delivery tracking with webhooks
  • Local-first storage for maximum privacy
  • Full control over your SMS infrastructure

Architecture

┌─────────────┐      HTTPS      ┌──────────────┐      FCM Push      ┌─────────────┐
│   Your App  │  ──────────────> │   Firebase   │  ─────────────────> │   Android   │
│             │                  │   Functions  │                     │    Device   │
└─────────────┘                  └──────────────┘                     └──────┬──────┘
       ▲                                                                     │
       │                                                                     │ Send SMS
       │                         Webhook Callback                           │
       └─────────────────────────────────────────────────────────────────────┘

🔐 Authentication

All API requests require authentication using an API key. Include your API key in the request header:

X-API-Key: your_api_key_here

Getting Your API Key

  1. Open SMS Gateway Master app on your Android device
  2. Navigate to Settings → Gateway API
  3. Tap Generate API Key
  4. Copy and securely store your API key
⚠️ Security Notice Keep your API key secret. Never share it publicly or commit it to version control. If compromised, regenerate it immediately from the app settings.

Base URL

https://us-central1-sms-gateway-ae7e1.cloudfunctions.net

🚀 Quick Start

Send your first SMS in under 5 minutes:

1. Install the App

Download SMS Gateway Master from Google Play Store and set it as your default SMS app.

2. Get Your API Key

Generate an API key from the app settings (Settings → Gateway API).

3. Send Your First SMS

cURL Example

curl -X POST https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+1234567890",
    "message": "Hello from SMS Gateway!",
    "webhookUrl": "https://your-server.com/webhook"
  }'

JavaScript Example

const response = await fetch('https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your_api_key_here',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    phoneNumber: '+1234567890',
    message: 'Hello from SMS Gateway!',
    webhookUrl: 'https://your-server.com/webhook'
  })
});

const data = await response.json();
console.log(data);

Python Example

import requests

response = requests.post(
    'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send',
    headers={
        'X-API-Key': 'your_api_key_here',
        'Content-Type': 'application/json'
    },
    json={
        'phoneNumber': '+1234567890',
        'message': 'Hello from SMS Gateway!',
        'webhookUrl': 'https://your-server.com/webhook'
    }
)

print(response.json())

📤 Send SMS

Send an SMS message to a phone number.

POST /api_sms_send

Request Body Parameters

phoneNumber string required

The recipient's phone number in international format (e.g., +1234567890)

message string required

The SMS message content. Maximum 1600 characters (automatically split into multiple SMS if longer).

webhookUrl string optional

URL to receive delivery status updates. Overrides the default webhook set in app settings. Also accepted as serverWebhookUrl (preferred field name).

Response

{
  "smsId": "sms_1707400000000_on1t75e",
  "status": "queued",
  "message": "SMS queued for sending. Status updates will be sent to your webhook.",
  "timestamp": "2026-03-01T12:00:00.000Z"
}

Response Fields

Field Type Description
smsId string Unique identifier for this SMS. Format: sms_<timestamp_ms>_<7-char-alphanumeric>
status string Always "queued" on a successful send response
message string Human-readable confirmation. Varies based on whether a webhook is configured.
timestamp string ISO 8601 timestamp of when the request was processed (e.g. "2026-03-01T12:00:00.000Z")

🔄 Request Status / Retry Failed SMS

Check the current delivery status of a specific SMS. Optionally retry sending if the SMS failed (e.g., sent while in airplane mode).

POST /api_sms_requestStatus

Request current status of an SMS and optionally retry if it failed. Also accepts GET with smsId and retry as query parameters.

Request Headers

HeaderValue
X-API-KeyYour API key
Content-Typeapplication/json

Request Body

smsId string required

The SMS ID returned when the message was sent (e.g., sms_1707400000000_on1t75e).

retry boolean optional

Set to true to retry sending if the SMS is in failed status. Default: false.

Response (Status Check)

{
  "smsId": "sms_1707400000000_on1t75e",
  "status": "pending",
  "message": "Status request sent to device. Check your webhook for updates.",
  "retry": false,
  "timestamp": "2026-03-01T14:30:00.000Z"
}

Response (Retry)

{
  "smsId": "sms_1707400000000_on1t75e",
  "status": "pending",
  "message": "Retry request sent to device. If SMS was failed, it will be resent.",
  "retry": true,
  "timestamp": "2026-03-01T14:30:00.000Z"
}

How It Works

  1. API sends a push notification to your device
  2. The app checks the SMS status in its local database
  3. Current status is sent to your webhook URL
  4. If retry=true and SMS is failed, the app resends the SMS automatically

Retry Flow

When retry=true and the SMS has failed status:

webhook: status=retrying → status=sending → status=sent → status=delivered
                                                        ↘ status=failed (if retry also fails)
💡 Use Case: If you sent SMS while the phone was in airplane mode or had no signal, all messages will fail. Use this endpoint with retry=true to resend them once connectivity is restored.

Example: Check Status (cURL)

curl -X POST \
  https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_requestStatus \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"smsId": "sms_1707400000000_on1t75e"}'

Example: Retry Failed SMS (cURL)

curl -X POST \
  https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_requestStatus \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"smsId": "sms_1707400000000_on1t75e", "retry": true}'

Example: Retry Failed SMS (Python)

import requests

response = requests.post(
    "https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_requestStatus",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json"
    },
    json={
        "smsId": "sms_1707400000000_on1t75e",
        "retry": True
    }
)
print(response.json())

Example: Batch Retry (Node.js)

// Retry multiple failed SMS
const failedIds = ['sms_1707400000000_abc1234', 'sms_1707400001000_def5678', 'sms_1707400002000_ghi9012'];

for (const smsId of failedIds) {
  const res = await fetch(
    'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_requestStatus',
    {
      method: 'POST',
      headers: {
        'X-API-Key': 'YOUR_API_KEY',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ smsId, retry: true })
    }
  );
  console.log(`${smsId}: ${(await res.json()).message}`);
}

Error Codes

CodeErrorDescription
401UNAUTHORIZEDMissing or invalid API key
402SUBSCRIPTION_REQUIREDActive subscription needed
400INVALID_REQUESTMissing smsId field
404NO_DEVICENo active device found — open the app
500FCM_ERRORFailed to reach device

📊 Get Statistics

Retrieve SMS usage statistics for your account.

GET /api_sms_getStatistics

Query Parameters

ParameterValueDescription
typetotals (default)All-time aggregate totals
typemonthlyStatistics for a specific month (requires month param)
typeall-monthsStatistics for the last 12 months
monthe.g. 2026-03Required when type=monthly. Format: YYYY-MM

Response — type=totals (default)

GET /api_sms_getStatistics
X-API-Key: your_api_key

{
  "totalSent": 1250,
  "totalDelivered": 1200,
  "totalFailed": 50,
  "totalPending": 15,
  "lastUpdatedAt": "2026-03-01T12:00:00.000Z"
}

Response — type=monthly

GET /api_sms_getStatistics?type=monthly&month=2026-03
X-API-Key: your_api_key

{
  "month": "2026-03",
  "totalSent": 150,
  "totalDelivered": 145,
  "totalFailed": 5,
  "totalPending": 2,
  "lastUpdatedAt": "2026-03-01T12:00:00.000Z"
}

Response — type=all-months

GET /api_sms_getStatistics?type=all-months
X-API-Key: your_api_key

{
  "months": [
    { "month": "2026-03", "totalSent": 150, "totalDelivered": 145, "totalFailed": 5, "totalPending": 2, "lastUpdatedAt": "..." },
    { "month": "2026-02", "totalSent": 130, "totalDelivered": 125, "totalFailed": 5, "totalPending": 0, "lastUpdatedAt": "..." }
  ]
}

🔗 Delivery Status Webhooks

Receive real-time updates when your SMS messages are sent, delivered, or failed.

How It Works

When an SMS status changes, we'll send a GET request to your webhook URL with status parameters:

GET https://your-server.com/webhook?id=sms_1707400000000_on1t75e&status=delivered×tamp=1707400005000

Webhook Parameters

Parameter Type Description
id string The SMS ID returned when you sent the message
status string New status: queued, sending, sent, delivered, or failed
timestamp number Unix timestamp in milliseconds when this status was recorded
error string (Optional) Error message if status is "failed"

Dual Webhook Strategy

SMS Gateway Master supports two types of webhooks:

1. Default User Webhook

Set once in app settings (Settings → Gateway API → Webhook URL). Used for all SMS messages by default.

2. Per-Request Webhook

Specify a custom webhook URL in each API request using the webhookUrl parameter. Overrides the default webhook for that specific message.

💡 Priority If you specify a webhook URL in your API request, it will be used instead of the default webhook set in the app.

Example Webhook Handler (Node.js)

app.get('/webhook', (req, res) => {
  const { id, status, timestamp, error } = req.query;

  console.log(`SMS ${id} status: ${status}`);

  if (status === 'delivered') {
    console.log('Message delivered successfully!');
  } else if (status === 'failed') {
    console.log('Message failed:', error);
  }

  res.sendStatus(200);
});

📥 Incoming SMS Forwarding NEW

Forward all incoming SMS messages to your API endpoint in real-time. Your API can optionally reply with a text message that will be auto-sent back to the sender — enabling two-way SMS automation, chatbots, and auto-responders.

Setup in App

  1. Open SMS Gateway Master
  2. Go to Settings → Incoming SMS Forwarding
  3. Enter your API Endpoint URL
  4. Enter your X-API-Key (optional, for securing your endpoint)
  5. Set Conversation History count (0, 5, 10, 20, or 50 messages)
  6. Enable the Forward Incoming SMS toggle
💡 Requires TRIAL or PRO subscription — Incoming SMS Forwarding is available for authenticated users with an active Trial or Pro plan.

How It Works

When your device receives an SMS, the app immediately sends a POST request to your configured endpoint:

POST https://your-api.com/sms-webhook
Content-Type: application/json
X-API-Key: your-api-key

{
  "type": "incoming_sms",
  "sender": "+1234567890",
  "message": "Hello, I need help!",
  "timestamp": 1707400000000,

  // conversation_history is ONLY included when history count > 0 in Settings.
  // It already contains the current message as the last "in" entry.
  "conversation_history": [
    { "role": "out", "message": "Hi! How can we help?", "timestamp": 1707390000000 },
    { "role": "in", "message": "I have a question about my order", "timestamp": 1707395000000 },
    { "role": "out", "message": "Sure, what's your order number?", "timestamp": 1707396000000 },
    { "role": "in", "message": "Hello, I need help!", "timestamp": 1707400000000 }
  ]
}

Request Fields

Field Type Description
type string Always "incoming_sms" for received messages
sender string Phone number that sent the SMS (international format)
message string The SMS message body
timestamp number Unix timestamp in milliseconds when SMS was received
conversation_history array Only present when history count > 0 in settings. Recent messages from this conversation (up to the configured limit: 5, 10, 20, or 50). Each entry has role ("in" = received, "out" = sent), message, and timestamp (milliseconds). Sorted oldest → newest. The current incoming message is always the last entry (role "in"). Phone number matching uses last-9-digits normalization to handle prefix variations (e.g. +40 vs 0).

Response Options

Option 1: Auto-Reply (send SMS back to sender)

Return a JSON body with sms_text to automatically send a reply SMS:

HTTP 200 OK
Content-Type: application/json

{
  "sms_text": "Thanks for your message! We'll get back to you shortly."
}

The app will:

  • Send the reply SMS to the original sender
  • Track delivery status (sending → sent → delivered)
  • POST status updates back to your same endpoint

Option 2: No Action (just log the message)

Return an empty body or empty sms_text to take no action:

HTTP 200 OK
(empty body)

Status Callbacks (after auto-reply)

When your API sends a reply (via sms_text), the app POSTs delivery status updates to the same endpoint. The sequence is always: sendingsentdelivered (or failed).

The sender field in status callbacks is the phone number of the original SMS sender (i.e. the person the reply was sent to).

Example status callback payload:

POST https://your-api.com/sms-webhook
Content-Type: application/json
X-API-Key: your-api-key

{
  "type": "sms_status",
  "smsId": "sms_1707400000000_abc123ef",
  "status": "delivered",
  "sender": "+1234567890",
  "timestamp": 1707400005000
}

Status Values

Status Description
sendingAuto-reply triggered — SMS queued for sending (fired immediately before the SMS is handed to the carrier)
sentSMS accepted by carrier (confirmed via system SMS_SENT broadcast)
deliveredSMS delivered to recipient's handset (confirmed via system SMS_DELIVERED broadcast)
failedSMS delivery failed — includes an error field with the reason

Status Callback Fields

FieldTypeDescription
typestringAlways "sms_status"
smsIdstringUnique ID of the auto-reply SMS. Format: sms_<timestamp_ms>_<8-char-uuid> (e.g. sms_1707400000000_a1b2c3d4)
statusstringOne of: sending, sent, delivered, failed
senderstringPhone number of the original SMS sender (the recipient of the auto-reply)
timestampnumberUnix timestamp in milliseconds when this status was recorded
errorstringOnly present on failed status. Description of the failure reason.

Complete Example: Auto-Responder (Node.js)

const express = require('express');
const app = express();
app.use(express.json());

app.post('/sms-webhook', (req, res) => {
  const { type, sender, message, conversation_history, smsId, status } = req.body;

  // Verify API key
  if (req.headers['x-api-key'] !== 'your-secret-key') {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  if (type === 'incoming_sms') {
    console.log(`📩 SMS from ${sender}: ${message}`);

    // Auto-reply logic
    if (message.toLowerCase().includes('help')) {
      return res.json({
        sms_text: 'Support hours: Mon-Fri 9AM-5PM. Reply URGENT for immediate help.'
      });
    }

    if (message.toLowerCase().includes('urgent')) {
      return res.json({
        sms_text: 'An agent will contact you within 10 minutes.'
      });
    }

    // No reply needed for other messages
    return res.status(200).send();
  }

  if (type === 'sms_status') {
    console.log(`📊 SMS ${smsId} → ${status}`);
    // Track delivery in your database
  }

  res.status(200).send();
});

app.listen(3000);

Complete Example: Auto-Responder (Python / Flask)

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/sms-webhook', methods=['POST'])
def sms_webhook():
    api_key = request.headers.get('X-API-Key')
    if api_key != 'your-secret-key':
        return jsonify({'error': 'Unauthorized'}), 401

    data = request.json
    msg_type = data.get('type')

    if msg_type == 'incoming_sms':
        sender = data['sender']
        message = data['message']
        history = data.get('conversation_history', [])
        print(f"📩 SMS from {sender}: {message} (history: {len(history)} msgs)")

        # Auto-reply logic
        if 'help' in message.lower():
            return jsonify({
                'sms_text': 'Support hours: Mon-Fri 9AM-5PM. Reply URGENT for immediate help.'
            })

        # No reply
        return '', 200

    if msg_type == 'sms_status':
        sms_id = data['smsId']
        status = data['status']
        print(f"📊 SMS {sms_id} → {status}")

    return '', 200

if __name__ == '__main__':
    app.run(port=3000)

Complete Example: Auto-Responder (PHP)

<?php
// sms-webhook.php
header('Content-Type: application/json');

$apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
if ($apiKey !== 'your-secret-key') {
    http_response_code(401);
    echo json_encode(['error' => 'Unauthorized']);
    exit;
}

$data = json_decode(file_get_contents('php://input'), true);
$type = $data['type'] ?? '';

if ($type === 'incoming_sms') {
    $sender = $data['sender'];
    $message = $data['message'];
    $history = $data['conversation_history'] ?? [];
    error_log("📩 SMS from {$sender}: {$message} (history: " . count($history) . " msgs)");

    // Auto-reply logic
    if (stripos($message, 'help') !== false) {
        echo json_encode([
            'sms_text' => 'Support hours: Mon-Fri 9AM-5PM. Reply URGENT for immediate help.'
        ]);
        exit;
    }

    // No reply
    http_response_code(200);
    exit;
}

if ($type === 'sms_status') {
    $smsId = $data['smsId'];
    $status = $data['status'];
    error_log("📊 SMS {$smsId} → {$status}");
}

http_response_code(200);
?>

📜 Conversation History NEW

Include previous messages from the conversation in the API request, enabling your server to generate context-aware, AI-powered replies.

Configure the number of history messages in Settings → Incoming SMS Forwarding → Conversation History. Choose between 0 (no history), 5, 10, 20, or 50 messages. Both incoming and outgoing messages are included, sorted oldest → newest.

⚠️ Important: The conversation_history array already contains the current incoming message as its last entry (with "role": "in"). You can feed the array directly to an AI model — there is no need to append message again.

Phone numbers are matched using last-9-digits normalization, so history is correctly retrieved regardless of prefix format (e.g. +40721000000 and 0721000000 are treated as the same contact).

History Entry Fields

Field Type Description
role string "in" = received SMS, "out" = sent SMS
message string The message text content
timestamp number Unix timestamp in milliseconds

AI-Powered Auto-Responder (Node.js + OpenAI)

const express = require('express');
const OpenAI = require('openai');
const app = express();
app.use(express.json());

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

app.post('/sms-webhook', async (req, res) => {
  const { type, sender, message, conversation_history } = req.body;

  if (req.headers['x-api-key'] !== 'your-secret-key') {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  if (type === 'incoming_sms') {
    const messages = [
      { role: 'system', content: 'You are a helpful SMS assistant. Keep replies under 160 characters.' }
    ];

    if (conversation_history && conversation_history.length > 0) {
      // conversation_history already contains the current message as the last "in" entry
      conversation_history.forEach(msg => {
        messages.push({
          role: msg.role === 'in' ? 'user' : 'assistant',
          content: msg.message
        });
      });
    } else {
      // No history configured — add the current message manually
      messages.push({ role: 'user', content: message });
    }

    try {
      const completion = await openai.chat.completions.create({
        model: 'gpt-4o-mini',
        messages: messages,
        max_tokens: 100
      });

      const reply = completion.choices[0].message.content;
      return res.json({ sms_text: reply });
    } catch (err) {
      console.error('OpenAI error:', err);
      return res.json({ sms_text: 'Sorry, please try again later.' });
    }
  }

  if (type === 'sms_status') {
    console.log(`📊 SMS ${req.body.smsId} → ${req.body.status}`);
  }

  res.status(200).send();
});

app.listen(3000);

AI-Powered Auto-Responder (Python + OpenAI)

from flask import Flask, request, jsonify
from openai import OpenAI

app = Flask(__name__)
client = OpenAI()

@app.route('/sms-webhook', methods=['POST'])
def sms_webhook():
    if request.headers.get('X-API-Key') != 'your-secret-key':
        return jsonify({'error': 'Unauthorized'}), 401

    data = request.json

    if data.get('type') == 'incoming_sms':
        messages = [
            {'role': 'system', 'content': 'You are a helpful SMS assistant. Keep replies under 160 characters.'}
        ]

        history = data.get('conversation_history', [])
        if history:
            # conversation_history already contains the current message as the last "in" entry
            for msg in history:
                role = 'user' if msg['role'] == 'in' else 'assistant'
                messages.append({'role': role, 'content': msg['message']})
        else:
            # No history configured — add the current message manually
            messages.append({'role': 'user', 'content': data['message']})

        try:
            completion = client.chat.completions.create(
                model='gpt-4o-mini',
                messages=messages,
                max_tokens=100
            )
            reply = completion.choices[0].message.content
            return jsonify({'sms_text': reply})
        except Exception as e:
            print(f'OpenAI error: {e}')
            return jsonify({'sms_text': 'Sorry, please try again later.'})

    if data.get('type') == 'sms_status':
        print(f"📊 SMS {data['smsId']} → {data['status']}")

    return '', 200

if __name__ == '__main__':
    app.run(port=3000)

Use Cases

  • AI-Powered SMS Chatbot: Use conversation history with OpenAI, Claude, or Gemini for intelligent context-aware replies
  • Customer Support Auto-Responder: Instant replies with FAQ or escalation
  • SMS Chatbot: Keyword-based automated conversations
  • Two-Way SMS Communication: Full duplex messaging for apps
  • Order Status by SMS: Customers text order ID, get status back
  • Appointment Confirmations: Reply YES/NO to confirm appointments
  • Survey & Feedback Collection: Collect responses via SMS
  • OTP/Verification Logging: Forward OTP codes to your backend
💡 Tips
  • Always respond with HTTP 200, even if you don't want to reply
  • Use X-API-Key to secure your endpoint from unauthorized access
  • Process incoming SMS asynchronously if your logic is complex
  • The same endpoint receives both incoming SMS and status updates — use the type field to differentiate
  • Reply SMS are tracked with the same delivery status flow as API-sent SMS
  • Enable Conversation History to send previous messages for AI-powered context-aware replies
  • conversation_history already includes the current incoming message as its last "in" entry — pass the array directly to your AI model without appending message again
  • When history is disabled (count = 0), use the top-level message field to get the incoming text
  • History includes both "in" (received) and "out" (sent) messages, sorted oldest → newest
  • Phone number matching uses last-9-digits normalization — history is correctly fetched even when the sender uses a different prefix format (e.g. +40721000000 vs 0721000000)
  • Status callbacks sequence: sending (immediate) → sent (carrier accepted) → delivered (handset confirmed). A failed status can occur at the sent or delivered stage and includes an error field

⚙️ Webhook Setup Guide

1. Set Default Webhook in App

  1. Open SMS Gateway Master app
  2. Go to Settings → Gateway API
  3. Find Webhook URL field
  4. Enter your webhook URL (e.g., https://your-server.com/webhook)
  5. Tap Save

2. Override Per Request (Optional)

Include webhookUrl in your API request body:

{
  "phoneNumber": "+1234567890",
  "message": "Test message",
  "webhookUrl": "https://custom-webhook.com/hook"
}

3. Test Your Webhook

Send a test SMS and verify that your webhook receives the status updates.

💡 Best Practices
  • Always respond with HTTP 200 status code
  • Process webhooks asynchronously to avoid timeouts
  • Implement retry logic for failed webhook deliveries
  • Use HTTPS for secure webhook endpoints
  • Validate incoming webhook requests

⚠️ Error Codes

Standard HTTP status codes and error responses.

Status Code Error Description
200 Success Request completed successfully
400 Bad Request Invalid request parameters
401 Unauthorized Invalid or missing API key
402 Payment Required Subscription expired or insufficient quota
404 Not Found No active device found — open the app and ensure you are logged in (NO_ACTIVE_DEVICE)
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server error, please retry
503 Service Unavailable Device FCM token expired — open the app once to refresh, then retry (FCM_TOKEN_EXPIRED)

Error Response Format

{
  "error": "The provided API key is invalid or has been revoked",
  "code": "UNAUTHORIZED"
}

The code field is present on most errors. Common codes: UNAUTHORIZED, SUBSCRIPTION_REQUIRED, INVALID_REQUEST, NO_ACTIVE_DEVICE, FCM_ERROR, FCM_TOKEN_EXPIRED.

⏱️ Rate Limits

API usage limits based on subscription tier.

Tier Daily Limit Burst Limit Price
FREE 0 SMS/day - Free
TRIAL 100 SMS/day 10 SMS/minute Free (7 days)
PRO 10,000 SMS/day 100 SMS/minute $9.99/month
💡 Rate Limit Headers Each API response includes rate limit information in the headers:
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9500
X-RateLimit-Reset: 1707400000

📋 SMS Status Codes

Understanding SMS delivery statuses.

Status Description
queued Message is queued and will be sent shortly
sending Message is being sent to the carrier
sent Message was sent to the carrier successfully
delivered Message was delivered to the recipient
failed Message delivery failed (error details provided)

Status Flow

queued → sending → sent → delivered
                           ↓
                         failed

💻 Code Examples

PHP Example

<?php
$apiKey = 'your_api_key_here';
$url = 'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send';

$data = [
    'phoneNumber' => '+1234567890',
    'message' => 'Hello from PHP!',
    'webhookUrl' => 'https://your-server.com/webhook'
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'X-API-Key: ' . $apiKey,
    'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
print_r($result);
?>

Go Example

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)

func sendSMS() {
    url := "https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send"

    data := map[string]string{
        "phoneNumber": "+1234567890",
        "message":     "Hello from Go!",
        "webhookUrl":  "https://your-server.com/webhook",
    }

    jsonData, _ := json.Marshal(data)

    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    req.Header.Set("X-API-Key", "your_api_key_here")
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, _ := client.Do(req)
    defer resp.Body.Close()

    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    fmt.Println(result)
}

Ruby Example

require 'net/http'
require 'json'

uri = URI('https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri.path, {
  'X-API-Key' => 'your_api_key_here',
  'Content-Type' => 'application/json'
})

request.body = {
  phoneNumber: '+1234567890',
  message: 'Hello from Ruby!',
  webhookUrl: 'https://your-server.com/webhook'
}.to_json

response = http.request(request)
puts JSON.parse(response.body)

🛠️ SDK Examples

Complete, production-ready code examples for integrating SMS Gateway Master into your application. Every example below uses only the existing REST API with X-API-Key authentication.

📌 API Endpoint

All examples use:
POST https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send

Python — Full Example with Error Handling

import requests
import time
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("sms_gateway")

API_URL = "https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send"
API_KEY = "sk_live_your_api_key_here"  # Replace with your key

def send_sms(phone: str, message: str, webhook_url: str = None, retries: int = 3) -> dict:
    """
    Send SMS via SMS Gateway Master API.

    Args:
        phone: Recipient phone in international format (e.g. +1234567890)
        message: Text message (1-1600 characters)
        webhook_url: Optional webhook for delivery status callbacks
        retries: Number of retry attempts on failure

    Returns:
        dict with keys: success, smsId, status, timestamp
    """
    headers = {
        "X-API-Key": API_KEY,
        "Content-Type": "application/json"
    }
    payload = {
        "phoneNumber": phone,
        "message": message
    }
    if webhook_url:
        payload["webhookUrl"] = webhook_url

    for attempt in range(1, retries + 1):
        try:
            response = requests.post(API_URL, json=payload, headers=headers, timeout=30)

            if response.status_code == 200:
                data = response.json()
                logger.info(f"SMS sent: {data.get('smsId')} -> {phone}")
                return data

            elif response.status_code == 429:
                wait = 2 ** attempt
                logger.warning(f"Rate limited. Retrying in {wait}s...")
                time.sleep(wait)

            else:
                logger.error(f"API error {response.status_code}: {response.text}")
                return {"success": False, "error": response.text}

        except requests.exceptions.Timeout:
            logger.warning(f"Timeout on attempt {attempt}/{retries}")
        except requests.exceptions.ConnectionError:
            logger.error("Connection failed. Check internet.")
            break

    return {"success": False, "error": "Max retries exceeded"}


# ── Usage ──────────────────────────────────────────────
result = send_sms(
    phone="+1234567890",
    message="Your verification code is 483920",
    webhook_url="https://yourserver.com/sms-status"
)
print(result)
# {"smsId": "sms_1707400000000_on1t75e", "status": "queued", "message": "SMS queued for sending...", "timestamp": "2026-03-01T12:00:00.000Z"}

Node.js — Async/Await with Axios

const axios = require('axios');

const API_URL = 'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send';
const API_KEY = 'sk_live_your_api_key_here'; // Replace with your key

/**
 * Send SMS via SMS Gateway Master API
 * @param {string} phone  - International format (+1234567890)
 * @param {string} message - 1-1600 characters
 * @param {string} [webhookUrl] - Optional delivery status webhook
 * @returns {Promise<object>} API response
 */
async function sendSMS(phone, message, webhookUrl = null) {
  const payload = { phoneNumber: phone, message };
  if (webhookUrl) payload.webhookUrl = webhookUrl;

  try {
    const { data } = await axios.post(API_URL, payload, {
      headers: {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json'
      },
      timeout: 30000
    });
    console.log(`SMS queued: ${data.smsId}`);
    return data;
  } catch (err) {
    if (err.response) {
      console.error(`API ${err.response.status}: ${JSON.stringify(err.response.data)}`);
    } else {
      console.error('Network error:', err.message);
    }
    throw err;
  }
}

// ── Usage ──────────────────────────────────────────────
(async () => {
  const result = await sendSMS('+1234567890', 'Order #1234 confirmed!');
  console.log(result);
})();

PHP — Production-Ready Function

<?php
define('SMS_API_URL', 'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send');
define('SMS_API_KEY', 'sk_live_your_api_key_here'); // Replace with your key

/**
 * Send SMS via SMS Gateway Master API
 *
 * @param string $phone   International format (+1234567890)
 * @param string $message Message text (1-1600 chars)
 * @param string|null $webhookUrl Optional delivery webhook
 * @return array|false     Decoded JSON response or false on failure
 */
function sendSMS(string $phone, string $message, ?string $webhookUrl = null) {
    $data = [
        'phoneNumber' => $phone,
        'message'     => $message,
    ];
    if ($webhookUrl) {
        $data['webhookUrl'] = $webhookUrl;
    }

    $ch = curl_init(SMS_API_URL);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode($data),
        CURLOPT_HTTPHEADER     => [
            'X-API-Key: ' . SMS_API_KEY,
            'Content-Type: application/json',
        ],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 30,
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error    = curl_error($ch);
    curl_close($ch);

    if ($error) {
        error_log("SMS Gateway cURL error: $error");
        return false;
    }
    if ($httpCode !== 200) {
        error_log("SMS Gateway HTTP $httpCode: $response");
        return false;
    }

    return json_decode($response, true);
}

// ── Usage ──────────────────────────────────────────────
$result = sendSMS('+1234567890', 'Your order has shipped!');
if ($result && isset($result['smsId'])) {
    echo "SMS ID: " . $result['smsId'];   // e.g. sms_1707400000000_on1t75e
    echo "Status: " . $result['status'];  // "queued"
}
?>

Java — HttpClient (Java 11+)

import java.net.URI;
import java.net.http.*;
import java.net.http.HttpResponse.BodyHandlers;

public class SmsGateway {

    private static final String API_URL =
        "https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send";
    private static final String API_KEY = "sk_live_your_api_key_here";

    public static String sendSms(String phone, String message) throws Exception {
        String json = String.format(
            "{\"phoneNumber\":\"%s\",\"message\":\"%s\"}", phone, message);

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(API_URL))
            .header("X-API-Key", API_KEY)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .build();

        HttpResponse<String> response = client.send(request, BodyHandlers.ofString());

        if (response.statusCode() == 200) {
            return response.body(); // JSON string
        }
        throw new RuntimeException("API error " + response.statusCode() + ": " + response.body());
    }

    public static void main(String[] args) throws Exception {
        System.out.println(sendSms("+1234567890", "Hello from Java!"));
    }
}

C# — HttpClient (.NET 6+)

using System.Net.Http.Json;
using System.Text.Json;

var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
client.DefaultRequestHeaders.Add("X-API-Key", "sk_live_your_api_key_here");

var payload = new {
    phoneNumber = "+1234567890",
    message     = "Hello from C#!",
    webhookUrl  = "https://yourserver.com/hook"
};

var response = await client.PostAsJsonAsync(
    "https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send",
    payload);

response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);

Google Apps Script — Send SMS from Google Sheets

/**
 * Send SMS directly from a Google Spreadsheet.
 * Add this script via Extensions > Apps Script, then call from a cell
 * or run manually.
 *
 * Sheet layout expected:
 *   A: Phone  |  B: Message  |  C: Status (filled by script)
 */
var API_URL = 'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send';
var API_KEY = 'sk_live_your_api_key_here'; // Replace with your key

function sendSmsFromSheet() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var data  = sheet.getDataRange().getValues();

  for (var i = 1; i < data.length; i++) {          // skip header row
    var phone   = data[i][0];
    var message = data[i][1];
    var status  = data[i][2];

    if (!phone || !message || status === 'sent') continue;

    var payload = JSON.stringify({
      phoneNumber: String(phone),
      message:     String(message)
    });

    var options = {
      method:      'post',
      contentType: 'application/json',
      headers:     { 'X-API-Key': API_KEY },
      payload:     payload,
      muteHttpExceptions: true
    };

    try {
      var resp = UrlFetchApp.fetch(API_URL, options);
      var json = JSON.parse(resp.getContentText());
      sheet.getRange(i + 1, 3).setValue(json.smsId ? 'sent' : 'error');
      sheet.getRange(i + 1, 4).setValue(json.smsId || json.error || '');
    } catch (e) {
      sheet.getRange(i + 1, 3).setValue('error');
      sheet.getRange(i + 1, 4).setValue(e.message);
    }
  }
  SpreadsheetApp.flush();
}

/**
 * Custom menu for easy access
 */
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('SMS Gateway')
    .addItem('Send All SMS', 'sendSmsFromSheet')
    .addToUi();
}

Excel VBA — Send SMS from Excel (.xlsm)

' ─────────────────────────────────────────────
' SMS Gateway Master — VBA Module
' Add to: Developer > Visual Basic > Insert > Module
' Requires: Microsoft XML, v6.0 reference
' ─────────────────────────────────────────────
Const API_URL As String = "https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send"
Const API_KEY As String = "sk_live_your_api_key_here"

Public Function SendSMS(phone As String, message As String) As String
    Dim http As Object
    Set http = CreateObject("MSXML2.XMLHTTP")

    Dim json As String
    json = "{""phoneNumber"":""" & phone & """,""message"":""" & message & """}"

    http.Open "POST", API_URL, False
    http.setRequestHeader "X-API-Key", API_KEY
    http.setRequestHeader "Content-Type", "application/json"
    http.send json

    If http.Status = 200 Then
        SendSMS = "OK: " & http.responseText
    Else
        SendSMS = "ERROR " & http.Status & ": " & http.responseText
    End If

    Set http = Nothing
End Function

' ── Batch send from worksheet ──────────────────────
' Column A = Phone, Column B = Message, Column C = Status
Sub SendAllSMS()
    Dim ws As Worksheet
    Set ws = ActiveSheet
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    Dim i As Long
    For i = 2 To lastRow    ' skip header
        Dim phone As String: phone = ws.Cells(i, 1).Value
        Dim msg As String:   msg = ws.Cells(i, 2).Value

        If phone <> "" And msg <> "" And ws.Cells(i, 3).Value <> "sent" Then
            Dim result As String
            result = SendSMS(phone, msg)
            ws.Cells(i, 3).Value = IIf(Left(result, 2) = "OK", "sent", "error")
            ws.Cells(i, 4).Value = result
        End If
    Next i
    MsgBox "Batch complete!", vbInformation
End Sub

🧪 Testing & Debugging

Tools and techniques to verify your integration works correctly before going to production.

1. Test with cURL

The simplest way to verify your API key and endpoint.

curl -v -X POST \
  https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send \
  -H "X-API-Key: sk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+1234567890",
    "message": "API test message",
    "webhookUrl": "https://webhook.site/your-unique-id"
  }'
💡 Tip

Use the -v (verbose) flag to see full request and response headers for debugging.

2. Test Webhooks with webhook.site

Before setting up your own server, use webhook.site to inspect delivery callbacks:

  1. Visit https://webhook.site — you get a unique URL
  2. Copy that URL and use it as your webhookUrl in the API call
  3. Send a test SMS
  4. Watch the webhook.site dashboard — you will see GET requests with delivery status parameters

3. Webhook Callback Format

When SMS status changes, your webhook receives an HTTP GET request:

GET https://yourserver.com/hook?id=sms_1707400000000_on1t75e&status=delivered&timestamp=1707400005000
ParameterTypeDescription
idstringSMS ID returned by the send endpoint
statusstringqueued | sent | delivered | failed
timestampnumberUnix timestamp in milliseconds
errorstringPresent only when status=failed

4. Test Webhook Handler (Node.js)

const express = require('express');
const app = express();

// SMS Gateway sends delivery status as GET with query parameters
app.get('/hook', (req, res) => {
  const { id, status, timestamp, error } = req.query;
  console.log(`[${new Date(Number(timestamp)).toISOString()}] SMS ${id}: ${status}`);
  if (error) console.error('  Error:', error);
  res.sendStatus(200);   // IMPORTANT: always respond 200
});

app.listen(3000);

5. Common Error Codes

HTTP CodeMeaningSolution
200Success — SMS queued
400Bad Request — invalid phone or messageCheck phone format (+country code) and message length (1-1600)
401Unauthorized — bad API keyVerify key starts with sk_live_ or sk_test_ and has 28+ chars
402Payment Required — no active subscriptionActivate PRO or start trial in the app
429Rate Limited — too many requestsWait and retry with exponential backoff
500Server ErrorRetry after a few seconds; contact support if persistent

✅ Best Practices

API Key Security

  • Store API keys in environment variables or a secrets manager — never hard-code them in source files.
  • Add your .env file to .gitignore so keys are never committed to version control.
  • Rotate keys periodically from Settings → Gateway API in the app.
  • Use a server-side proxy if you need to call the API from a browser — never expose the key in front-end code.

Reliable Webhook Handling

  • Always respond with HTTP 200 immediately — process the data asynchronously.
  • Make your webhook handler idempotent: the same callback may arrive more than once due to retries.
  • Log every callback for auditing and debugging.
  • Use HTTPS for your webhook endpoint.

Rate Limiting & Retry

The API allows up to 10,000 SMS per day. If you receive HTTP 429:

# Exponential backoff pattern
import time

delays = [1, 2, 4, 8, 16]  # seconds
for attempt, delay in enumerate(delays):
    response = send_sms(phone, message)
    if response.status_code != 429:
        break
    time.sleep(delay)

Phone Number Format

  • Always use international format: + followed by country code and number.
  • Examples: +14155551234 (US), +40721123456 (Romania), +447911123456 (UK).
  • Strip spaces, dashes, and parentheses before sending.

Message Length

  • Maximum 1,600 characters per API call.
  • Messages over 160 characters are automatically split into multi-part SMS by the Android system.
  • All parts share the same smsId.

🛒 WooCommerce Integration

Send automated SMS notifications for WooCommerce orders by calling the SMS Gateway API from your WordPress site. No plugin required — just a small snippet in your theme's functions.php or a custom plugin file.

📌 How it works

WooCommerce fires action hooks when order status changes. We hook into those actions and call the SMS Gateway REST API with PHP wp_remote_post().

Step 1 — Add Helper Function

Add this to your theme's functions.php or a custom plugin file:

<?php
/**
 * SMS Gateway Master — WooCommerce helper
 * File: functions.php (theme) or a custom plugin
 */
define('SMS_GW_URL', 'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send');
define('SMS_GW_KEY', 'sk_live_your_api_key_here'); // Replace with your key

function sms_gateway_send(string $phone, string $message): bool {
    $response = wp_remote_post(SMS_GW_URL, [
        'timeout' => 30,
        'headers' => [
            'X-API-Key'    => SMS_GW_KEY,
            'Content-Type' => 'application/json',
        ],
        'body' => wp_json_encode([
            'phoneNumber' => $phone,
            'message'     => $message,
        ]),
    ]);

    if (is_wp_error($response)) {
        error_log('SMS Gateway error: ' . $response->get_error_message());
        return false;
    }

    $code = wp_remote_retrieve_response_code($response);
    if ($code !== 200) {
        error_log("SMS Gateway HTTP $code: " . wp_remote_retrieve_body($response));
        return false;
    }
    return true;
}

Step 2 — Hook into Order Events

// ── New order placed ─────────────────────────────────
add_action('woocommerce_new_order', function ($order_id) {
    $order = wc_get_order($order_id);
    $phone = $order->get_billing_phone();
    if (!$phone) return;

    sms_gateway_send($phone, sprintf(
        'Thank you for your order #%s! We will process it shortly. — %s',
        $order->get_order_number(),
        get_bloginfo('name')
    ));
});

// ── Order shipped ────────────────────────────────────
add_action('woocommerce_order_status_completed', function ($order_id) {
    $order = wc_get_order($order_id);
    $phone = $order->get_billing_phone();
    if (!$phone) return;

    sms_gateway_send($phone, sprintf(
        'Great news! Your order #%s has been shipped. Track: %s',
        $order->get_order_number(),
        $order->get_meta('_tracking_url') ?: 'check your email'
    ));
});

// ── Order on-hold (payment pending) ──────────────────
add_action('woocommerce_order_status_on-hold', function ($order_id) {
    $order = wc_get_order($order_id);
    $phone = $order->get_billing_phone();
    if (!$phone) return;

    sms_gateway_send($phone, sprintf(
        'Order #%s is awaiting payment. Please complete checkout. — %s',
        $order->get_order_number(),
        get_bloginfo('name')
    ));
});

Step 3 — Admin Notification (optional)

// Notify store owner on every new order
add_action('woocommerce_new_order', function ($order_id) {
    $order = wc_get_order($order_id);
    sms_gateway_send(
        '+40721123456',  // Store owner phone
        sprintf('New order #%s — %s %s',
            $order->get_order_number(),
            $order->get_formatted_order_total(),
            $order->get_billing_first_name()
        )
    );
});

🟢 Shopify Integration

Send SMS notifications when Shopify orders are placed by creating a webhook that forwards order data to a small server-side script.

📌 How it works

Shopify fires webhooks for order events. You create a small server endpoint that receives the Shopify webhook and calls the SMS Gateway API.

Architecture

Shopify Order Created
        │
        ▼  (HTTP POST with order JSON)
  Your Server Endpoint
        │
        ▼  (HTTP POST to SMS Gateway API)
  SMS Gateway Master API
        │
        ▼  (FCM push)
  Android Device sends SMS

Step 1 — Create Webhook Receiver (Node.js / Express)

const express = require('express');
const crypto  = require('crypto');
const axios   = require('axios');
const app     = express();

const SHOPIFY_SECRET = process.env.SHOPIFY_WEBHOOK_SECRET;
const SMS_API_URL    = 'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send';
const SMS_API_KEY    = process.env.SMS_API_KEY;   // sk_live_...

// Parse raw body for HMAC verification
app.post('/shopify/order-created',
  express.raw({ type: 'application/json' }),
  async (req, res) => {

    // 1. Verify Shopify signature
    const hmac = req.get('X-Shopify-Hmac-Sha256');
    const hash = crypto
      .createHmac('sha256', SHOPIFY_SECRET)
      .update(req.body)
      .digest('base64');

    if (hmac !== hash) {
      console.warn('Invalid Shopify signature');
      return res.sendStatus(401);
    }

    // 2. Parse order
    const order = JSON.parse(req.body);
    const phone = order.billing_address?.phone
               || order.customer?.phone;

    if (!phone) {
      console.log('No phone on order', order.name);
      return res.sendStatus(200);
    }

    // 3. Send SMS
    try {
      await axios.post(SMS_API_URL, {
        phoneNumber: phone,
        message: `Thank you for order ${order.name}! ` +
                 `Total: ${order.total_price} ${order.currency}. ` +
                 `We'll notify you when it ships.`
      }, {
        headers: {
          'X-API-Key': SMS_API_KEY,
          'Content-Type': 'application/json'
        }
      });
      console.log(`SMS sent for order ${order.name}`);
    } catch (err) {
      console.error('SMS failed:', err.response?.data || err.message);
    }

    res.sendStatus(200);  // Always ACK Shopify quickly
  }
);

app.listen(3000);

Step 2 — Register Webhook in Shopify

  1. Open your Shopify Admin → Settings → Notifications
  2. Scroll to Webhooks and click Create webhook
  3. Event: Order creation
  4. Format: JSON
  5. URL: https://yourserver.com/shopify/order-created
  6. Click Save
⚠️ Security

Always verify the X-Shopify-Hmac-Sha256 header to ensure the request really comes from Shopify.

🔵 PrestaShop Integration

Add SMS notifications to PrestaShop by creating a module that hooks into order events and calls the SMS Gateway API.

Custom Module (PHP)

Create a file at modules/smsgateway/smsgateway.php:

<?php
/**
 * SMS Gateway Master — PrestaShop Module
 */
if (!defined('_PS_VERSION_')) exit;

class SmsGateway extends Module {

    const API_URL = 'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send';

    public function __construct() {
        $this->name        = 'smsgateway';
        $this->version     = '1.0.0';
        $this->author      = 'Your Name';
        $this->displayName = 'SMS Gateway Master';
        $this->description = 'Send SMS notifications via SMS Gateway Master API';
        parent::__construct();
    }

    public function install() {
        return parent::install()
            && $this->registerHook('actionValidateOrder')
            && $this->registerHook('actionOrderStatusPostUpdate');
    }

    /** Fired when a new order is validated */
    public function hookActionValidateOrder($params) {
        $order    = $params['order'];
        $customer = new Customer($order->id_customer);
        $address  = new Address($order->id_address_delivery);
        $phone    = $address->phone_mobile ?: $address->phone;

        if (!$phone) return;

        $this->sendSms($phone, sprintf(
            'Thank you for order #%s! Total: %s. We will process it shortly.',
            $order->reference,
            Tools::displayPrice($order->total_paid)
        ));
    }

    /** Fired when order status changes (e.g. shipped) */
    public function hookActionOrderStatusPostUpdate($params) {
        $order    = new Order($params['id_order']);
        $status   = $params['newOrderStatus'];
        $address  = new Address($order->id_address_delivery);
        $phone    = $address->phone_mobile ?: $address->phone;

        if (!$phone) return;

        // OrderState id 4 = "Shipped" in default PrestaShop
        if ($status->id == 4) {
            $this->sendSms($phone, sprintf(
                'Order #%s has been shipped! Track your package in your account.',
                $order->reference
            ));
        }
    }

    private function sendSms(string $phone, string $message): bool {
        $apiKey = Configuration::get('SMS_GW_API_KEY');
        if (!$apiKey) return false;

        $ch = curl_init(self::API_URL);
        curl_setopt_array($ch, [
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => json_encode([
                'phoneNumber' => $phone,
                'message'     => $message,
            ]),
            CURLOPT_HTTPHEADER     => [
                'X-API-Key: ' . $apiKey,
                'Content-Type: application/json',
            ],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 30,
        ]);
        $resp = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($code !== 200) {
            PrestaShopLogger::addLog("SMS Gateway error $code: $resp", 3);
            return false;
        }
        return true;
    }
}

Configuration

  1. Upload the smsgateway folder to /modules/
  2. Go to Back Office → Modules and install "SMS Gateway Master"
  3. Set your API key in the module configuration
  4. Test by placing a test order

📦 General E-commerce Patterns

Common SMS automation patterns that work with any e-commerce platform.

Order Lifecycle Notifications

EventSMS TemplateWhen to Send
Order Placed Thank you for order #{id}! Total: {total}. We'll process it shortly. Immediately after checkout
Payment Confirmed Payment received for order #{id}. Preparing your items now! After payment gateway confirms
Shipped Order #{id} is on its way! Tracking: {tracking_url} When tracking number is added
Delivered Order #{id} has been delivered. Enjoy! Leave us a review? When carrier confirms delivery
Abandoned Cart You left items in your cart! Complete your order: {cart_url} 30-60 min after cart abandon

OTP / Verification Code (Any Platform)

import random, requests, time

API_URL = "https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send"
API_KEY = "sk_live_your_api_key_here"

# Store codes temporarily (use Redis in production)
otp_store = {}

def send_otp(phone: str) -> str:
    code = str(random.randint(100000, 999999))
    otp_store[phone] = {"code": code, "expires": time.time() + 300}  # 5 min

    requests.post(API_URL, json={
        "phoneNumber": phone,
        "message": f"Your verification code is {code}. Expires in 5 minutes."
    }, headers={
        "X-API-Key": API_KEY,
        "Content-Type": "application/json"
    }, timeout=30)

    return code

def verify_otp(phone: str, code: str) -> bool:
    entry = otp_store.get(phone)
    if not entry:
        return False
    if time.time() > entry["expires"]:
        del otp_store[phone]
        return False
    if entry["code"] == code:
        del otp_store[phone]
        return True
    return False
⚠️ Security Note for E-commerce
  • Never include sensitive data (passwords, full credit card numbers) in SMS messages.
  • Store API keys in environment variables, not in source code.
  • Validate and sanitize phone numbers before sending (use international format).
  • Verify webhook signatures if your e-commerce platform provides them (e.g. Shopify HMAC).

🏠 Home Assistant Integration

Send SMS notifications from Home Assistant using the REST notify platform. Works with any Home Assistant installation (Home Assistant OS, Docker, Supervised, Core).

📌 How it works

Home Assistant calls the SMS Gateway REST API via its built-in rest_command or notify integration. No custom component required.

Option A — REST Command (recommended)

Add to your configuration.yaml:

rest_command:
  send_sms:
    url: "https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send"
    method: POST
    headers:
      X-API-Key: "sk_live_your_api_key_here"
      Content-Type: "application/json"
    payload: '{"phoneNumber":"{{ phone }}","message":"{{ message }}"}'
    content_type: "application/json"

Usage in Automations

automation:
  - alias: "Security — Motion Detected"
    trigger:
      - platform: state
        entity_id: binary_sensor.front_door_motion
        to: "on"
    action:
      - service: rest_command.send_sms
        data:
          phone: "+1234567890"
          message: >-
            Motion detected at front door!
            Time: {{ now().strftime('%H:%M %d/%m') }}

  - alias: "Climate — Temperature Alert"
    trigger:
      - platform: numeric_state
        entity_id: sensor.living_room_temperature
        above: 35
    action:
      - service: rest_command.send_sms
        data:
          phone: "+1234567890"
          message: >-
            High temperature alert!
            Living room: {{ states('sensor.living_room_temperature') }}°C

  - alias: "Security — Garage Door Left Open"
    trigger:
      - platform: state
        entity_id: cover.garage_door
        to: "open"
        for:
          minutes: 10
    action:
      - service: rest_command.send_sms
        data:
          phone: "+1234567890"
          message: "Garage door has been open for 10 minutes!"

Option B — Notify Platform (Shell Command)

shell_command:
  sms_notify: >-
    curl -s -X POST
    https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send
    -H "X-API-Key: sk_live_your_api_key_here"
    -H "Content-Type: application/json"
    -d '{"phoneNumber":"{{ phone }}","message":"{{ message }}"}'
⚠️ Important

Store your API key in secrets.yaml instead of directly in configuration.yaml:

# secrets.yaml
sms_api_key: "sk_live_your_api_key_here"

# configuration.yaml
rest_command:
  send_sms:
    ...
    headers:
      X-API-Key: !secret sms_api_key

⚡ Zapier Integration

Connect SMS Gateway Master with 6,000+ apps through Zapier — no coding required. Use the Webhooks by Zapier action to call our API.

Step-by-Step Setup

  1. Log in to zapier.com and click Create Zap.
  2. Trigger — Choose the app that starts the workflow. Examples:
    • Gmail — "New Email"
    • Google Sheets — "New Spreadsheet Row"
    • Stripe — "New Payment"
    • Calendly — "New Event"
  3. Action — Choose Webhooks by ZapierCustom Request.
  4. Configure the action:
    MethodPOST
    URLhttps://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send
    Data{"phoneNumber":"+1234567890","message":"New email from {{sender}}: {{subject}}"}
    HeadersX-API-Key: sk_live_your_api_key_here
    Content-Type: application/json
  5. Click Test to send a test SMS.
  6. Turn on your Zap.

Popular Zap Examples

TriggerSMS Message
Google Sheets — New RowNew lead: {{Name}} — {{Email}}
Stripe — New PaymentPayment received: {{Amount}} from {{Customer}}
Calendly — New EventNew booking: {{Invitee Name}} on {{Event Date}}
Typeform — New EntryNew form submission from {{Name}}

🔧 n8n Integration

Integrate SMS Gateway with n8n — the open-source, self-hosted workflow automation platform.

HTTP Request Node Configuration

FieldValue
MethodPOST
URLhttps://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send
AuthenticationGeneric Credential Type → Header Auth
Header NameX-API-Key
Header Valuesk_live_your_api_key_here
Body Content TypeJSON
Body{"phoneNumber":"{{ $json.phone }}","message":"{{ $json.message }}"}

Example Workflow: Server Monitoring

┌────────────┐    ┌──────────┐    ┌───────────┐    ┌────────────┐
│  Schedule  │───>│  HTTP    │───>│  IF node  │───>│ SMS Gateway│
│  (1 min)   │    │  GET     │    │ status≠200│    │ HTTP POST  │
└────────────┘    │ /health  │    └───────────┘    └────────────┘
                  └──────────┘

Workflow JSON (importable)

{
  "nodes": [
    {
      "name": "Every 5 minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": { "rule": { "interval": [{ "field": "minutes", "minutesInterval": 5 }] } },
      "position": [250, 300]
    },
    {
      "name": "Check Server",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": { "url": "https://yourserver.com/health", "method": "GET" },
      "position": [450, 300]
    },
    {
      "name": "Send SMS Alert",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send",
        "method": "POST",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "X-API-Key", "value": "sk_live_your_api_key_here" },
            { "name": "Content-Type", "value": "application/json" }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            { "name": "phoneNumber", "value": "+1234567890" },
            { "name": "message", "value": "Server DOWN! Status: {{ $json.statusCode }}" }
          ]
        }
      },
      "position": [650, 300]
    }
  ]
}

🟣 Make (Integromat) Integration

Use Make's visual scenario builder to connect SMS Gateway Master with hundreds of apps.

Setup Steps

  1. Create a new Scenario in make.com.
  2. Add a Trigger module (e.g., Google Sheets → Watch Rows).
  3. Add an HTTP → Make a request module with these settings:
FieldValue
URLhttps://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send
MethodPOST
HeadersX-API-Key: sk_live_your_api_key_here
Content-Type: application/json
Body typeRaw → JSON
Request content{"phoneNumber":"{{phone}}","message":"{{message}}"}
  1. Map the phone and message variables from your trigger module.
  2. Click Run once to test.
  3. Activate the scenario.

🔗 Other Automation Platforms

SMS Gateway Master works with any platform that can make HTTP POST requests. Below are quick-start guides for popular tools.

IFTTT

  1. Create a new Applet at ifttt.com/create.
  2. If This — choose any trigger (Weather, Smart Home, etc.).
  3. Then That — choose Webhooks → Make a web request.
  4. Configure:
    • URL: https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send
    • Method: POST
    • Content Type: application/json
    • Additional Headers: X-API-Key: sk_live_your_api_key_here
    • Body: {"phoneNumber":"+1234567890","message":"{{EventDescription}}"}
  5. Save and enable.

Node-RED

Use an http request node with these settings:

// Function node — prepare payload
msg.headers = {
    "X-API-Key": "sk_live_your_api_key_here",
    "Content-Type": "application/json"
};
msg.payload = {
    phoneNumber: "+1234567890",
    message: "Alert from Node-RED: " + msg.payload
};
return msg;

// Then connect to an HTTP Request node:
//   Method: POST
//   URL: https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send
//   Return: a parsed JSON object

Microsoft Power Automate

  1. Create a new Flow.
  2. Add your trigger (e.g., "When an email arrives").
  3. Add action: HTTP (Premium connector).
  4. Configure:
    • Method: POST
    • URI: https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send
    • Headers: X-API-Key: sk_live_your_api_key_here and Content-Type: application/json
    • Body: {"phoneNumber":"+1234567890","message":"@{triggerBody()?['Subject']}"}
  5. Save and test.

Grafana Alerting

Forward Grafana alerts to SMS by creating a webhook contact point with a small proxy:

// Node.js proxy: receives Grafana alert, sends SMS
const express = require('express');
const axios   = require('axios');
const app     = express();

app.use(express.json());

app.post('/grafana-to-sms', async (req, res) => {
  const alert = req.body;
  const status = alert.status || 'unknown';
  const title  = alert.commonLabels?.alertname || 'Alert';

  try {
    await axios.post(
      'https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send',
      {
        phoneNumber: '+1234567890',
        message: `[Grafana ${status.toUpperCase()}] ${title}: ${alert.commonAnnotations?.description || ''}`
      },
      { headers: { 'X-API-Key': 'sk_live_your_api_key_here', 'Content-Type': 'application/json' } }
    );
  } catch (e) {
    console.error('SMS failed:', e.message);
  }
  res.sendStatus(200);
});

app.listen(4000);

Then in Grafana → Alerting → Contact Points, add a Webhook pointing to https://yourserver.com/grafana-to-sms.

Jenkins / GitHub Actions / GitLab CI

Add a curl step at the end of your CI/CD pipeline:

# Jenkins Pipeline (Groovy)
post {
    failure {
        sh '''curl -s -X POST \
          https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send \
          -H "X-API-Key: ${SMS_API_KEY}" \
          -H "Content-Type: application/json" \
          -d '{"phoneNumber":"+1234567890","message":"Build #${BUILD_NUMBER} FAILED"}'
        '''
    }
}

# GitHub Actions (YAML step)
- name: Notify via SMS
  if: failure()
  run: |
    curl -s -X POST \
      https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send \
      -H "X-API-Key: ${{ secrets.SMS_API_KEY }}" \
      -H "Content-Type: application/json" \
      -d '{"phoneNumber":"+1234567890","message":"Deploy failed — ${{ github.repository }}"}'

❓ Frequently Asked Questions

How does the SMS Gateway work?

Your Android device acts as an SMS gateway server. When you make an API request, we send a push notification to your device, which then sends the SMS using the native Android SmsManager.

Do I need an internet connection on my phone?

Yes, your Android device needs an active internet connection to receive push notifications from our API. However, SMS sending works even without internet (uses cellular network).

What happens if my phone is offline?

Messages will be queued and delivered when your device comes back online. The queue persists for up to 24 hours.

What about RCS messages?

RCS (Rich Communication Services) message reception is coming soon! You'll be able to receive RCS messages and forward them to your webhook, just like regular SMS. RCS sending support is planned for a future release.

What about long messages?

Messages longer than 160 characters are automatically split into multiple SMS parts by the Android system. All parts share the same SMS ID.

Is my data private?

Yes! All SMS content is stored locally on your device only. Our servers never store message content - only aggregate statistics for rate limiting and usage tracking.

What about delivery receipts?

Delivery receipts depend on carrier support. Most carriers provide delivery confirmation, which triggers webhook updates. If the carrier doesn't support delivery receipts, the status will remain at "sent".

Can I use multiple devices?

Each device generates its own API key. You can use multiple devices with different API keys, but each API key is tied to one device and subscription.

What's the cost per SMS?

SMS Gateway Master uses your carrier's SMS plan. The app subscription ($9.99/month) covers the API infrastructure, not SMS costs. Check your carrier plan for SMS pricing.