Skip to main content
Reduce no-shows by sending automated SMS appointment reminders with the Telnyx Messaging API. This guide covers scheduling strategies, message templates, opt-out handling, and timing best practices.

How it works


Send an appointment reminder

import os
from datetime import datetime

from telnyx import Telnyx

client = Telnyx(api_key=os.environ.get("TELNYX_API_KEY"))


def send_reminder(to: str, patient_name: str, appointment_time: datetime, location: str):
    """Send an appointment reminder SMS."""
    formatted_time = appointment_time.strftime("%A, %B %d at %I:%M %p")

    response = client.messages.send(
        from_=os.environ.get("TELNYX_FROM_NUMBER"),
        to=to,
        text=(
            f"Hi {patient_name}, this is a reminder for your appointment "
            f"on {formatted_time} at {location}. "
            f"Reply CONFIRM to confirm or CANCEL to cancel."
        ),
    )
    return response.data


# Example
send_reminder(
    to="+15559876543",
    patient_name="Jane",
    appointment_time=datetime(2026, 3, 15, 14, 30),
    location="123 Main St, Suite 200",
)

Scheduling strategies

Choose a scheduling approach based on your application’s requirements:
The simplest approach — use the Telnyx API’s built-in scheduled messaging feature. No external scheduler needed.
Python
from datetime import datetime, timedelta, timezone

# Schedule reminder 24 hours before appointment
reminder_time = appointment_time - timedelta(hours=24)

response = client.messages.send(
    from_=os.environ.get("TELNYX_FROM_NUMBER"),
    to="+15559876543",
    text="Reminder: You have an appointment tomorrow at 2:30 PM.",
    send_at=reminder_time.astimezone(timezone.utc).isoformat(),
)
Pros: No infrastructure needed, simple API call Cons: Limited to single scheduled time per API call, max 7 days in advance

Handle replies (confirm / cancel)

Set up a webhook to receive replies and update appointment status:
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/webhooks/messaging", methods=["POST"])
def handle_webhook():
    data = request.json["data"]

    if data["event_type"] != "message.received":
        return jsonify({"status": "ignored"}), 200

    payload = data["payload"]
    from_number = payload["from"]["phone_number"]
    text = payload["text"].strip().upper()

    if text == "CONFIRM":
        # Update appointment status in your database
        db.execute(
            "UPDATE appointments SET status = 'confirmed' WHERE phone = %s "
            "AND start_time > NOW()",
            (from_number,)
        )
        # Send confirmation
        client.messages.send(
            from_=os.environ.get("TELNYX_FROM_NUMBER"),
            to=from_number,
            text="Your appointment has been confirmed. See you then!",
        )

    elif text == "CANCEL":
        db.execute(
            "UPDATE appointments SET status = 'cancelled' WHERE phone = %s "
            "AND start_time > NOW()",
            (from_number,)
        )
        client.messages.send(
            from_=os.environ.get("TELNYX_FROM_NUMBER"),
            to=from_number,
            text="Your appointment has been cancelled. "
                 "Please call us to reschedule.",
        )

    return jsonify({"status": "ok"}), 200

Opt-out handling

You must honor opt-out requests. Telnyx automatically handles STOP/UNSTOP keywords for 10DLC and Toll-Free numbers, but you should also track opt-outs in your application.
Telnyx automatically handles standard opt-out keywords (STOP, UNSUBSCRIBE, CANCEL, END, QUIT) for US long codes and toll-free numbers. When a user texts STOP:
  1. Telnyx sends an automatic reply confirming the opt-out
  2. Future messages to that number are blocked at the carrier level
  3. You receive a message.received webhook with the STOP keyword
See Advanced Opt-In/Out for customization options.
In addition to Telnyx’s automatic handling, track opt-outs in your database to prevent scheduling reminders for opted-out users:
def handle_opt_out(phone_number: str):
    """Mark a phone number as opted out."""
    db.execute(
        "UPDATE patients SET sms_opted_out = TRUE WHERE phone = %s",
        (phone_number,)
    )
    # Cancel any pending reminders
    db.execute(
        "DELETE FROM scheduled_reminders WHERE phone = %s AND sent = FALSE",
        (phone_number,)
    )

def can_send_reminder(phone_number: str) -> bool:
    """Check if we can send a reminder to this number."""
    result = db.query(
        "SELECT sms_opted_out FROM patients WHERE phone = %s",
        (phone_number,)
    )
    return result and not result.sms_opted_out

Timing best practices

1

Send reminders at appropriate times

  • 24 hours before: Primary reminder — enough time to cancel/reschedule
  • 2-3 hours before: Final reminder for same-day appointments
  • Avoid late night/early morning: Only send between 9 AM and 8 PM in the recipient’s local time zone
2

Use multiple reminder windows

For high-value appointments (medical, legal), send two reminders:
  1. 48 or 24 hours before — gives time to reschedule
  2. 2-3 hours before — final confirmation
For routine appointments (salon, auto service), a single reminder 24 hours before is usually sufficient.
3

Respect time zones

Always calculate reminder times in the recipient’s local time zone. Sending a reminder at 3 AM is worse than not sending one at all.
from zoneinfo import ZoneInfo

# Store patient timezone in your database
patient_tz = ZoneInfo(patient.timezone)  # e.g., "America/New_York"
local_time = reminder_time.astimezone(patient_tz)

# Only send between 9 AM and 8 PM local time
if 9 <= local_time.hour < 20:
    send_reminder(...)
else:
    # Reschedule to 9 AM local time
    next_9am = local_time.replace(hour=9, minute=0)
    if next_9am < local_time:
        next_9am += timedelta(days=1)
    schedule_reminder_at(next_9am, ...)
4

Keep messages concise

SMS has character limits. Keep reminders under 160 characters (1 segment) when possible to minimize costs. Include only essential info:
  • Patient name
  • Date and time
  • Location (short form)
  • Reply instructions

Message templates

Healthcare:
Hi {name}, reminder: your appointment with Dr. {provider} is on {date} at {time}.
Reply CONFIRM or CANCEL. Call {phone} to reschedule.
Dental:
{name}, your dental cleaning at {practice} is tomorrow at {time}.
Please arrive 10 min early. Reply C to confirm, X to cancel.
Salon / Spa:
Hi {name}! Your {service} appointment is {date} at {time}.
Reply YES to confirm or call {phone} to reschedule.
Auto Service:
{name}, your vehicle service at {shop} is scheduled for {date} at {time}.
Reply OK to confirm.
Legal / Financial:
Reminder: Your meeting with {advisor} is on {date} at {time} at {location}.
Please bring required documents. Reply CONFIRM to confirm.