The Cost of No-Shows
Missed appointments cost service businesses billions of dollars every year. Whether you run a medical practice, a salon, a consulting firm, or a tutoring service, no-shows mean lost revenue and wasted time. The Healthcare Finance Management Association estimates that the average no-show rate across industries is 20-30%. A simple reminder sent 24 hours before the appointment can reduce that rate by 30-50%.
The most effective reminder systems use multiple channels. An email sent the day before serves as a detailed reminder with appointment information and a calendar link. A WhatsApp or SMS message sent one hour before serves as a final nudge. With One-Ping, you can automate this entire flow and reach your clients on the channels they actually check.
What you will build: An automated reminder system that sends a detailed email 24 hours before each appointment and a short WhatsApp or SMS reminder 1 hour before. Includes integration with Google Calendar, Calendly, and custom booking systems.
Step-by-Step Setup
Plan Your Reminder Schedule
Before building anything, decide when to send reminders and what each one should contain. The industry standard is a 24-hour reminder with full appointment details (date, time, location, preparation instructions) and a 1-hour reminder that is short and action-oriented ("Your appointment is in 1 hour at 123 Main St"). Some businesses also send a 1-week reminder for appointments booked far in advance. Start with the 24-hour and 1-hour pattern and add more intervals later based on your no-show data.
Choose Your Reminder Channels
Different channels serve different purposes in a reminder system. Email is best for the 24-hour reminder because it can include rich details, calendar attachments, and links to reschedule. WhatsApp is ideal for the 1-hour reminder because it has a 98% open rate and most people read WhatsApp messages within 3 minutes. SMS is the universal fallback since it works on every phone, even without internet. Use multi-channel delivery for the most effective reach.
Connect Your Calendar or Booking System
Your reminder system needs to know about upcoming appointments. If you use Google Calendar, you can query the Google Calendar API for events in the next 24 hours. If you use Calendly, set up a webhook that fires when a new booking is created. If you have a custom booking system, query your database for appointments with scheduled times approaching. The code examples below cover all three approaches.
Build the Reminder Logic
The reminder logic runs on a schedule (cron job or n8n scheduled trigger) and checks for appointments that need reminders. For each appointment, it calculates how much time is left and sends the appropriate reminder via One-Ping. The script should track which reminders have been sent to avoid duplicates. A simple approach is to store a "reminder_sent" flag for each appointment in your database.
Handle Confirmations and Cancellations
Make your reminders actionable by including links to confirm or cancel the appointment. For email, include confirmation and cancellation buttons that link to your booking system. For WhatsApp, you can use interactive message templates with reply buttons. Track confirmations in your system and send a follow-up if someone cancels so you can fill the slot.
Code Examples
Node.js: Cron-Based Reminder Script
const cron = require('node-cron'); // Check for appointments every 15 minutes cron.schedule('*/15 * * * *', async () => { const now = new Date(); const in24h = new Date(now.getTime() + 24 * 60 * 60 * 1000); const in1h = new Date(now.getTime() + 60 * 60 * 1000); // Get appointments needing 24h reminder const upcoming24h = await db.query(` SELECT * FROM appointments WHERE start_time BETWEEN $1 AND $2 AND reminder_24h_sent = false `, [in24h, new Date(in24h.getTime() + 15 * 60 * 1000)]); for (const apt of upcoming24h.rows) { // Send detailed email reminder await fetch('https://api.one-ping.com/send', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ONEPING_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ message: `Reminder: You have an appointment tomorrow at ${apt.start_time}`, channels: ['email'], metadata: { email: { to: apt.client_email, subject: `Appointment Reminder - ${apt.service_name}`, html: `<h2>Appointment Reminder</h2> <p><strong>Service:</strong> ${apt.service_name}</p> <p><strong>Date:</strong> ${apt.start_time}</p> <p><strong>Location:</strong> ${apt.location}</p> <p><a href="${apt.confirm_url}">Confirm</a> | <a href="${apt.cancel_url}">Cancel</a></p>` } } }) }); await db.query('UPDATE appointments SET reminder_24h_sent = true WHERE id = $1', [apt.id]); } // Get appointments needing 1h reminder const upcoming1h = await db.query(` SELECT * FROM appointments WHERE start_time BETWEEN $1 AND $2 AND reminder_1h_sent = false `, [in1h, new Date(in1h.getTime() + 15 * 60 * 1000)]); for (const apt of upcoming1h.rows) { // Send short WhatsApp/SMS reminder await fetch('https://api.one-ping.com/send', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ONEPING_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ message: `Reminder: Your ${apt.service_name} appointment is in 1 hour at ${apt.location}.`, channels: ['whatsapp', 'sms'], recipient: apt.client_phone }) }); await db.query('UPDATE appointments SET reminder_1h_sent = true WHERE id = $1', [apt.id]); } }); console.log('Appointment reminder service running...');
n8n Workflow for Appointment Reminders
For a no-code approach, build an n8n workflow that handles the entire reminder flow visually. The workflow structure is:
- Schedule Trigger -- runs every 15 minutes to check for upcoming appointments.
- Google Calendar node (or database query) -- fetches appointments within the reminder window.
- IF node -- checks if the appointment is 24 hours away or 1 hour away.
- HTTP Request node -- calls One-Ping API with the appropriate channel (email for 24h, WhatsApp/SMS for 1h).
- Update node -- marks the reminder as sent in your database or calendar.
This workflow can be imported from our n8n template library and customized with your specific calendar and message content.
Calendly Integration
If you use Calendly for booking, you can set up a webhook that fires when a new appointment is scheduled, and immediately schedule the reminders.
# Python: Calendly webhook - schedule reminders when booking is created from flask import Flask, request import requests, os from datetime import datetime, timedelta from apscheduler.schedulers.background import BackgroundScheduler app = Flask(__name__) scheduler = BackgroundScheduler() scheduler.start() def send_reminder(message, channels, recipient, metadata=None): payload = { 'message': message, 'channels': channels, 'recipient': recipient } if metadata: payload['metadata'] = metadata requests.post( 'https://api.one-ping.com/send', headers={'Authorization': f'Bearer {os.environ["ONEPING_API_KEY"]}'}, json=payload ) @app.route('/webhooks/calendly', methods=['POST']) def calendly_webhook(): data = request.get_json() event = data['payload'] start = datetime.fromisoformat(event['scheduled_event']['start_time']) name = event['name'] email = event['email'] # Schedule 24h reminder scheduler.add_job( send_reminder, 'date', run_date=start - timedelta(hours=24), args=[ f'Reminder: Your appointment is tomorrow at {start.strftime("%I:%M %p")}.', ['email'], email, {'email': {'subject': 'Appointment Reminder - Tomorrow', 'to': email}} ] ) # Schedule 1h reminder scheduler.add_job( send_reminder, 'date', run_date=start - timedelta(hours=1), args=[ f'Reminder: Your appointment starts in 1 hour!', ['whatsapp', 'sms'], email ] ) return '', 200
Choosing the Right Channel for Each Reminder
| Timing | Best Channels | Why |
|---|---|---|
| 1 week before | Gives time to reschedule. Include full details and calendar link. | |
| 24 hours before | Email + WhatsApp | Detailed email for reference, WhatsApp for visibility and confirmation. |
| 1 hour before | WhatsApp or SMS | Short, urgent nudge. High open rate ensures they see it in time. |
| 15 minutes before | SMS | Last resort for critical appointments. Keep the message very short. |
Pro tip: Track your confirmation and no-show rates by channel to find the optimal reminder timing and channel for your specific audience. Healthcare practices often see the best results with a 24-hour email plus a 2-hour SMS reminder.
Best Practices
- Include essential details only: Time, date, location, and how to cancel or reschedule. Do not overload the message with terms and conditions.
- Send from a recognizable name: Use your business name as the sender so clients immediately know what the message is about.
- Offer easy rescheduling: Include a link to reschedule in every reminder. A rescheduled appointment is better than a no-show.
- Respect time zones: Always send reminders based on the client's local time zone, not yours. Store time zones with each appointment record.
- Handle cancellations gracefully: When someone cancels via the reminder link, send a confirmation and optionally notify your team so they can fill the slot.
- Do not over-remind: Sending too many reminders can annoy clients and lead them to unsubscribe. Two reminders (24h + 1h) is the sweet spot for most businesses.