📡 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.
📋 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
- Your application sends an HTTP request to our API
- We validate your API key and subscription status
- A push notification (FCM) is sent to your Android device
- The app receives the notification and sends the SMS via Android SmsManager
- SMS status updates are sent to your webhook URL in real-time
- All message details are stored locally on your device (privacy-first)
- 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
- Open SMS Gateway Master app on your Android device
- Navigate to Settings → Gateway API
- Tap Generate API Key
- Copy and securely store your API key
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.
Request Body Parameters
The recipient's phone number in international format (e.g., +1234567890)
The SMS message content. Maximum 1600 characters (automatically split into multiple SMS if longer).
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).
Request current status of an SMS and optionally retry if it failed. Also accepts GET with smsId and retry as query parameters.
Request Headers
| Header | Value |
|---|---|
X-API-Key | Your API key |
Content-Type | application/json |
Request Body
The SMS ID returned when the message was sent (e.g., sms_1707400000000_on1t75e).
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
- API sends a push notification to your device
- The app checks the SMS status in its local database
- Current status is sent to your webhook URL
- If
retry=trueand 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)
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
| Code | Error | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid API key |
| 402 | SUBSCRIPTION_REQUIRED | Active subscription needed |
| 400 | INVALID_REQUEST | Missing smsId field |
| 404 | NO_DEVICE | No active device found — open the app |
| 500 | FCM_ERROR | Failed to reach device |
📊 Get Statistics
Retrieve SMS usage statistics for your account.
Query Parameters
| Parameter | Value | Description |
|---|---|---|
type | totals (default) | All-time aggregate totals |
type | monthly | Statistics for a specific month (requires month param) |
type | all-months | Statistics for the last 12 months |
month | e.g. 2026-03 | Required 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:
Set once in app settings (Settings → Gateway API → Webhook URL). Used for all SMS messages by default.
Specify a custom webhook URL in each API request using the webhookUrl parameter. Overrides the default webhook for that specific message.
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
- Open SMS Gateway Master
- Go to Settings → Incoming SMS Forwarding
- Enter your API Endpoint URL
- Enter your X-API-Key (optional, for securing your endpoint)
- Set Conversation History count (0, 5, 10, 20, or 50 messages)
- Enable the Forward Incoming SMS toggle
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: sending → sent → delivered (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 |
|---|---|
sending | Auto-reply triggered — SMS queued for sending (fired immediately before the SMS is handed to the carrier) |
sent | SMS accepted by carrier (confirmed via system SMS_SENT broadcast) |
delivered | SMS delivered to recipient's handset (confirmed via system SMS_DELIVERED broadcast) |
failed | SMS delivery failed — includes an error field with the reason |
Status Callback Fields
| Field | Type | Description |
|---|---|---|
type | string | Always "sms_status" |
smsId | string | Unique ID of the auto-reply SMS. Format: sms_<timestamp_ms>_<8-char-uuid> (e.g. sms_1707400000000_a1b2c3d4) |
status | string | One of: sending, sent, delivered, failed |
sender | string | Phone number of the original SMS sender (the recipient of the auto-reply) |
timestamp | number | Unix timestamp in milliseconds when this status was recorded |
error | string | Only 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
- 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
typefield 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_historyalready includes the current incoming message as its last"in"entry — pass the array directly to your AI model without appendingmessageagain- When history is disabled (count = 0), use the top-level
messagefield 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.
+40721000000vs0721000000) - Status callbacks sequence:
sending(immediate) →sent(carrier accepted) →delivered(handset confirmed). Afailedstatus can occur at thesentordeliveredstage and includes anerrorfield
⚙️ Webhook Setup Guide
1. Set Default Webhook in App
- Open SMS Gateway Master app
- Go to Settings → Gateway API
- Find Webhook URL field
- Enter your webhook URL (e.g., https://your-server.com/webhook)
- 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.
- 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 |
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.
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"
}'
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:
- Visit https://webhook.site — you get a unique URL
- Copy that URL and use it as your
webhookUrlin the API call - Send a test SMS
- 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×tamp=1707400005000
| Parameter | Type | Description |
|---|---|---|
id | string | SMS ID returned by the send endpoint |
status | string | queued | sent | delivered | failed |
timestamp | number | Unix timestamp in milliseconds |
error | string | Present 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 Code | Meaning | Solution |
|---|---|---|
| 200 | Success — SMS queued | — |
| 400 | Bad Request — invalid phone or message | Check phone format (+country code) and message length (1-1600) |
| 401 | Unauthorized — bad API key | Verify key starts with sk_live_ or sk_test_ and has 28+ chars |
| 402 | Payment Required — no active subscription | Activate PRO or start trial in the app |
| 429 | Rate Limited — too many requests | Wait and retry with exponential backoff |
| 500 | Server Error | Retry 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
.envfile to.gitignoreso 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.
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.
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
- Open your Shopify Admin → Settings → Notifications
- Scroll to Webhooks and click Create webhook
- Event: Order creation
- Format: JSON
- URL:
https://yourserver.com/shopify/order-created - Click Save
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
- Upload the
smsgatewayfolder to/modules/ - Go to Back Office → Modules and install "SMS Gateway Master"
- Set your API key in the module configuration
- Test by placing a test order
📦 General E-commerce Patterns
Common SMS automation patterns that work with any e-commerce platform.
Order Lifecycle Notifications
| Event | SMS Template | When 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
- 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).
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 }}"}'
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
- Log in to zapier.com and click Create Zap.
- Trigger — Choose the app that starts the workflow. Examples:
- Gmail — "New Email"
- Google Sheets — "New Spreadsheet Row"
- Stripe — "New Payment"
- Calendly — "New Event"
- Action — Choose Webhooks by Zapier → Custom Request.
- Configure the action:
Method POSTURL https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_sendData {"phoneNumber":"+1234567890","message":"New email from {{sender}}: {{subject}}"}Headers X-API-Key: sk_live_your_api_key_hereContent-Type: application/json - Click Test to send a test SMS.
- Turn on your Zap.
Popular Zap Examples
| Trigger | SMS Message |
|---|---|
| Google Sheets — New Row | New lead: {{Name}} — {{Email}} |
| Stripe — New Payment | Payment received: {{Amount}} from {{Customer}} |
| Calendly — New Event | New booking: {{Invitee Name}} on {{Event Date}} |
| Typeform — New Entry | New form submission from {{Name}} |
🔧 n8n Integration
Integrate SMS Gateway with n8n — the open-source, self-hosted workflow automation platform.
HTTP Request Node Configuration
| Field | Value |
|---|---|
| Method | POST |
| URL | https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send |
| Authentication | Generic Credential Type → Header Auth |
| Header Name | X-API-Key |
| Header Value | sk_live_your_api_key_here |
| Body Content Type | JSON |
| 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
- Create a new Scenario in make.com.
- Add a Trigger module (e.g., Google Sheets → Watch Rows).
- Add an HTTP → Make a request module with these settings:
| Field | Value |
|---|---|
| URL | https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send |
| Method | POST |
| Headers | X-API-Key: sk_live_your_api_key_hereContent-Type: application/json |
| Body type | Raw → JSON |
| Request content | {"phoneNumber":"{{phone}}","message":"{{message}}"} |
- Map the
phoneandmessagevariables from your trigger module. - Click Run once to test.
- 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
- Create a new Applet at ifttt.com/create.
- If This — choose any trigger (Weather, Smart Home, etc.).
- Then That — choose Webhooks → Make a web request.
- 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}}"}
- URL:
- 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
- Create a new Flow.
- Add your trigger (e.g., "When an email arrives").
- Add action: HTTP (Premium connector).
- Configure:
- Method: POST
- URI:
https://us-central1-sms-gateway-ae7e1.cloudfunctions.net/api_sms_send - Headers:
X-API-Key: sk_live_your_api_key_hereandContent-Type: application/json - Body:
{"phoneNumber":"+1234567890","message":"@{triggerBody()?['Subject']}"}
- 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.