Calendly + Google Sheets: bookings logged clean
Calendly is great at getting meetings on the calendar. The mess usually starts after that: “Who booked?”, “Did they cancel?”, “Where do we track it?”, and “Why is the sheet always out of date?”
This Calendly Sheets automation hits sales ops and client services teams hardest, but solo consultants feel it too. You will get a clean, searchable booking + cancellation history in Google Sheets, plus instant Slack notifications so nothing slips through.
Below you’ll see exactly how the workflow routes each Calendly event, what gets logged, and how to adapt it for your own follow-up process.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Calendly + Google Sheets: bookings logged clean
flowchart LR
subgraph sg0["Calendly Webhook Flow"]
direction LR
n0@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Route Event Type", pos: "b", h: 48 }
n1@{ icon: "mdi:swap-vertical", form: "rounded", label: "Transform Booking Data", pos: "b", h: 48 }
n2@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check Urgency", pos: "b", h: 48 }
n3@{ icon: "mdi:swap-vertical", form: "rounded", label: "Mark as Urgent", pos: "b", h: 48 }
n4@{ icon: "mdi:swap-vertical", form: "rounded", label: "Mark as Normal", 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/merge.svg' width='40' height='40' /></div><br/>Merge Booking Data"]
n6["<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/slack.svg' width='40' height='40' /></div><br/>Slack Booking Notification"]
n7@{ icon: "mdi:swap-vertical", form: "rounded", label: "Transform Cancellation Data", pos: "b", h: 48 }
n8@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Categorize Cancellation", pos: "b", h: 48 }
n9@{ icon: "mdi:swap-vertical", form: "rounded", label: "Label: Last Minute", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-vertical", form: "rounded", label: "Label: Standard", pos: "b", h: 48 }
n11@{ icon: "mdi:swap-vertical", form: "rounded", label: "Label: Past Event", pos: "b", h: 48 }
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/merge.svg' width='40' height='40' /></div><br/>Merge Cancellation Data"]
n13@{ icon: "mdi:database", form: "rounded", label: "Log to Cancellations Sheet", pos: "b", h: 48 }
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/slack.svg' width='40' height='40' /></div><br/>Slack Cancellation Alert"]
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/calendly.svg' width='40' height='40' /></div><br/>Calendly Webhook Trigger1"]
n16@{ icon: "mdi:database", form: "rounded", label: "Log to Bookings Sheet1", pos: "b", h: 48 }
n2 --> n3
n2 --> n4
n4 --> n5
n3 --> n5
n10 --> n12
n0 --> n1
n0 --> n7
n9 --> n12
n5 --> n16
n16 --> n6
n1 --> n2
n8 --> n9
n8 --> n10
n8 --> n11
n12 --> n13
n15 --> n0
n13 --> n14
n7 --> n8
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 n15 trigger
class n0,n2,n8 decision
class n13,n16 database
classDef customIcon fill:none,stroke:none
class n5,n6,n12,n14,n15 customIcon
The Problem: Bookings Change, but Your Tracking Doesn’t
Bookings are “easy” until you try to manage them like a business process. New invites arrive, cancellations happen at the worst time, and suddenly your team is working from three sources of truth: Calendly, someone’s inbox, and a half-maintained spreadsheet. It’s not just time lost to copy-paste. It’s the mental load of constantly checking what changed, plus the awkward follow-up when someone assumes a meeting is still on. Over a week, that turns into missed opportunities, messy reporting, and follow-ups that land too late.
It adds up fast. Here’s where it usually breaks down.
- Bookings get logged sometimes, which means your “pipeline” sheet becomes a guess.
- Last-minute cancellations are easy to miss, so the slot goes unfilled and no one reaches out.
- Details like meeting links, time zones, and reschedule URLs live in Calendly, not where your team works.
- Reporting becomes a manual chore, because cancellations and bookings are mixed together or not tracked at all.
The Solution: Auto-log Every Booking and Cancellation
This workflow turns Calendly events into a reliable back-office system. When someone books or cancels in Calendly, n8n catches the webhook instantly and routes it down the right path. For new bookings, it extracts the invitee and event details, formats dates into something humans can read, and calculates useful fields like “days until event” and “urgent” status for near-term meetings. For cancellations, it captures the reason, who canceled, and how close it was to the scheduled time, then labels it as last-minute, standard, or past-event. Finally, it logs everything into two clean Google Sheets tabs (Bookings and Cancellations) and posts a clear Slack message so your team can act right away.
The workflow starts with a Calendly webhook for invitee.created and invitee.canceled. It then enriches each event with computed fields (urgency for bookings, priority for cancellations). Google Sheets becomes your history, and Slack becomes your real-time alert channel, so you’re not chasing updates.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say your team handles about 20 Calendly events a week (bookings and cancellations combined). Manually logging each one to Google Sheets, plus dropping a message in Slack, can easily take 5 minutes per event, so you’re spending around 2 hours weekly just doing admin. With this automation, the “work” is basically zero after setup: Calendly triggers the flow instantly, Sheets updates in the background, and Slack posts right away. You still review exceptions, but you stop doing repetitive logging.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Calendly to send booking and cancellation events
- Google Sheets to store Bookings and Cancellations tabs
- Slack to alert your team in real time
- Calendly OAuth2 or Personal Access Token (get it from developer.calendly.com)
Skill level: Beginner. You’ll connect accounts, paste a Sheet ID, and pick Slack channels.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
A Calendly event kicks it off. The workflow listens for invitee.created (new booking) and invitee.canceled (cancellation) through a Calendly webhook trigger.
The event gets routed and cleaned up. A routing step splits bookings from cancellations, then “mapping” steps extract the useful details and format them for humans (names, time zone, start/end time, meeting link, reschedule/cancel URLs).
Urgency and priority get calculated. For bookings, an IF check flags same-day and next-day appointments as urgent. For cancellations, another routing step categorizes the cancellation based on how close it was to the event time, which helps your team respond appropriately.
Sheets and Slack stay in sync. Bookings append to the Bookings tab, cancellations append to the Cancellations tab, and Slack posts a message that matches the context so nobody has to interpret raw data.
You can easily modify urgency rules to match your sales cycle or service policy based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Calendly Trigger
This workflow starts when Calendly sends booking or cancellation events into n8n.
- Add the Calendly Event Listener node as your trigger.
- Set Scope to
organization. - Set Authentication to
oAuth2. - Under Events, include
invitee.createdandinvitee.canceled. - Credential Required: Connect your calendlyOAuth2Api credentials.
Step 2: Connect Google Sheets for Booking and Cancellation Logs
The workflow appends structured booking and cancellation data to two different sheets.
- Open Append to Bookings Sheet and set Operation to
append. - Set Document to your spreadsheet (replace the placeholder
[YOUR_ID]). - Set Sheet Name to
Bookings. - Credential Required: Connect your googleSheetsOAuth2Api credentials.
- Open Append to Cancellations Sheet and set Operation to
append. - Set Document to the same spreadsheet (replace
[YOUR_ID]), and set Sheet Name toCancellations. - Credential Required: Connect your googleSheetsOAuth2Api credentials.
[YOUR_ID] in Append to Bookings Sheet or Append to Cancellations Sheet, data will not be written. Always select your actual spreadsheet.Step 3: Set Up Booking Processing and Urgency Logic
This branch maps booking data, evaluates urgency, and tags the record before logging it.
- In Route Event Category, confirm the booking rule checks
={{ $json.event }}equalsinvitee.created. - In Map Booking Details, set key fields like event_id to
={{ $json.payload.uri.split('/').pop() }}and invitee_email to={{ $json.payload.email }}. - Ensure formatted_date uses
={{ new Date($json.payload.scheduled_event.start_time).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', timeZone: $json.payload.timezone }) }}. - Ensure formatted_time uses
={{ new Date($json.payload.scheduled_event.start_time).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', timeZone: $json.payload.timezone }) }}. - In Assess Booking Urgency, keep the OR condition where
={{ $json.is_same_day }}equalstrueor={{ $json.days_until_event }}is less than or equal to1. - In Flag Urgent Booking, verify urgency_label is
🚨 URGENTand is_urgent istrue. - In Flag Standard Booking, verify urgency_label is
📅 Scheduledand is_urgent isfalse. - Confirm Flag Urgent Booking and Flag Standard Booking both connect into Combine Booking Streams.
Step 4: Configure Cancellation Routing and Slack Notifications
This branch maps cancellations, categorizes them, logs them to Sheets, and posts messages to Slack.
- In Route Event Category, confirm the cancellation rule checks
={{ $json.event }}equalsinvitee.canceled. - In Map Cancellation Details, map fields such as cancellation_reason to
={{ $json.payload.cancellation?.reason || 'No reason provided' }}and is_last_minute to={{ Math.round((new Date($json.payload.scheduled_event.start_time) - new Date()) / (1000 * 60 * 60)) < 24 && new Date($json.payload.scheduled_event.start_time) > new Date() }}. - In Route Cancellation Type, keep the boolean checks for
={{ $json.is_last_minute }}and={{ $json.was_upcoming }}. - Verify the three tagging nodes set labels correctly: Tag Last-Minute Cancel uses
🚨 LAST MINUTE, Tag Standard Cancel uses❌ Cancelled, and Tag Past Event Cancel uses📋 Past Event Cancelled. - Confirm the three tagging nodes connect into Combine Cancellation Paths, which then connects to Append to Cancellations Sheet.
- In Post Booking to Slack, set Text to the existing Slack template:
={{ $json.urgency_label }} *New Booking Confirmed* ...and choose your target channel. - Credential Required: Connect your slackApi credentials in Post Booking to Slack.
- In Post Cancellation to Slack, set Text to
={{ $json.cancel_label }} *Meeting Cancelled* ...and choose your target channel. - Credential Required: Connect your slackApi credentials in Post Cancellation to Slack.
is_last_minute and was_upcoming.Step 5: Test and Activate Your Workflow
Validate the full execution flow from trigger to Sheets and Slack before enabling production use.
- Click Execute Workflow and trigger a test booking and cancellation in Calendly.
- Confirm Route Event Category sends bookings to Map Booking Details and cancellations to Map Cancellation Details.
- Verify a new row is appended in Append to Bookings Sheet for bookings and in Append to Cancellations Sheet for cancellations.
- Check Slack for messages from Post Booking to Slack and Post Cancellation to Slack with the correct labels.
- When satisfied, toggle the workflow to Active for ongoing automation.
Common Gotchas
- Calendly credentials can expire or need specific permissions. If things break, check your Calendly developer app or Personal Access Token settings 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.
- Slack apps often fail quietly when scopes are missing. If notifications stop, verify the bot token scopes and that the app is installed in the right workspace/channel.
Frequently Asked Questions
About 30 minutes if your Calendly, Slack, and Google accounts are ready.
No coding required. You’ll authenticate the apps, set your Google Sheet IDs, and choose where Slack messages should go.
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 Slack and Google Sheets (usually $0), plus any Calendly plan requirements for webhooks in your account.
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 it’s one of the best tweaks to make. Update the “Assess Booking Urgency” IF logic so “urgent” matches your reality (for example, only same-day, or anything within two days). You can also change what Slack posts by editing the “Post Booking to Slack” message template, then add extra fields from the “Map Booking Details” step such as custom form questions or UTM tags. Many teams also add an email notification after urgent alerts for redundancy.
Usually it’s expired OAuth permissions or a token that was regenerated. Reconnect your Calendly credentials in n8n, then confirm the webhook is still registered for invitee.created and invitee.canceled in your Calendly developer settings. If it works for a while and then stops, check if the Calendly account changed owners, permissions, or plan features related to webhooks.
A lot. On n8n Cloud, the limit is mainly your monthly executions, and each booking or cancellation is typically one execution. If you self-host, there’s no execution cap, so it mostly depends on your server size and Google Sheets API limits; for most small teams, it will run comfortably without special tuning.
Often, yes, especially once you want branching logic. This workflow doesn’t just “send data to a sheet”; it routes bookings vs. cancellations, labels urgency, and categorizes cancellation timing, which is where simpler tools get messy or expensive. n8n also gives you the self-hosting option, which is a big deal if volume grows. Zapier or Make can still be fine for a basic two-step log, but you’ll feel the limits when you add priority rules and richer messages. If you want a quick recommendation for your setup, Talk to an automation expert and you’ll get an honest answer.
Once this is live, your booking history just exists, clean and trustworthy. The workflow handles the repetitive tracking so your team can focus on showing up and following up.
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.