Skip to content

Twilio Receive SMS — Handling Incoming Text Messages with Webhooks

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Twilio Receive SMS. We cover key concepts, practical examples, and best practices to help you master this topic.

Twilio receives incoming SMS messages by sending an HTTP POST Webhook to your application when someone sends a text to your Twilio number, allowing you to Process messages and respond programmatically.

What You'll Learn

  • How to configure your Twilio number for incoming SMS
  • How to process incoming SMS Webhooks
  • How to respond to SMS with TwiML

Why It Matters

Receiving SMS enables two-way communication: customer support via text, order confirmations via reply, and interactive SMS applications. Twilio's webhook model lets you handle incoming messages with a simple HTTP endpoint.

Real-World Use

DodaTech's support number receives SMS from customers. When a customer texts "STATUS" to the support number, the webhook processes the message, looks up their latest order status, and replies with tracking information — all without human intervention.

Webhook Setup

from flask import Flask, request, Response
from twilio.twiml.messaging_response import MessagingResponse

app = Flask(__name__)

@app.route('/twilio/sms-inbound', methods=['POST'])
def handle_incoming_sms():
    # Extract message details
    from_number = request.form.get('From')
    to_number = request.form.get('To')
    body = request.form.get('Body', '').strip()
    message_sid = request.form.get('MessageSid')

    print(f"Received SMS from {from_number}: {body}")

    # Log the incoming message
    database.log_incoming_message(
        sid=message_sid,
        from_number=from_number,
        to_number=to_number,
        body=body
    )

    # Create a response
    response = MessagingResponse()
    response.message(f"Thanks for your message! We received: '{body[:50]}...'")

    return Response(str(response), mimetype='text/xml')

Interactive SMS Handler

@app.route('/twilio/sms-interactive', methods=['POST'])
def handle_interactive_sms():
    from_number = request.form.get('From')
    body = request.form.get('Body', '').strip().upper()
    response = MessagingResponse()

    if body == 'HELP':
        response.message(
            "Available commands:\n"
            "STATUS - Check your order status\n"
            "BALANCE - Check account balance\n"
            "SUPPORT - Talk to a human\n"
            "STOP - Unsubscribe"
        )

    elif body == 'STATUS':
        orders = database.get_recent_orders(from_number)
        if orders:
            msg = "Your orders:\n"
            for order in orders[:3]:
                msg += f"#{order['id']}: {order['status']}\n"
            response.message(msg)
        else:
            response.message("No recent orders found.")

    elif body.startswith('SUPPORT'):
        database.create_support_ticket(from_number, body)
        response.message(
            "A support agent will contact you shortly. "
            "Your ticket ID: TKT-" + str(int(time.time()))
        )

    elif body == 'STOP':
        database.update_sms_preference(from_number, opted_out=True)
        response.message("You've been unsubscribed. Reply START to resubscribe.")

    else:
        response.message(
            "I didn't understand that. Reply HELP for available commands."
        )

    return Response(str(response), mimetype='text/xml')

Processing Incoming Messages

def parse_sms_command(body, from_number):
    """Parse incoming SMS and determine the action to take"""
    body = body.strip().upper()

    if body == 'STOP' or body == 'STOPALL' or body == 'UNSUBSCRIBE' or body == 'CANCEL':
        return {'action': 'opt_out', 'message': 'You have been unsubscribed.'}

    elif body == 'START' or body == 'YES':
        return {'action': 'opt_in', 'message': 'You have been resubscribed.'}

    elif body == 'HELP' or body == 'INFO':
        return {
            'action': 'help',
            'message': 'Commands: HELP, STATUS, BALANCE, SUPPORT, STOP'
        }

    elif body.startswith('Y') or body.startswith('YES'):
        return {'action': 'confirm', 'message': 'Confirmed!'}

    elif body.startswith('N') or body == 'NO':
        return {'action': 'decline', 'message': 'Action cancelled.'}

    else:
        return {'action': 'unknown', 'message': 'Reply HELP for options.'}

Common Mistakes

1. Not Returning TwiML Properly

The webhook must return a text/xml response with valid TwiML. Returning JSON or HTML causes Twilio to retry and potentially mark the message as failed.

2. Forgetting to Acknowledge Opt-Out Keywords

Twilio requires handling of standard opt-out keywords (STOP, STOPALL, UNSUBSCRIBE, CANCEL). Not handling them violates carrier regulations.

3. Slow Webhook Responses

Twilio expects a response within 15 seconds. If your processing takes longer, return an empty 200 response immediately and process asynchronously.

4. Not Validating Twilio Requests

Anyone could send requests to your webhook URL. Validate the Twilio signature to ensure requests actually come from Twilio.

5. Hardcoding the Messaging Service SID

If you use a Messaging Service, messages may come from different numbers. Handle the To parameter dynamically.

Practice Questions

  1. What HTTP method does Twilio use for incoming SMS webhooks?
  2. What response format does Twilio expect?
  3. What standard opt-out keywords must be handled?
  4. What is the timeout for webhook responses?
  5. How do you validate that a webhook came from Twilio?

Answers

  1. POST. 2. TwiML (text/xml). 3. STOP, STOPALL, UNSUBSCRIBE, CANCEL. 4. 15 seconds. 5. Validate the X-Twilio-Signature header using your auth token.

Challenge

Build an interactive SMS chatbot that: handles HELP, STATUS, STOP, and START commands, looks up user data from a database, responds with personalized information, handles opt-out/opt-in according to regulations, and logs all conversations.

FAQ

How does Twilio send incoming SMS to my app?

Via an HTTP POST webhook to your configured URL when someone texts your number.

What is TwiML?

Twilio Markup Language - XML instructions that tell Twilio what to do next.

How fast must my webhook respond?

Within 15 seconds. Otherwise Twilio retries the webhook.

What are the standard opt-out keywords?

STOP, STOPALL, UNSUBSCRIBE, CANCEL. You must handle these.

Can I receive MMS (picture messages)?

Yes, the webhook includes NumMedia and MediaUrl parameters for MMS.

Mini Project

Build a two-way SMS customer support system: incoming SMS webhook that categorizes messages (support, order status, general inquiry), automated responses for common queries, ticket creation for complex issues, and forwarding to human agents when automated handling fails.

What's Next

  • Learn about Twilio Messaging Service for scaling SMS
  • Explore Twilio Verify for phone verification
  • Continue to Twilio WhatsApp API for business messaging

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro