Skip to content

Twilio Send SMS: Programmable SMS Messaging API Guide

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Twilio Send SMS: Programmable SMS Messaging API Guide. We cover key concepts, practical examples, and best practices to help you master this topic.

Twilio Programmable SMS lets you send text messages to any phone number globally, supporting message scheduling, delivery status callbacks, long message concatenation, and MMS with media attachments.

What You'll Learn

How to send SMS messages with the Twilio Python SDK, compose messages with Unicode support, schedule future delivery, receive delivery status via Webhooks, send long messages (segmentation), and attach media as MMS.

Why It Matters

SMS has 98% open rates within 3 minutes, making it the most reliable notification channel. DodaTech uses SMS for order confirmations, account alerts, and verification codes with real-time delivery tracking.

Real-World Use

A customer places an order on DodaTech. The server sends an SMS confirmation, sets a Webhook for delivery status, and when the message is delivered, a status callback updates the order tracking system.

flowchart LR
    A["Send\nSMS API Call"] --> B["Twilio\nProcesses"]
    B --> C["Message\nQueued"]
    C --> D["Carrier\nDelivery"]
    D --> E{"Status\nUpdate"}
    E -->|delivered| F["Status Callback\nsuccess"]
    E -->|undelivered| G["Status Callback\nfailed"]
    E -->|failed| G
    style A fill:#f22f46,color:#fff
    style D fill:#dbeafe,stroke:#2563eb
    style F fill:#bbf7d0,stroke:#16a34a
    style G fill:#fecaca,stroke:#dc2626

Sending a Basic SMS

import os
from twilio.rest import Client

account_sid = os.environ["TWILIO_ACCOUNT_SID"]
auth_token = os.environ["TWILIO_AUTH_TOKEN"]
from_number = os.environ["TWILIO_PHONE_NUMBER"]

client = Client(account_sid, auth_token)

message = client.messages.create(
    body="Your DodaTech order ORD-12345 has been confirmed!",
    from_=from_number,
    to="+14155551234"
)

print(f"Message SID: {message.sid}")
print(f"Status: {message.status}")
print(f"To: {message.to}")
print(f"From: {message.from_}")
print(f"Body: {message.body[:50]}...")
# Expected output:
# Message SID: SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Status: queued
# To: +14155551234
# From: +14155559876
# Body: Your DodaTech order ORD-12345 has been conf...

Scheduling Messages

from datetime import datetime, timedelta
import pytz

def schedule_sms(to_number, message_body, send_at):
    message = client.messages.create(
        body=message_body,
        from_=from_number,
        to=to_number,
        send_at=send_at,
        schedule_type="fixed"
    )
    print(f"Scheduled: {message.sid}")
    print(f"Send at: {send_at}")
    print(f"Status: {message.status}")
    return message

# Schedule for 2 hours from now
send_time = datetime.now(pytz.UTC) + timedelta(hours=2)
schedule_sms(
    to_number="+14155551234",
    message_body="Reminder: Your appointment is tomorrow at 10 AM.",
    send_at=send_time
)
# Expected output:
# Scheduled: SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Send at: 2026-06-28 15:00:00+00:00
# Status: scheduled

Delivery Status Callbacks

# Set status_callback when sending
def send_with_tracking(to_number, message_body):
    message = client.messages.create(
        body=message_body,
        from_=from_number,
        to=to_number,
        status_callback="https://example.com/sms/status"
    )
    print(f"Sent with tracking: {message.sid}")

# The status endpoint receives POST with:
# - MessageSid
# - MessageStatus (queued, sent, delivered, failed, undelivered)
# - ErrorCode
# - To, From, Body

# Flask handler example
"""
@app.route("/sms/status", methods=["POST"])
def sms_status():
    message_sid = request.form["MessageSid"]
    status = request.form["MessageStatus"]
    error_code = request.form.get("ErrorCode")
    print(f"Message {message_sid}: {status}")
    if error_code:
        print(f"Error: {error_code}")
    return "", 200
"""

Long Messages and MMS

# Twilio automatically concatenates messages > 160 characters
# Each segment = 160 chars (GSM-7) or 70 chars (UCS-2/Unicode)

def send_long_message(to_number, long_text):
    message = client.messages.create(
        body=long_text,
        from_=from_number,
        to=to_number
    )
    print(f"SID: {message.sid}")
    print(f"Body length: {len(long_text)} chars")
    print(f"Segment count: {message.num_segments}")
    return message

# 300 character message (2 segments)
long_body = "Your DodaTech Pro subscription has been upgraded. " * 6
send_long_message("+14155551234", long_body)
# Expected output:
# SID: SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Body length: 312 chars
# Segment count: 2

# Send MMS with media
def send_mms(to_number, media_url):
    message = client.messages.create(
        body="Check out this image!",
        from_=from_number,
        to=to_number,
        media_url=[media_url]
    )
    print(f"MMS sent: {message.sid}")
    print(f"Media count: {len(message.media.list())}")
    return message

# send_mms("+14155551234", "https://example.com/photo.jpg")

Common Mistakes

1. Sending Without a Registered Sender ID

In many countries, you need an alphanumeric Sender ID (like DODATECH) registered with carriers. Without registration, messages show as random numbers or get blocked.

2. Not Handling Status Callbacks

Without status callbacks, you don't know if the message was delivered or failed. Always set status_callback for production use to track delivery and detect issues.

3. Ignoring Message Segmentation Costs

Each SMS segment is billed separately. A 500-character message costs up to 4x a single message. Test the num_segments property to estimate costs.

4. Sending 10DLC-Unregistered Messages

In the US, A2P 10DLC registration is required for application-to-person messaging. Unregistered traffic may be blocked or filtered. Register your messaging use case in the Twilio Console.

5. Using Incorrect Number Formatting

Always use E.164 format (+14155551234). Never use formatted numbers like (415) 555-1234 or 415-555-1234. Strip all formatting from user input before passing to the API.

Practice Questions

  1. What is the maximum length of a single SMS segment?
  2. How do you know if a message was delivered?
  3. What is message concatenation?
  4. How do you send an MMS with Twilio?

Answers:

  1. 160 characters for GSM-7 encoding (standard ASCII). 70 characters for UCS-2 (Unicode, emoji, special characters). Beyond these limits, Twilio concatenates into segments.
  2. Set a status_callback URL when sending. Twilio POSTs status updates (queued, sent, delivered, failed, undelivered) to your endpoint.
  3. Messages longer than 160 characters are split into multiple segments. Twilio and the receiving phone reassemble them transparently. Each segment costs separately.
  4. Include a media_url parameter with a publicly accessible URL to an image. The message is sent as MMS instead of SMS. MMS is more expensive than SMS.

Challenge: Build a notification system that sends SMS order confirmations, tracks delivery with status callbacks, handles failed deliveries with 3 retry attempts, segments long messages correctly, sends MMS receipts with order images, and logs all status transitions.

FAQ

How fast do SMS messages deliver?

Most SMS messages deliver within 5-10 seconds in the US and Europe. International messages may take 30-60 seconds depending on carrier routing.

Can I send SMS to any country?

Twilio supports SMS to 190+ countries. Some countries require sender registration or have specific content restrictions. Check the Twilio country guide before sending.

What happens if I send to an opted-out number?

Twilio automatically blocks messages to numbers that have opted out via STOP/HELP commands. You'll receive a 21610 error (landline or unreachable carrier).

How do I know if a number can receive SMS?

Not all numbers can receive SMS (some landlines, VoIP numbers). Use Twilio's Lookup API to check carrier and line type before sending.

Can I send Unicode/emoji in SMS?

Yes, but Unicode messages use 70 characters per segment instead of 160. Sending emoji increases segment count and cost significantly.

Mini Project

Build an SMS notification system: send a welcome message to a test number, set up a status callback endpoint, schedule a reminder message for 24 hours later, send a long message and log segment count, send an MMS with a test image, and review delivery logs in the Twilio Console.

What's Next

Receive SMS — handle incoming text messages with webhooks.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro