Blog · · 6 min read

How to fill cancelled appointments automatically with a waitlist in n8n and AI

Step-by-step guide to filling last-minute gaps in your calendar with n8n, Google Calendar, Google Sheets and AI whenever a client cancels.

When a client gives you fair notice that they can't make their appointment, you've already won half the battle against last-minute no-shows. The real problem comes next: you suddenly have an open slot tomorrow at 17:00 and a list of people who wanted an appointment this week, but messaging them one by one while running your business means that slot often goes unfilled.

In this guide you'll build an n8n workflow that detects when an appointment slot opens up, checks your Google Sheets waitlist for clients who match that service and time window, sends a short AI-written offer and books the first person who confirms into Google Calendar.

What you're going to build

A five-step workflow connected to your calendar and a "Waitlist" Google Sheet:

  1. Open-slot detection: when an appointment is cancelled (via your cancellation link or by marking/removing the event in Google Calendar), n8n captures the freed date, time and duration.
  2. Candidate matching: filters your "Waitlist" sheet for clients who requested that service (or one that fits the duration) and prefer that time of day.
  3. Small-batch AI outreach: a Basic LLM Chain writes a clear, natural message offering the exact time slot that just opened up.
  4. Conflict-free booking: when a client clicks to claim the slot, n8n checks Google Calendar first to make sure it's still free before creating the event.
  5. Graceful close: marks the row as booked and, if someone else clicks after the slot was taken, lets them know politely that it just filled and keeps them at the top of the list for the next opening.

What you need

  • An n8n instance (cloud or self-hosted for free on your computer).
  • Google Calendar, Google Sheets and Gmail (or WhatsApp Cloud API) connected in n8n.
  • An API key from OpenAI or another AI provider with a monthly spend limit set in your billing dashboard.
  • A Google Sheet called "Waitlist" with columns id, name, contact, service, duration_min, preferred_days (e.g. Mon,Tue,Wed,Thu,Fri), time_window (morning, afternoon, any), status (waiting, notified, booked, expired), last_notified_at and notes.

Step 1: feed the waitlist without extra admin work

A waitlist only works if joining it takes ten seconds. There are two easy ways to keep it full:

  1. From your booking form or front desk: whenever someone asks for a slot this week and you're fully booked, instead of saying "try again next Monday", add a row to your "Waitlist" sheet with their preferred days and time window.
  2. From your customer-service agent: if you run a WhatsApp AI agent or a website AI chatbot, give it a Google Sheets tool so that when no slots are open this week, it offers to add the client to the waitlist right away.

Step 2: detect the cancellation and filter matches

Your trigger can be the same Webhook that handles cancellations from your appointment reminders, or a Schedule Trigger every 15 minutes that looks for Google Calendar events tagged [CANCELLED].

Before messaging anyone, add two checks:

  1. Minimum lead time: make sure the open slot is at least 2 hours from now (texting someone 15 minutes before an appointment rarely works).
  2. True match filter: read rows from "Waitlist" with Google Sheets (Get Rows) and pass them through a Filter node that keeps only rows where:
  3. status = waiting.
  4. duration_min is less than or equal to the freed slot's length.
  5. time_window is any or matches the freed hour (morning before 14:00, afternoon after).
  6. last_notified_at is empty or not from today, so the same client never gets pinged twice in one afternoon if two appointments cancel back to back.

Add a Sort + Limit node to take the first 3 matching clients in signup order. Messaging 3 people at once is usually enough to fill the slot fast without leaving twenty people disappointed.

Step 3: draft a short, natural offer with AI

Connect a Basic LLM Chain (with a Structured Output Parser) to generate a brief message with the essentials: day, time, service and how to claim it. Use a prompt like this:

You work at [BUSINESS NAME]. An appointment slot just opened up and you're writing to a client on the waitlist. Data: name {{ $json.name }}, service {{ $json.service }}, open date and time {{ $json.slot_datetime }}. Rules: warm, direct, natural tone; max 55 words; state the exact day, time and service that opened up; tell them to click the confirmation link [CLAIM_LINK] or reply "I'LL TAKE IT" to claim it, noting it goes to the first person who confirms; never invent prices or terms. Return JSON only: {"subject": max 6 words, "message": text}.

After the AI node:

  • Send the message via Gmail (or WhatsApp if you have an open 24-hour window or an approved template).
  • Update the Google Sheets row: set status = notified and last_notified_at to the current timestamp.

Step 4: book the first person who confirms (no double-booking)

When one of the notified clients claims the slot (by clicking your confirmation link with slot_id and client_id parameters pointing to an n8n Webhook, or by replying):

  1. Check live availability: call Google Calendar (Get Many) for the exact start and end time of the slot.
  2. Add an IF node:
  3. If the slot is still free: create the Google Calendar event with the client's details, set their sheet row to booked, send their confirmation, and reset the other two notified rows back to waiting so they stay in line for future openings.
  4. If someone else claimed it a minute earlier: do not create an event. Reply automatically to let them know the slot was just taken, and reassure them that they keep their spot at the top of the waitlist for the next opening.

Checking the calendar right before creating the event prevents the classic mistake of giving the same slot to two people.

Step 5: expire stale rows weekly

A waitlist full of two-month-old requests quickly becomes useless. Add a weekly Schedule Trigger every Monday at 9:00 that flips rows older than 21 days from waiting to expired (or past the client's requested date), so you only contact people who are still looking for an appointment.

Test it in 5 minutes before going live

  1. Create a test appointment in Google Calendar for tomorrow at 17:00 and trigger its cancellation.
  2. Add two test rows to your "Waitlist" sheet using your own email: one requesting afternoon and one requesting morning.
  3. Run the workflow in n8n and verify that only the afternoon row gets the offer.
  4. Open the claim link twice in a row: the first click should create the calendar event and mark the row booked; the second should return the "just taken" message without creating a duplicate event.

Cost and best practices

  • Cost: generating 3 short waitlist messages per cancellation costs well under a cent on your AI provider's API.
  • Don't blast the whole list at once: notify 1 to 3 people per batch. If nobody claims the slot within 45 minutes, a follow-up check can notify the next 3 in line.
  • Route questions to a person: if a client replies asking "can we do 30 minutes later instead?", hand the conversation over to your team using the human handoff pattern in n8n.

Start with ready-to-import templates

If you want your booking and customer-service foundation ready in n8n without building from scratch, download the free WhatsApp agent or check out the full AgentKiosk pack: 8 tested n8n agents in English and Spanish — including Google Calendar bookings and WhatsApp customer service PRO — ready to import and connect to this waitlist workflow.