# Keep Calendly bookings in sync with Airtable and Slack

Give sales one meeting record per Calendly invitee. Link the Google Calendar event when the invitee and time match, record exceptions in Airtable, and send an internal Slack alert for each new meeting record.

**Category** Revenue Operations  
**Tools** n8n, Calendly, Google Calendar, Airtable, Slack (optional)  
**Trigger** Calendly `invitee.created`  
**Package** [Workflow JSON](calendly-booking-sync.n8n.json) · [Test payloads](test-payloads.json) · [Validation report](validation-report.txt)

## How it works

1. Wait briefly for Calendly’s Google Calendar sync, then find the event by the exact invitee email and start and end times. Record `missing` or `ambiguous` when the workflow cannot select one event.
2. Optionally add one internal attendee to a matched event. The update checks the event version and suppresses calendar update emails.
3. Upsert the Airtable contact by email and the meeting by Calendly invitee URI. If a new meeting row is created and a channel is configured, post its status in Slack.

## How to use

1. Import the workflow and run **Run with sample data**. **Match calendar event** should show `matched` and a fictional calendar event ID.
2. Connect Calendly OAuth on **Receive event**. The trigger is scoped to the connected user. Use a Calendly account that can register webhooks and a Google calendar that already receives its bookings. Configure the Google Calendar OAuth account on the calendar HTTP nodes.
3. Create an Airtable base with these tables. Use single-line text for key fields and include time on both date fields.

   | Table | Fields |
   | --- | --- |
   | Contacts | `Email` (text), `Name` (text) |
   | Meetings | `Booking ID` (text), `Contact` (link to Contacts), `Event` (text), `Starts At` and `Ends At` (date and time), `Calendar Event ID` (text), `Calendar Status` (text) |

4. Create an Airtable personal access token with record read and write access to that base. Select a **Header Auth** credential using `Authorization: Bearer <token>` on both Airtable nodes.
5. In **Setup**, enter `calendarId`, `airtableBaseId`, `contactsTableId`, and `meetingsTableId`. Start with the 30-second wait and leave `addInternalAttendeeEmail` blank. To enable Slack, enter `slackChannelId` and attach a separate **Header Auth** credential with a bot token that has `chat:write` and access to the channel.
6. Set `dryRun` to `false` in staging. Create a test booking and check Calendar, Airtable, and Slack before enabling the production trigger.

## Test and operate

| Scenario | Expected result |
| --- | --- |
| One exact calendar match | The meeting row stores the event ID and `matched` status. |
| Calendar sync is late or has two matching events | The meeting still logs with `missing` or `ambiguous`. Review it in Airtable. |
| Same invitee URI arrives again | The existing row updates. Slack is reserved for newly created rows. |
| Slack fails after the meeting is recorded | The n8n execution shows the failure. Check the channel and notify sales manually if needed. |

Use an Airtable view for unmatched meetings. This workflow tracks newly created bookings. Add a cancellation workflow if the team needs to reconcile canceled or superseded rows.

[Community source by Muhammad Bin Zohaib](https://n8n.io/workflows/19719-sync-calendly-bookings-with-google-calendar-airtable-crm-and-slack/) · [Airtable record upserts](https://airtable.com/developers/web/api/update-multiple-records)
