WhatsApp + Google Sheets: bookings logged, no chaos
Your inbox isn’t a booking system. But when patients DM “Can I come in tomorrow?” it’s easy to start juggling screenshots, half-finished notes, and a Google Sheet you update “later”. That’s how double bookings happen.
Clinic managers feel it first. A busy solo practitioner feels it too, just with fewer staff and the same WhatsApp booking automation headache. Even agencies helping practices run smoother end up stuck in the same back-and-forth.
This workflow turns WhatsApp conversations into clean rows in Google Sheets, sends reminders, and handles Stripe payment links. You’ll see how the automation behaves, what you need to connect, and where to customize it safely.
How This Automation Works
Here’s the complete workflow you’ll be setting up:
n8n Workflow Template: WhatsApp + Google Sheets: bookings logged, no chaos
flowchart LR
subgraph sg0["WhatsApp Flow"]
direction LR
n0@{ icon: "mdi:brain", form: "rounded", label: "Google Gemini Chat Model", pos: "b", h: 48 }
n1["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/whatsapp.svg' width='40' height='40' /></div><br/>WhatsApp Trigger"]
n2@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory", pos: "b", h: 48 }
n3@{ icon: "mdi:cog", form: "rounded", label: "Date & Time", pos: "b", h: 48 }
n4["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/whatsapp.svg' width='40' height='40' /></div><br/>Send message"]
n5@{ icon: "mdi:database", form: "rounded", label: "Get Patient List For User", pos: "b", h: 48 }
n6@{ icon: "mdi:database", form: "rounded", label: "Add Patient", pos: "b", h: 48 }
n7@{ icon: "mdi:database", form: "rounded", label: "Get User Appointments", pos: "b", h: 48 }
n8@{ icon: "mdi:database", form: "rounded", label: "Add Appointment", pos: "b", h: 48 }
n9@{ icon: "mdi:database", form: "rounded", label: "Get All Appointments", pos: "b", h: 48 }
n10@{ icon: "mdi:robot", form: "rounded", label: "AI Agent", pos: "b", h: 48 }
n11@{ icon: "mdi:database", form: "rounded", label: "Reschedule Appointment", pos: "b", h: 48 }
n12@{ icon: "mdi:database", form: "rounded", label: "Cancel Appointment", pos: "b", h: 48 }
n13@{ icon: "mdi:database", form: "rounded", label: "Config", pos: "b", h: 48 }
n13 -.-> n10
n10 --> n4
n6 -.-> n10
n3 -.-> n10
n2 -.-> n10
n8 -.-> n10
n1 --> n10
n12 -.-> n10
n9 -.-> n10
n7 -.-> n10
n11 -.-> n10
n0 -.-> n10
n5 -.-> n10
end
subgraph sg1["Google Sheets Flow"]
direction LR
n20["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/whatsapp.svg' width='40' height='40' /></div><br/>Send Cancellation Message (C.."]
n21["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/whatsapp.svg' width='40' height='40' /></div><br/>Send Cancellation Message (S.."]
n22@{ icon: "mdi:play-circle", form: "rounded", label: "Google Sheets Trigger1", pos: "b", h: 48 }
n23@{ icon: "mdi:database", form: "rounded", label: "Update Refund Status1", pos: "b", h: 48 }
n24["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Stripe Refund API1"]
n25@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check status 'Cancelled'1", pos: "b", h: 48 }
n26@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check Is Amount Paid1", pos: "b", h: 48 }
n24 --> n21
n24 --> n23
n26 --> n24
n26 --> n20
n22 --> n25
n25 --> n26
end
subgraph sg2["Schedule Flow"]
direction LR
n14@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger1", pos: "b", h: 48 }
n15@{ icon: "mdi:brain", form: "rounded", label: "Google Gemini Chat Model3", pos: "b", h: 48 }
n16@{ icon: "mdi:database", form: "rounded", label: "Get Appointment sheet1", pos: "b", h: 48 }
n17@{ icon: "mdi:cog", form: "rounded", label: "Date & Time2", pos: "b", h: 48 }
n18@{ icon: "mdi:cog", form: "rounded", label: "Send message in WhatsApp Bus..", pos: "b", h: 48 }
n19@{ icon: "mdi:robot", form: "rounded", label: "Appointment Reminder AI Agent1", pos: "b", h: 48 }
n17 -.-> n19
n14 --> n19
n16 -.-> n19
n15 -.-> n19
n18 -.-> n19
end
subgraph sg3["Stripe Flow"]
direction LR
n27["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/stripe.svg' width='40' height='40' /></div><br/>Stripe Trigger1"]
n28["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/whatsapp.svg' width='40' height='40' /></div><br/>Send Payment Confirmation1"]
n29["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Retrieve Payment Session1"]
n30@{ icon: "mdi:database", form: "rounded", label: "Mark Payment Paid1", pos: "b", h: 48 }
n27 --> n29
n29 --> n30
n29 --> n28
end
subgraph sg4["Look For New Appointment1 Flow"]
direction LR
n31@{ icon: "mdi:play-circle", form: "rounded", label: "Look For New Appointment1", pos: "b", h: 48 }
n32["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/whatsapp.svg' width='40' height='40' /></div><br/>Send Payment Link1"]
n33@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check Appointment Payment Mo..", pos: "b", h: 48 }
n34["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Generate Stripe Payment Link1"]
n31 --> n33
n34 --> n32
n33 --> n34
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n1,n22,n14,n27,n31 trigger
class n10,n19 ai
class n0,n15 aiModel
class n2 ai
class n25,n26,n33 decision
class n5,n6,n7,n8,n9,n11,n12,n13,n23,n16,n30 database
class n24,n29,n34 api
classDef customIcon fill:none,stroke:none
class n1,n4,n20,n21,n24,n27,n28,n29,n32,n34 customIcon
Why This Matters: WhatsApp Bookings Get Messy Fast
Appointment booking seems simple until you’re doing it all day, inside a chat app. You answer questions, check availability, confirm the slot, and then copy the details somewhere “official”. Then someone wants to reschedule, another person cancels, and now you’re hunting through messages to figure out what’s true. Meanwhile, the schedule is only accurate if you remembered to update it. Honestly, most clinics don’t have a scheduling problem. They have an “admin work hidden inside WhatsApp” problem.
The friction compounds. And it shows up in predictable places:
- It’s easy to confirm a slot in chat and forget to log it, which is how double bookings sneak in.
- Reschedules and cancellations get buried under new messages, so staff waste time scrolling for context.
- Payments turn into awkward follow-ups, especially when you need to send a link, check status, and confirm manually.
- Reminders are inconsistent, and missed reminders quietly turn into no-shows and lost revenue.
What You’ll Build: A WhatsApp Booking Assistant Powered by Google Sheets
This workflow gives you an AI booking assistant that lives inside WhatsApp. A patient messages your WhatsApp number, the assistant responds in a natural conversation, and it checks availability using Google Sheets as the “database” behind the scenes. When a booking is confirmed, the workflow writes the patient and appointment details into the correct sheet tab, so your schedule stays current without anyone retyping. If the patient wants to reschedule or cancel, they can do it in the same chat, and the workflow updates the appointment status immediately. On top of that, it can send Stripe payment links for prepaid appointments and trigger day-of reminders automatically.
The workflow starts with an incoming WhatsApp message, then the AI agent decides what the patient is trying to do (book, change, cancel, pay). Google Sheets is used to fetch patients, check existing appointments, and store new entries. Finally, WhatsApp sends confirmations, reminders, and payment updates so the whole lifecycle stays in one place.
What You’re Building
| What Gets Automated | What You’ll Achieve |
|---|---|
|
|
Expected Results
Say your clinic books about 10 appointments a day through WhatsApp. Manually, each booking often means checking the sheet (about 3 minutes), confirming in chat (about 3 minutes), logging details (about 3 minutes), and sometimes sending a payment link (about 3 minutes). That’s roughly 10–15 minutes per patient, or around 2 hours daily. With this workflow, staff mainly review exceptions: a quick glance at the sheet and the occasional edge-case message. Most days, the admin time drops to about 15 minutes.
Before You Start
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- WhatsApp Business (Cloud API) for receiving and sending patient messages.
- Google Sheets to store patients, appointments, and configuration.
- Stripe account + API access (get it from your Stripe Dashboard → Developers → API keys)
Skill level: Intermediate. You won’t code, but you will connect credentials and match your sheet columns exactly.
Want someone to build this for you? Talk to an automation expert (free 15-minute consultation).
Step by Step
A patient messages your WhatsApp number. The workflow starts at the WhatsApp incoming webhook, which captures the message and basic sender details so the assistant can keep context.
The AI agent figures out intent and gathers details. Using a chat model plus session memory, the assistant asks for what it needs (date, time, name) and routes the request down the right path (new booking vs. reschedule vs. cancel).
Google Sheets becomes the source of truth. The workflow loads working hours from a Config tab, checks Appointments for conflicts, and then writes the final booking (or updates/cancels an existing one). Patients get stored in a separate Patients tab so you don’t duplicate people.
Payments and reminders run automatically. If online payment is selected, the workflow creates a Stripe checkout link and sends it in WhatsApp. A schedule trigger runs daily to send reminders for same-day appointments, which helps cut no-shows without your team remembering to do it.
You can easily modify reminder timing to match your clinic hours based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the WhatsApp Trigger
Set up the incoming WhatsApp webhook that starts the appointment conversation flow.
- Add and open WhatsApp Incoming Hook and confirm it listens to updates with
messages. - Copy the webhook URL generated by WhatsApp Incoming Hook and configure it in your WhatsApp Business provider.
- Ensure the incoming payload includes
contacts[0].wa_idandmessages[0].text.bodybecause these are referenced later.
Credential Required: Connect your WhatsApp credentials for WhatsApp Incoming Hook.
contacts[0].wa_id, the conversation memory and reply routing will fail.
Step 2: Connect Google Sheets Data Sources
Link your Google Sheets for patients, appointments, and configuration. This workflow uses multiple Google Sheets tools and triggers.
- In Retrieve User Patients, Append Patient Record, Fetch User Appointments, Append Appointment Entry, Retrieve All Appointments, Modify Appointment Slot, Set Appointment Cancelled, Load Configuration, and Fetch Appointment Sheet, select the correct Document and Sheet for each.
- In Sheets Status Update Trigger, set Event to
rowUpdate, sheetName to[YOUR_ID], and documentId to[YOUR_ID], and keep columnsToWatch asstatus. - In New Appointment Watcher, set Event to
rowAdded, sheetName to[YOUR_ID], and documentId to[YOUR_ID]. - In Fetch Appointment Sheet, set sheetName to
[YOUR_ID]and documentId to[YOUR_ID].
Credential Required: Connect your Google Sheets credentials for all Google Sheets nodes, including googleSheetsTool, googleSheets, and googleSheetsTrigger nodes.
Step 3: Set Up the AI Orchestration for WhatsApp Conversations
Configure the AI agent to manage appointment workflows and send replies.
- Open Clinic AI Orchestrator and confirm Text is set to
={{ $json.messages[0].text.body }}. - Attach Gemini Chat Engine as the language model for Clinic AI Orchestrator.
- Attach Compact Session Memory as memory, with sessionKey set to
={{ $('WhatsApp Incoming Hook').item.json.contacts[0].wa_id }}and contextWindowLength set to6. - Attach tools to Clinic AI Orchestrator: Retrieve User Patients, Append Patient Record, Fetch User Appointments, Append Appointment Entry, Retrieve All Appointments, Modify Appointment Slot, Set Appointment Cancelled, Load Configuration, and Local Time Utility.
- In Dispatch WhatsApp Reply, set Text Body to
={{ $json.output }}and Recipient Phone Number to={{ $('WhatsApp Incoming Hook').item.json.contacts[0].wa_id }}.
Credential Required: Connect your Google Gemini credentials for Gemini Chat Engine.
Credential Required: Connect your WhatsApp credentials for Dispatch WhatsApp Reply.
Step 4: Configure Reminder Automation and Daily Schedule
Set up the daily reminder workflow that checks appointments and sends WhatsApp reminders.
- Open Daily Schedule Trigger and confirm it runs at
triggerAtHour: 8. - Configure Reminder AI Coordinator with Text set to
={{ $json['Readable date'] }}and attach Gemini Reminder Model as its language model. - Attach Fetch Appointment Sheet, Current Time Helper, and Send WhatsApp Reminder as tools to Reminder AI Coordinator.
- In Send WhatsApp Reminder, set Text Body to
Hello {{ $json['Name'] }}, this is a reminder for your appointment scheduled today at {{ $json['Time'] }}.and update Recipient Phone Number from[YOUR_PHONE]to a dynamic field if required.
Credential Required: Connect your Google Gemini credentials for Gemini Reminder Model.
Credential Required: Connect your WhatsApp credentials for Send WhatsApp Reminder.
Asia/Kolkata. Match this to your clinic’s timezone to ensure same-day reminders are accurate.
Step 5: Configure Payment and Checkout Handling
Set up Stripe payment links, payment confirmations, and automatic status updates in Google Sheets.
- In Evaluate Payment Method, keep the conditions checking
={{ $json.payment_method }}containsstripeor=Stripe. - In Create Stripe Checkout Link, verify the Stripe API parameters, including
metadata[appointmentId]set to={{ $('New Appointment Watcher').item.json.appointment_id }}andmetadata[whatsappNo]set to={{ $('New Appointment Watcher').item.json.whatsapp_number }}. - In Send Stripe Payment Link, set Text Body to
=This is the link to pay for your appointment Id {{ $json.metadata.appointmentId }} {{ $json.url }}and ensure the Recipient Phone Number is={{ $json.metadata.whatsappNo }}. - In Stripe Payment Trigger, select the event
payment_intent.succeeded. - In Retrieve Checkout Session, keep the Stripe endpoint
https://api.stripe.com/v1/checkout/sessionsand setpayment_intentto={{ $json.data.object.id }}. - Retrieve Checkout Session outputs to both Set Payment Paid and Send Payment Confirmation in parallel.
- In Set Payment Paid, confirm payment_status is
Paidand stripe_payment_intent is={{ $json.data[0].payment_intent }}.
Credential Required: Connect your Stripe credentials for Stripe Payment Trigger, Create Stripe Checkout Link, and Retrieve Checkout Session. If you are using token headers, replace Bearer [CONFIGURE_YOUR_TOKEN] with your live secret key.
Credential Required: Connect your WhatsApp credentials for Send Stripe Payment Link and Send Payment Confirmation.
appointmentId or whatsappNo to message the user.
Step 6: Configure Cancellation and Refund Logic
Monitor appointment status changes and send refunds or cancellation notices based on payment status.
- In Sheets Status Update Trigger, confirm the trigger watches the
statuscolumn and fires every minute. - In Verify Cancelled Status, ensure the condition checks
={{ $json.status.toLowerCase() }}equalscancelled. - In Check Payment Presence, keep the condition checking
={{ $('Sheets Status Update Trigger').item.json.stripe_payment_intent }}is not empty. - When payment exists, Check Payment Presence routes to Stripe Refund Request, which outputs to both Send Refund Cancel Notice and Update Refund Flag in parallel.
- When payment does not exist, Check Payment Presence routes to Send Cash Cancel Notice.
- In Stripe Refund Request, verify URL is
https://api.stripe.com/v1/refundsand payment_intent is={{ $('Sheets Status Update Trigger').item.json.stripe_payment_intent }}.
Credential Required: Connect your Stripe credentials for Stripe Refund Request and update the Authorization header from Bearer [CONFIGURE_YOUR_TOKEN] to your real key.
Credential Required: Connect your WhatsApp credentials for Send Refund Cancel Notice and Send Cash Cancel Notice.
Credential Required: Connect your Google Sheets credentials for Update Refund Flag.
{{ $('Sheets Status Update Trigger').item.json.appointment_id }}.
Step 7: Configure Output Messaging Nodes
Verify all WhatsApp messaging nodes send to the correct recipient and use expressions for dynamic values.
- In Dispatch WhatsApp Reply, confirm Text Body is
={{ $json.output }}and Recipient Phone Number is={{ $('WhatsApp Incoming Hook').item.json.contacts[0].wa_id }}. - In Send Payment Confirmation, keep Recipient Phone Number as
={{ $json.data[0].metadata.whatsappNo }}. - In Send Stripe Payment Link, keep Recipient Phone Number as
={{ $json.metadata.whatsappNo }}. - In Send Cash Cancel Notice and Send Refund Cancel Notice, confirm Recipient Phone Number is
={{ $('Sheets Status Update Trigger').item.json.whatsapp_number.toString() }}.
Credential Required: Connect your WhatsApp credentials for all WhatsApp output nodes (5+ nodes across the workflow).
Step 8: Test and Activate Your Workflow
Run end-to-end tests for booking, payment, reminders, and cancellations before activating.
- Click Execute Workflow and send a WhatsApp message to trigger WhatsApp Incoming Hook; verify Clinic AI Orchestrator responds via Dispatch WhatsApp Reply.
- Add a new appointment row to the sheet and confirm New Appointment Watcher triggers Evaluate Payment Method and then Create Stripe Checkout Link → Send Stripe Payment Link.
- Simulate a Stripe payment to trigger Stripe Payment Trigger, then confirm Retrieve Checkout Session runs and outputs to Set Payment Paid and Send Payment Confirmation in parallel.
- Change an appointment status to
Cancelledin the sheet to trigger Sheets Status Update Trigger, then confirm the correct branch fires: refund or cash cancellation notice. - Once tests pass, toggle the workflow to Active to run in production.
Troubleshooting Tips
- WhatsApp Cloud API credentials can expire or need specific permissions. If things break, check your Meta for Developers app settings and the Phone Number ID you entered first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Quick Answers
About 45 minutes if your WhatsApp, Sheets, and Stripe accounts are ready.
No. You’ll connect credentials and paste IDs (like your Google Sheet ID and WhatsApp Phone Number ID).
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in Stripe fees and your WhatsApp Cloud API messaging costs.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, and you should. You can change the working hours by editing the Config tab values the “Load Configuration” step reads, and you can adjust reminder timing in the “Daily Schedule Trigger”. Common tweaks include adding appointment types (long vs. short), requiring a deposit via Stripe for certain visits, and changing the AI Agent’s system message to match your clinic’s tone and language.
Usually it’s the Phone Number ID, an access token that expired, or missing permissions in your Meta for Developers app. Double-check the WhatsApp credential in n8n and confirm the number is connected to the correct business app. If messages arrive but replies fail, it can also be a template/format issue (for example, sending the wrong message type for your WhatsApp Cloud API settings).
On most n8n Cloud plans you can handle typical small-clinic volumes easily, and self-hosting removes execution caps (your server becomes the limit). In practice, this workflow is lightweight because it’s mostly messaging plus a few Google Sheets reads/writes per conversation. If you expect heavy traffic, the first bottlenecks are usually WhatsApp messaging limits and how fast your sheet queries run when the Appointments tab grows.
Often, yes, because this is not a simple two-step zap. You need conversation handling, branching paths (book/reschedule/cancel), memory, and multi-trigger logic for reminders and payments. n8n handles that kind of complexity without turning your bill into a surprise, and you can self-host if you want more control. Zapier or Make can still work if you only want “message in → row added” with no AI. If you’re unsure, Talk to an automation expert and we’ll sanity-check your requirements.
Once this is live, bookings stop living in someone’s head (or a scroll of messages). Your Google Sheet stays accurate, patients get faster replies, and your team gets a calmer day.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.