DIDfarm
  • Numbers
  • Trunks
  • Messaging
  • Connect
  • Pricing
  • Coverage
  • Help
🇬🇧 EN 🇳🇱 NL 🇩🇪 DE 🇫🇷 FR 🇪🇸 ES 🇧🇷 PT 🇸🇦 AR 🇨🇳 ZH 🇯🇵 JA 🇮🇳 HI
Sign in Get a Number
← Help Center
On this page
Overview Prerequisites Reminder Flow Schedule a Reminder Send the Reminder Handle Replies Cancellation Flow WhatsApp Templates Best Practices FAQ

Appointment Reminders via SMS & WhatsApp

Messaging · 10 min read Reminders SMS WhatsApp
What this guide covers: Building an automated appointment reminder system using the DIDfarm SMS and WhatsApp APIs. You will learn how to schedule reminders, send them at the right time, handle patient or client replies, and manage cancellations — all through a single API integration.

Overview

Missed appointments cost businesses across healthcare, professional services, and hospitality billions each year. Automated reminders sent via SMS or WhatsApp can reduce no-show rates by 20–30%, according to industry benchmarks.

DIDfarm lets you send reminders from the same local or national numbers your customers already recognise. Because messages come from a real phone number (not a short code), open rates are significantly higher and recipients can reply directly.

SMS vs WhatsApp for reminders

Channel Delivery Rich content Reply handling Best for
SMS Near-instant, works on all phones Plain text only (160 chars / segment) Keyword-based (YES / NO) Universal reach, older demographics
WhatsApp Near-instant, requires WhatsApp app Buttons, images, location pins Quick-reply buttons + free text Rich interactions, European & LATAM audiences
Tip: Many businesses use both channels together — send WhatsApp first and fall back to SMS if the recipient does not have WhatsApp or the message is undelivered after 60 seconds.

Prerequisites

  • A DIDfarm account with at least one active phone number.
  • SMS enabled on the number (toggle in the portal under My Numbers → number settings).
  • For WhatsApp: a WhatsApp-enabled number (request via the portal or contact support).
  • A DIDfarm API key generated in the portal under Account → API Keys.
  • A scheduling system in your application (cron, task queue, or external scheduler).
  • A publicly reachable webhook endpoint to receive inbound replies.

Reminder Flow

A typical appointment reminder flow involves four stages. Here is the end-to-end lifecycle from booking to confirmation:

  1. Appointment booked — Your system stores the appointment details and calculates reminder times (e.g. 24 hours and 2 hours before).
  2. Reminder scheduled — A background job or cron task is queued for each reminder window.
  3. Reminder sent — At the scheduled time, your system calls the DIDfarm API to send an SMS or WhatsApp message with appointment details.
  4. Reply received — The patient or client replies YES, NO, or RESCHEDULE. Your webhook handler parses the reply and updates the booking accordingly.
FLOW DIAGRAM
Appointment booked
       |
       v
Schedule reminders (24h + 2h before)
       |
       v
Cron / queue fires at T-24h
       |
       v
POST /api/v1/sms/messages  ──────>  SMS / WhatsApp delivered
       |                                      |
       v                                      v
Cron fires at T-2h                  Patient replies YES / NO
       |                                      |
       v                                      v
Send 2nd reminder              Webhook fires on your server
                                              |
                                              v
                                   Update booking status

Schedule a Reminder

1

Queue reminders when the appointment is created

When a new appointment is saved, calculate the reminder timestamps and persist them in your database or job queue. Most businesses send two reminders: one 24 hours before and one 2 hours before the appointment.

SCHEDULING LOGIC — PSEUDO-CODE
function onAppointmentCreated(appointment) {
  const reminders = [
    { offset: 24 * 60,  label: '24h' },   // 24 hours before
    { offset: 2 * 60,   label: '2h'  },   // 2 hours before
  ];

  for (const r of reminders) {
    const sendAt = subtractMinutes(appointment.datetime, r.offset);

    // Skip if the send time is already in the past
    if (sendAt <= now()) continue;

    scheduleJob('send-reminder', {
      appointmentId: appointment.id,
      recipientPhone: appointment.phone,
      sendAt: sendAt,
      label: r.label,
    });
  }
}
Timezone handling: Always store appointment times in UTC internally. Convert to the patient's local timezone only when composing the message body so the displayed time matches their expectations.

Send the Reminder

2

Call the DIDfarm API when the scheduled time arrives

When your queue worker or cron job fires, send the reminder via the DIDfarm messaging API. Include the appointment date, time, location, and a clear call to action.

SMS reminder example

POST /API/V1/SMS/MESSAGES
curl -X POST https://didfarm.com/api/v1/sms/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+31201234567",
    "to": "+31612345678",
    "body": "Reminder: Your appointment with Dr. van Berg is tomorrow, April 6 at 10:30 AM at Wijnhaven Clinic, Rotterdam. Reply YES to confirm or NO to cancel."
  }'

WhatsApp reminder example

POST /API/V1/WHATSAPP/MESSAGES
curl -X POST https://didfarm.com/api/v1/whatsapp/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+31201234567",
    "to": "+31612345678",
    "template": "appointment_reminder",
    "template_variables": {
      "1": "Dr. van Berg",
      "2": "April 6, 2026",
      "3": "10:30 AM",
      "4": "Wijnhaven Clinic, Rotterdam"
    }
  }'

Node.js integration example

SEND REMINDER — NODE.JS
const axios = require('axios');

async function sendReminder(appointment) {
  const localTime = formatInTimezone(
    appointment.datetime,
    appointment.timezone
  );

  const body = [
    `Reminder: Your appointment with ${appointment.providerName}`,
    `is on ${localTime.date} at ${localTime.time}`,
    `at ${appointment.location}.`,
    `Reply YES to confirm or NO to cancel.`,
  ].join(' ');

  const response = await axios.post(
    'https://didfarm.com/api/v1/sms/messages',
    {
      from: process.env.DIDFARM_NUMBER,
      to: appointment.phone,
      body: body,
    },
    {
      headers: {
        Authorization: `Bearer ${process.env.DIDFARM_API_KEY}`,
        'Content-Type': 'application/json',
      },
    }
  );

  // Store the message ID for delivery tracking
  await db.reminders.update(appointment.reminderId, {
    messageId: response.data.id,
    status: 'sent',
    sentAt: new Date(),
  });
}
Response: A successful send returns a 201 status with the message ID. Store this ID to correlate delivery status webhooks later.

Handle Replies

3

Process inbound messages via your webhook

When a recipient replies to your reminder, DIDfarm sends an HTTP POST to the webhook URL configured on your number. Parse the message body for keywords to determine the patient's intent.

INBOUND WEBHOOK PAYLOAD
{
  "id": "msg_8f3a2b1c",
  "from": "+31612345678",
  "to": "+31201234567",
  "body": "YES",
  "received_at": "2026-04-05T08:31:12Z",
  "channel": "sms"
}

Webhook handler with keyword parsing

WEBHOOK HANDLER — NODE.JS (EXPRESS)
const express = require('express');
const app = express();
app.use(express.json());

// Normalise the reply to a known intent
function parseReply(body) {
  const text = body.trim().toUpperCase();

  const confirmKeywords  = ['YES', 'Y', 'CONFIRM', 'OK', 'SI', 'JA'];
  const cancelKeywords   = ['NO', 'N', 'CANCEL', 'NEE'];
  const reschedKeywords  = ['RESCHEDULE', 'CHANGE', 'MOVE', 'VERPLAATS'];

  if (confirmKeywords.includes(text))  return 'confirmed';
  if (cancelKeywords.includes(text))   return 'cancelled';
  if (reschedKeywords.includes(text))  return 'reschedule';

  return 'unknown';
}

app.post('/webhooks/didfarm/inbound', async (req, res) => {
  const { from, body, channel } = req.body;

  // Look up the upcoming appointment for this phone number
  const appointment = await db.appointments.findUpcoming(from);

  if (!appointment) {
    console.log(`No upcoming appointment for ${from}`);
    return res.sendStatus(200);
  }

  const intent = parseReply(body);

  switch (intent) {
    case 'confirmed':
      await db.appointments.update(appointment.id, {
        status: 'confirmed',
      });
      await sendSms(from, 'Thank you! Your appointment is confirmed.');
      break;

    case 'cancelled':
      await db.appointments.update(appointment.id, {
        status: 'cancelled',
      });
      await sendSms(
        from,
        'Your appointment has been cancelled. '
        + 'To rebook, visit our website or call us.'
      );
      break;

    case 'reschedule':
      await db.appointments.update(appointment.id, {
        status: 'reschedule_requested',
      });
      await sendSms(
        from,
        'We will contact you shortly to find a new time. '
        + 'You can also rebook online at our website.'
      );
      break;

    default:
      await sendSms(
        from,
        'Sorry, we did not understand your reply. '
        + 'Please reply YES to confirm or NO to cancel.'
      );
  }

  res.sendStatus(200);
});
Important: Always return a 200 status from your webhook handler, even if you cannot process the message. Returning an error causes DIDfarm to retry delivery, which could result in duplicate processing.

Cancellation Flow

4

Send a cancellation confirmation

When a patient cancels via reply, it is good practice to send an immediate confirmation so they know the cancellation was processed. You should also cancel any remaining scheduled reminders for that appointment.

CANCELLATION HANDLER — NODE.JS
async function handleCancellation(appointment) {
  // 1. Update the appointment status
  await db.appointments.update(appointment.id, {
    status: 'cancelled',
    cancelledAt: new Date(),
    cancelledVia: 'sms_reply',
  });

  // 2. Remove any pending reminder jobs
  await queue.removeByTag(`appointment:${appointment.id}`);

  // 3. Send cancellation confirmation
  await sendSms(
    appointment.phone,
    `Your appointment on ${appointment.dateFormatted} has been `
    + `cancelled. To rebook, visit ${process.env.BOOKING_URL} `
    + `or call us at ${process.env.OFFICE_PHONE}.`
  );

  // 4. Notify the provider / office
  await notifyProvider(appointment.providerId, {
    type: 'cancellation',
    patient: appointment.patientName,
    originalDate: appointment.datetime,
  });
}

WhatsApp Templates

WhatsApp requires pre-approved message templates for outbound notifications. Below are example templates you can submit for approval through the DIDfarm portal.

Reminder template with quick-reply buttons

WHATSAPP TEMPLATE — APPOINTMENT_REMINDER
Template name: appointment_reminder
Category:      UTILITY
Language:      en

Header:  Appointment Reminder
Body:    Your appointment with 1 is scheduled for 2
         at 3, located at 4.
         Please confirm or reschedule below.
Footer:  Sent via DIDfarm

Buttons:
  [Quick Reply] Confirm
  [Quick Reply] Reschedule

Follow-up template (no reply received)

WHATSAPP TEMPLATE — APPOINTMENT_FOLLOWUP
Template name: appointment_followup
Category:      UTILITY
Language:      en

Body:    Hi 1, we have not received your confirmation
         for your appointment on 2 at 3.
         Please reply to confirm or call us at 4.

Buttons:
  [Quick Reply] Confirm
  [Quick Reply] Cancel

Handling WhatsApp quick-reply button presses

When a recipient taps a quick-reply button, your webhook receives the button payload in the button_text field rather than in body:

WHATSAPP BUTTON REPLY PAYLOAD
{
  "id": "msg_wa_9c4d3e2f",
  "from": "+31612345678",
  "to": "+31201234567",
  "body": "",
  "button_text": "Confirm",
  "channel": "whatsapp",
  "received_at": "2026-04-05T09:15:44Z"
}
Template approval: WhatsApp templates typically take 24–48 hours to be approved. Submit your templates in advance and test them in the DIDfarm sandbox environment before going live.

Best Practices

Timing

  • Send two reminders — one 24 hours before and one 2 hours before the appointment. This gives recipients time to respond and still leaves a window for rebooking.
  • Respect quiet hours — avoid sending reminders before 08:00 or after 21:00 in the recipient's local timezone. If a reminder falls outside this window, shift it to the nearest allowed time.
  • Same-day bookings — for appointments booked less than 24 hours out, send a single reminder 2 hours before (or immediately after booking if less than 2 hours remain).

Message content

  • Keep it short — SMS messages should be under 160 characters when possible to avoid multi-segment charges. Include only the essential details: provider name, date, time, and location.
  • Include a clear CTA — always tell the recipient exactly how to respond. Use phrases like "Reply YES to confirm or NO to cancel."
  • Add the location — include the address or clinic name so the patient can navigate directly from the message.
  • Personalise — use the patient's first name and the provider's name for higher engagement.
  • Offer a reschedule option — cancellations are better than no-shows. Make it easy to reschedule rather than just cancel.

Technical considerations

  • Idempotency — tag each reminder with a unique reference (e.g. appointment_id + label) and check for duplicates before sending to avoid double-sending on queue retries.
  • Delivery status tracking — configure the delivery status webhook to monitor whether messages were delivered, failed, or are still pending.
  • Fallback strategy — if a WhatsApp message is undelivered after 60 seconds, automatically fall back to SMS.
  • Rate limits — DIDfarm allows up to 30 messages per second per number. If you have a large batch of reminders firing at the same time, stagger sends over a few seconds or use multiple numbers.
Pro tip: Track confirmation rates per reminder window (24h vs 2h). Most businesses find the 2-hour reminder drives the majority of confirmations, while the 24-hour reminder catches cancellations early enough to rebook the slot.

FAQ

What if the patient does not reply?

If no reply is received after the second reminder, treat the appointment as unconfirmed. You can optionally send a final WhatsApp follow-up (using the appointment_followup template) 1 hour before. Some businesses also place an automated phone call as a last resort.

Can I send reminders to landline numbers?

SMS reminders cannot be delivered to landlines. If the recipient's number is a landline, you should fall back to email or voice call reminders. DIDfarm's number lookup API can help you detect number types before sending.

How do I handle timezone differences?

Store all appointment times in UTC internally. When composing the message, convert to the patient's local timezone using their country code or an explicit timezone preference stored in your system. Always display the timezone abbreviation (e.g. "10:30 AM CET") to avoid ambiguity.

What about GDPR compliance?

Appointment reminders are generally covered under "legitimate interest" or "performance of a contract" under GDPR, as they relate to a service the patient has already booked. However, you should still inform patients during booking that they will receive SMS/WhatsApp reminders and provide an opt-out mechanism. Consult your legal advisor for your specific use case.

Can I include a link in the reminder?

Yes. You can include a short URL to a confirmation page, a calendar add link, or a map link. Keep URLs short to conserve SMS character space. For WhatsApp, you can use call-to-action buttons with URLs for a better user experience.

How many reminders should I send?

Two reminders (24h and 2h) is the industry standard. Sending more than three reminders per appointment risks being perceived as spam and may lead to opt-outs. If you add a third, make it a different channel (e.g. email 7 days before, SMS 24h and 2h before).

Start sending appointment reminders

Enable SMS on your DIDfarm numbers and reduce no-shows today.

Go to SMS settings →
© 2026 DIDfarm · didfarm.com
About Blog Partners Coverage API Docs Status Privacy Terms Cookies Help

We use essential cookies to make DIDfarm work. With your consent, we also use analytics cookies to improve our service. Cookie Policy