Google Calendar + Google Meet: bookings without clashes
Booking requests look simple until you’re the one untangling overlaps, replying to “is 2pm still free?”, and fixing the one appointment that somehow landed on a holiday. It’s not hard work. It’s constant work.
This Google Calendar booking automation hits service businesses first (clinics, salons, consultants), but agency teams building client sites and ops leads running internal scheduling feel it too. The payoff is straightforward: fewer clashes, fewer back-and-forth messages, and every confirmed slot automatically gets a real Google Meet link.
You’ll see how this workflow validates requests, checks availability (including holidays and breaks), and creates calendar events that invite attendees without you doing anything manually.
How This Automation Works
See how this solves the problem:
n8n Workflow Template: Google Calendar + Google Meet: bookings without clashes
flowchart LR
subgraph sg0["Flow 1"]
direction LR
n0["<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/webhook.dark.svg' width='40' height='40' /></div><br/>Booking Webhook"]
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/code.svg' width='40' height='40' /></div><br/>Validate Input"]
n2@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Validation Check", pos: "b", h: 48 }
n3["<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/code.svg' width='40' height='40' /></div><br/>Business Hours Check"]
n4@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Time Validation Check", pos: "b", h: 48 }
n5["<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/code.svg' width='40' height='40' /></div><br/>Check Availability"]
n6@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Availability Check", pos: "b", h: 48 }
n7@{ icon: "mdi:location-exit", form: "rounded", label: "Create Calendar Event", pos: "b", h: 48 }
n8["<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/code.svg' width='40' height='40' /></div><br/>Prepare Success Response"]
n9["<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/webhook.dark.svg' width='40' height='40' /></div><br/>Success Response"]
n10["<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/webhook.dark.svg' width='40' height='40' /></div><br/>Error Response"]
n11["<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/webhook.dark.svg' width='40' height='40' /></div><br/>Time Error Response"]
n12["<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/webhook.dark.svg' width='40' height='40' /></div><br/>Availability Error Response"]
n13["<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/code.svg' width='40' height='40' /></div><br/>Prepare Validation Error"]
n14["<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/code.svg' width='40' height='40' /></div><br/>Prepare Time Error"]
n15["<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/code.svg' width='40' height='40' /></div><br/>Prepare Availability Error"]
n16@{ icon: "mdi:location-exit", form: "rounded", label: "Check Calendar Availability ..", pos: "b", h: 48 }
n17@{ icon: "mdi:location-exit", form: "rounded", label: "Check Calendar Availability ..", pos: "b", h: 48 }
n21@{ icon: "mdi:cog", form: "rounded", label: "Wait", pos: "b", h: 48 }
n21 --> n1
n1 --> n2
n0 --> n21
n2 --> n3
n2 --> n13
n6 --> n7
n6 --> n15
n5 --> n6
n14 --> n11
n3 --> n4
n7 --> n8
n4 --> n17
n4 --> n14
n8 --> n9
n13 --> n10
n15 --> n12
n17 --> n16
n16 --> n5
end
subgraph sg1["Flow 2"]
direction LR
n18@{ icon: "mdi:location-exit", form: "rounded", label: "Check Calendar Availability", pos: "b", h: 48 }
n19["<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/code.svg' width='40' height='40' /></div><br/>Validate Date1"]
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/webhook.dark.svg' width='40' height='40' /></div><br/>Booking Timeslot webhook"]
n22@{ icon: "mdi:cog", form: "rounded", label: "Wait1", pos: "b", h: 48 }
n23@{ icon: "mdi:swap-vertical", form: "rounded", label: "ConfigTimeSlots", pos: "b", h: 48 }
n24@{ icon: "mdi:location-exit", form: "rounded", label: "Check Public Holiday Calendar", pos: "b", h: 48 }
n25["<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/code.svg' width='40' height='40' /></div><br/>Process Holiday Check Calendar"]
n26["<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/webhook.dark.svg' width='40' height='40' /></div><br/>Holiday Response Calendar"]
n22 --> n23
n19 --> n24
n23 --> n19
n20 --> n22
n18 --> n25
n24 --> n18
n25 --> n26
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 n2,n4,n6 decision
class n0,n9,n10,n11,n12,n20,n26 api
class n1,n3,n5,n8,n13,n14,n15,n19,n25 code
classDef customIcon fill:none,stroke:none
class n0,n1,n3,n5,n8,n9,n10,n11,n12,n13,n14,n15,n19,n20,n25,n26 customIcon
The Challenge: Booking requests that collide with reality
If you take appointments through a form, a DM, or a simple “pick a time” widget, you’ve probably learned the same lesson: calendars are messy. Someone picks a slot during lunch. Another person books the same hour from a different channel. A team member adds a personal block but forgets to mark it busy. Then you’re emailing, rescheduling, apologizing, and hoping it doesn’t happen twice in one day. It drains attention because you can’t just “do the work” until the schedule is reliable.
It adds up fast. Here’s where it breaks down.
- Availability checks happen in someone’s head, which is where mistakes love to hide.
- Customers don’t care about your rules (business hours, breaks, holidays), so your team ends up enforcing them manually.
- Double bookings create awkward conversations and “Can we move it?” follow-ups that waste about an hour you didn’t plan for.
- Even when a booking is valid, sending invites and meeting links still becomes another repetitive admin task.
The Fix: A smart booking API that creates clash-free Calendar events
This n8n workflow turns Google Calendar into a proper booking engine by putting a “brain” in front of event creation. A booking request hits a webhook endpoint (think: your website form’s submit button). The workflow validates the payload first, so missing names, broken emails, or weird date formats get rejected with clear error responses. Next, it applies your scheduling rules: weekdays only, business hours, timezone handling, and exclusions like lunch or dinner breaks. Then it checks for conflicts across calendars, including a public holiday calendar. If the slot is genuinely open, it creates the event in Google Calendar and lets Google handle attendee notifications and the Google Meet link automatically.
The same system also exposes an availability endpoint that returns a clean list of bookable time slots for a selected date. Your frontend can display “available vs booked” without guessing, and your customers stop picking impossible times.
What Changes: Before vs. After
| What This Eliminates | Impact You’ll See |
|---|---|
|
|
Real-World Impact
Say you offer 8 appointment slots per day and you currently handle requests through a form plus a couple of DMs. A typical manual cycle is about 10 minutes to read the request, check the calendar, confirm rules (hours, breaks, holidays), then send the invite. That’s roughly 80 minutes on a full day. With this workflow, the request is validated and booked automatically, and your “work” becomes quick exception handling (maybe 5 minutes total when someone submits a bad date or a full day).
Requirements
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Calendar to store bookings and availability.
- Google Meet to generate meeting links via Calendar events.
- Google Calendar API credentials (get them from Google Cloud Console).
Skill level: Intermediate. You’ll paste webhook URLs into your form and connect Google Calendar OAuth credentials inside n8n.
Need help implementing this? Talk to an automation expert (free 15-minute consultation).
The Workflow Flow
A booking request hits a webhook endpoint. Your site or app sends name, email, phone, date, time (and an optional source like “Website Form”). The workflow pauses briefly with a Wait node, then processes the payload.
Validation and business rules run first. Code nodes standardize formats (like YYYY-MM-DD and HH:MM), verify emails and phone numbers, and enforce your working schedule. Weekends get blocked. Break windows can be excluded. Timezones are handled so “2:30” actually means 2:30 in the timezone you operate in.
Conflict detection checks calendars before anything is created. Google Calendar lookups search your main booking calendar and a public holiday calendar. Another lookup checks what’s already on that day, then a conflict analyzer decides if the requested slot overlaps something that’s busy.
Successful bookings become real Calendar events with Meet links. If the slot passes every gate, n8n creates the event and returns a clean success response to your frontend. Your attendee gets the invite as usual, and the Google Meet link is included automatically.
You can easily modify available time slots to match different hours, industries, or appointment durations based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Webhook Trigger
Set up the two webhook entry points for bookings and timeslot availability checks.
- Open Incoming Booking Webhook and set Path to
make-booking, HTTP Method toPOST, and Response Mode toresponseNode. - Open Timeslot Webhook Trigger and set Path to
check-booking-date, HTTP Method toPOST, and Response Mode toresponseNode. - Confirm Delay Booking Intake and Delay Timeslot Intake are connected immediately after the respective webhooks, with Amount set to
2.2.
Step 2: Connect Google Calendar
Attach Google Calendar credentials for all calendar lookups and event creation.
- In Create Calendar Entry, select the calendar in Calendar and confirm Start is
{{ $('Business Hours Logic').all()[0].json.startDateTimeCal }}and End is{{ $('Business Hours Logic').all()[0].json.endDateTimeCal }}. - Set Summary to
Booking with {{ $('Incoming Booking Webhook').first().json.body.name }}and Attendees to{{ $('Incoming Booking Webhook').first().json.body.email }}. - Credential Required: Connect your googleCalendarOAuth2Api credentials in Create Calendar Entry, Holiday Calendar Lookup, Main Calendar Lookup, Daily Calendar Lookup, and Public Holiday Lookup.
- Verify Main Calendar Lookup, Holiday Calendar Lookup, Daily Calendar Lookup, and Public Holiday Lookup use Operation
getAllwith Limit10.
Step 3: Set Up Validation and Business Hours Logic
Validate incoming booking data and enforce business-hour rules before checking availability.
- In Validate Request Payload, keep the JavaScript validation that checks required fields, email format, phone format, and date/time formats.
- Configure Input Validation Gate to evaluate
{{ $json.success }}and route failed validation to Compose Validation Error. - In Business Hours Logic, keep the Malaysia timezone logic and confirm the output fields
startDateTimeCalandendDateTimeCalare used for calendar operations. - Ensure Time Window Gate checks
{{ $json.isValidTime }}and sends invalid requests to Compose Time Error.
Asia/Singapore. Keep the Malaysia UTC+8 offsets aligned with your calendar settings.Step 4: Configure Availability Checks and Booking Creation
Check for public holiday conflicts and existing calendar events before creating the booking.
- Confirm Time Window Gate routes to Main Calendar Lookup, then to Holiday Calendar Lookup, and into Conflict Analyzer as the execution flow specifies.
- In Conflict Analyzer, keep the references to Main Calendar Lookup and Time Window Gate to compare availability across holiday and main calendars.
- Set Slot Availability Gate to evaluate
{{ $json.isAvailable }}and route conflicts to Compose Availability Error. - Verify Create Calendar Entry feeds into Build Success Reply, which then feeds into Return Success Response with Response Body set to
{{ $json }}.
{{ $('Business Hours Logic').all()[0].json.startDateTime }} and {{ $('Business Hours Logic').all()[0].json.endDateTime }}.Step 5: Configure Timeslot Availability Endpoint
Provide a separate endpoint that returns available time slots for a requested date.
- In Configure Time Slots, set configuredAvailableTimeSlots to the provided array value, including display labels and availability flags.
- Ensure Validate Requested Date reads from Timeslot Webhook Trigger and enforces the
YYYY-MM-DDformat. - Confirm Public Holiday Lookup and Daily Calendar Lookup use the date boundaries
{{ $json.checkData.date + 'T00:00:00+08:00' }}and{{ $json.checkData.date + 'T23:59:59+08:00' }}. - Validate that Assemble Slot Availability outputs to Return Slots Response with Response Body set to
{{ $json }}.
11:30 and 17:30)—remove or adjust duplicates if your UI expects unique slots.Step 6: Test and Activate Your Workflow
Run manual tests to confirm successful booking and availability responses, then activate the workflow.
- Use Incoming Booking Webhook and send a POST request with valid
name,email,phone,date, andtimefields. - Confirm a successful execution ends at Return Success Response and the JSON includes
confirmationMessageandeventLink. - Test invalid payloads and confirm responses are returned by Return Validation Error, Return Time Error, or Return Availability Error.
- Test the availability endpoint using Timeslot Webhook Trigger and verify Return Slots Response includes
availableSlots. - When all tests pass, switch the workflow to Active for production use.
Watch Out For
- Google Calendar credentials can expire or need specific permissions. If things break, check the credential status in n8n (Credentials → your Google Calendar OAuth2 credential) 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.
Common Questions
About 15 minutes if your Google credentials are ready.
Yes, but someone should be comfortable connecting Google OAuth and testing webhook requests. No coding is required for basic use, though the workflow does include code nodes you can leave as-is.
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 Google Cloud costs (usually minimal for Calendar API at small volumes).
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.
Start with the “Configure Time Slots” node to change appointment times and durations, then adjust the “Business Hours Logic” rules for weekends, breaks, and timezone. If you don’t want holiday blocking, swap out the “Public Holiday Lookup” and “Holiday Calendar Lookup” checks (or point them to a different holiday calendar). Many teams also customize the “Build Success Reply” message so confirmations match their brand tone.
Usually it’s expired or misconfigured OAuth credentials in n8n. Reconnect the Google Calendar credential, then confirm the Google Calendar API is enabled in your Google Cloud project and that your OAuth consent screen is correctly configured. If it fails only sometimes, you may be hitting Google rate limits while testing rapidly, so slow down requests for a minute and retry.
On most setups, it can handle plenty of daily bookings for a small business, and scaling is mainly about n8n execution limits and Google API quotas. If you self-host, there’s no hard execution cap from n8n, but your server resources still matter. In practice, this workflow is lightweight because it’s a few calendar lookups plus one event creation per booking.
Often, yes, because this workflow isn’t just “create event when form submitted.” It validates inputs, enforces business-hour rules, checks holiday calendars, and runs multi-step conflict detection before it ever creates anything. Doing that in Zapier or Make is possible, but it usually turns into a long chain of paid steps and edge cases that still leak through. With n8n you also get the self-hosting route, which is handy if you expect higher volume. If you only need a simple 2-step automation, Zapier or Make can be quicker. Talk to an automation expert if you want a second opinion.
Once this is running, your calendar becomes the source of truth again, not a suggestion. The workflow handles the repetitive scheduling friction so you can focus on the actual appointment.
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.