📥 Now Live — Two-Way SMS

Two-Way SMS — Send, Receive, and Auto-Reply via API

Transform your Android phone into a full two-way SMS gateway. Forward every incoming SMS to your server and auto-reply programmatically — build chatbots, support flows, and AI-powered SMS automation. No third-party provider needed.

Download on Google Play API Documentation

How Two-Way SMS Works

The complete flow from incoming SMS to your server and back — in under a second.

📱
Customer sends SMS to your number
📲
SMS Gateway Master receives it on device
🌐
HTTP POST to your webhook URL
🖥️
Your server processes & returns reply
✉️
App auto-sends reply to the sender
💡 Auto-Reply is Optional — Return {"sms_text": "your reply"} to auto-respond. Return HTTP 200 with an empty body if no reply is needed. The same endpoint also receives outgoing SMS delivery status updates (differentiate using the type field).

Setup in 3 Steps

  1. Install SMS Gateway Master → sign in → activate TRIAL or PRO
  2. Go to Settings → Incoming SMS Forwarding → enable toggle → paste your webhook URL
  3. Deploy your webhook server (see examples below) → receive and reply to SMS in real time

Webhook Payload

Your server receives this JSON payload for every incoming SMS.

{
  "type": "incoming_sms",
  "sender": "+40721000000",
  "message": "Hi, I need help with my order",
  "timestamp": 1707400000000,
  "conversation_history": [
    { "role": "out", "message": "Your order #1234 has shipped!", "timestamp": 1707399000000 },
    { "role": "in",  "message": "Hi, I need help with my order", "timestamp": 1707400000000 }
  ]
}
⚠️ conversation_history already contains the current incoming message as its last entry (role: "in"). Feed it directly to your AI model — do not append message again. Requires Conversation History enabled in Settings (0 / 5 / 10 / 20 / 50 messages).

To auto-reply, return:

HTTP 200
Content-Type: application/json

{ "sms_text": "Thanks! Our support team will contact you shortly." }

Code Examples

Production-ready auto-responder implementations.

Node.js
Python
Node.js + OpenAI
Python + OpenAI

Auto-Responder (Node.js / Express)

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;

  // Secure your endpoint
  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}`);

    // Keyword-based auto-reply
    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
    return res.status(200).send();
  }

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

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

app.listen(3000, () => console.log('Webhook server running on :3000'));

Auto-Responder (Python / Flask)

from flask import Flask, request, jsonify

app = Flask(__name__)

@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
    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)")

        # Keyword-based auto-reply
        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':
        print(f"📊 SMS {data['smsId']} → {data['status']}")

    return '', 200

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

AI-Powered Chatbot (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 {
      messages.push({ role: 'user', content: message });
    }

    try {
      const completion = await openai.chat.completions.create({
        model: 'gpt-4o-mini',
        messages,
        max_tokens: 100
      });
      return res.json({ sms_text: completion.choices[0].message.content });
    } 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 Chatbot (Python + OpenAI)

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

app = Flask(__name__)
client = OpenAI()  # uses OPENAI_API_KEY env var

@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 last "in" entry
            for msg in history:
                role = 'user' if msg['role'] == 'in' else 'assistant'
                messages.append({'role': role, 'content': msg['message']})
        else:
            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

What you can build with two-way SMS automation.

🤖 AI SMS Chatbot

Connect incoming SMS to OpenAI, Claude, or Gemini. Include conversation history for context-aware, multi-turn conversations entirely via SMS — no app required for customers.

🤝 Customer Support

Auto-reply with FAQ answers based on keywords. Escalate complex queries to a human agent. Log all SMS conversations in your CRM automatically.

📅 Appointment Confirmations

Send "Your appointment is tomorrow at 10AM. Reply YES to confirm or NO to cancel." Process the reply and update your booking system automatically.

🔐 OTP / 2FA Receive

Forward OTP codes received on your Android to your backend for automated 2FA verification flows. Great for testing or server-side auth automation.

⭐ Feedback Collection

Ask customers to rate their experience (reply 1–5). Capture the reply on your server and store it in your analytics or CRM with zero manual work.

🛒 Order Status by SMS

Customers text their order number — your server looks it up and auto-replies with the current status. Real-time, no app needed, works on any phone.

FAQ — Two-Way SMS

Does SMS Gateway Master support two-way SMS?
Yes. SMS Gateway Master supports full two-way SMS: outgoing SMS via REST API, and incoming SMS forwarding to your webhook. The same endpoint receives both incoming SMS payloads (type: "incoming_sms") and delivery status updates (type: "sms_status").
Can I build an SMS chatbot?
Yes. Enable Incoming SMS Forwarding, set your webhook URL, and return {"sms_text": "reply"} from your endpoint. For AI-powered replies, pass the conversation_history array directly to OpenAI or Claude — it already includes the current message as the last entry.
Is auto-reply mandatory?
No. Return HTTP 200 with an empty body if you don't want to auto-reply. The sms_text field is optional — only include it when you want the app to send a reply back to the sender.
How do I get conversation history in the webhook?
Go to Settings → Incoming SMS Forwarding → Conversation History and choose 5, 10, 20, or 50 messages. The conversation_history array is included in every webhook payload with both sent ("out") and received ("in") messages, sorted oldest → newest. The current incoming message is already the last entry.
Is two-way SMS free?
Incoming SMS Forwarding requires a TRIAL (free, 7 days, 100 SMS/day) or PRO subscription (€5/month or €52/year, 10,000 SMS/day). There are no per-message fees — the flat subscription covers both outgoing API SMS and incoming SMS forwarding.
How do I secure my webhook endpoint?
In the app Settings, set a Webhook Secret Key. The app sends this as an X-API-Key header with every webhook request. Validate it in your server code to reject unauthorized requests.

Build Your Two-Way SMS System Today

7-day free trial. 100 SMS/day. No credit card required.