Best of Product Hunt

Developer Guide: Add Google Calendar Scheduling to Your App with Cal.com API + Google OAuth

Learn how to embed “scheduling with Google Calendar” into your product using Google OAuth, the Google Calendar API, and Cal.com’s developer-friendly scheduling API. This guide covers architecture, token handling, availability rules, booking flows, webhooks, and common pitfalls—so you can ship a reliable scheduling experience without endless calendar edge cases.

Share:

Use Google OAuth 2.0 to let users connect their calendars and securely store access/refresh tokens on your backend. Delegate availability, buffers, event types, and booking workflows to Cal.com, then keep your app in sync via webhooks for booking updates.

For most scheduling use cases, you’ll use `https://www.googleapis.com/auth/calendar.events` to create and update events. Optionally add `https://www.googleapis.com/auth/calendar.readonly` if you also need to read events, and prefer least-privilege scopes based on your requirements.

A common recommended approach is to let the scheduling layer compute availability because it handles working hours, buffers, minimum notice, and slot generation while checking conflicts. Computing availability yourself via Google’s `freebusy.query` gives more control but adds significant complexity.

Store `access_token`, `refresh_token`, an expiry timestamp, and a stable Google identifier like `sub` (don’t rely only on email). Encrypt tokens at rest, never expose refresh tokens to the browser, and handle refresh and revoked consent errors gracefully.

Many users have multiple calendars (work, personal, shared, or multiple accounts), and choosing avoids events landing in the wrong place. A primary booking calendar is where new events are created, while conflict calendars are used to prevent double-booking.

Double-booking can happen between availability fetch and booking creation or during concurrent requests. Mitigate it by re-checking conflicts at confirmation, using transaction/locking during booking creation, and applying idempotency keys on retries if supported.

Store all times in UTC internally and display times in the viewer’s time zone. Persist the selected time zone with the booking to make reschedules consistent and don’t trust client-provided time zones without server validation.

When creating events via the Google Calendar API, use `conferenceDataVersion=1` with `conferenceData.createRequest` to generate Google Meet links. Include stable identifiers (like booking ID and internal user ID) in the event’s description or `extendedProperties.private` to simplify reconciliation.

Use webhook events for booking created, rescheduled, and cancelled (and other status changes if your workflow supports them). Then update your database and notifications immediately instead of relying on expensive and fragile polling.

Use PKCE where appropriate, encrypt tokens at rest, and request least-privilege OAuth scopes. Add audit logging, handle revoked consent, and validate time zones and booking inputs on the server.

Developer Guide: Build “Scheduling With Google Calendar” Into Your App Using Cal.com API + Google OAuth

Embedding scheduling directly into your product sounds simple—until you run into real-world calendar complexity: OAuth token lifecycles, multiple calendars, conflicts, time zones, buffer rules, recurring events, cancellations, and webhooks.

This guide walks through a practical, production-oriented approach to “scheduling with Google Calendar” using **Google OAuth** + the **Google Calendar API**, while delegating booking logic (availability, buffers, event types, confirmations, rescheduling) to [PRODUCT_LINK]Cal.com[/PRODUCT_LINK].

You’ll leave with an implementation blueprint you can adapt to most stacks.

---

What you’re building (and why this approach works)

A solid scheduling integration typically needs these capabilities:

- **Sign in with Google** (OAuth 2.0) so users can connect their calendars.

- **Read busy times** to generate accurate availability.

- **Create/update/cancel events** when bookings happen.

- **Prevent double-booking** across multiple calendars.

- **Handle time zones**, buffers, and booking policies.

- **React to changes** (e.g., someone edits a meeting in Google Calendar).

You *can* implement all of this yourself with the Google Calendar API. But many teams prefer to:

- use Google Calendar primarily as the **source of truth for events**, and

- rely on a scheduling layer to manage **availability + booking workflows**.

That’s where [PRODUCT_LINK]the Cal.com API[/PRODUCT_LINK] fits in: it’s designed to be customizable and developer-friendly, so you can embed scheduling into your app without building every scheduling edge case from scratch.

---

Architecture overview

A common production setup looks like this:

1. **User connects Google Calendar** via OAuth 2.0 in your app.

2. Your backend stores tokens securely (access + refresh) and the user’s Google identity.

3. Your app uses Cal.com to:

- define event types (meeting templates)

- compute availability

- create bookings

4. On booking confirmation:

- Cal.com creates events and/or your system calls Google Calendar API (depending on your integration design)

5. Webhooks notify your system of booking updates (created/rescheduled/cancelled), so your app stays in sync.

**Key decision:**

- If you want to minimize calendar complexity, let the scheduling platform manage more of the booking workflow and calendar writes.

---

Step 1: Set up Google OAuth (the right way)

Create OAuth credentials

In Google Cloud Console:

- Configure the **OAuth consent screen**

- Create an **OAuth Client ID** (Web application)

- Add authorized redirect URIs (e.g., `https://yourapp.com/auth/google/callback`)

Choose scopes intentionally

For scheduling, you generally need:

- `https://www.googleapis.com/auth/calendar.events` (create/update events)

- Optionally `https://www.googleapis.com/auth/calendar.readonly` (read events)

If you only need to write events to a selected calendar and rely on free/busy elsewhere, review whether narrower scopes fit your UX and compliance requirements.

Token storage and refresh

Store:

- `access_token` (short-lived)

- `refresh_token` (long-lived)

- `expiry` timestamp

- Google `sub` (subject ID) or email (don’t rely solely on email; it can change)

**Best practice:** encrypt tokens at rest and never expose refresh tokens to the browser.

---

Step 2: Decide how you’ll compute availability

There are two common patterns:

Pattern A: Availability computed by scheduling layer (recommended for speed)

- You configure event types, working hours, buffers, minimum notice, etc.

- The scheduling layer checks calendar conflicts and produces available slots.

This is ideal when you want a reliable booking UX (and fewer edge cases to code).

Pattern B: Availability computed by your app using Google Calendar API

- You call Google’s `freebusy.query` to compute open slots

- You handle working hours, buffers, rounding rules, and slot generation

This offers maximum control but is significantly more work.

If you want the “batteries included” approach, lean on [PRODUCT_LINK]Cal.com’s scheduling infrastructure[/PRODUCT_LINK] for slot generation and booking rules.

---

Step 3: Implement “Connect Google Calendar” UX

A good connection flow includes:

1. User clicks **Connect Google Calendar**

2. You redirect to Google OAuth

3. On callback, you exchange the auth code for tokens

4. Ask the user which calendar(s) to use:

- a **primary booking calendar** (where new events are created)

- one or more **conflict calendars** (to prevent double-booking)

Why calendar selection matters

Many users have:

- separate work/personal calendars

- shared team calendars

- multiple Google accounts

Letting them choose avoids surprises (“Why are meetings landing in my personal calendar?”).

---

Step 4: Create event types (meeting templates) in your scheduling layer

Event types define the booking experience:

- duration (15/30/60 min)

- location (Google Meet, phone, in-person)

- availability rules (working hours)

- buffers (e.g., 10 minutes before/after)

- minimum notice (e.g., 2 hours)

- scheduling window (e.g., next 14 days)

- optional payments

Even if your app has its own “appointment types,” it’s useful to map them cleanly to scheduling event types so you can:

- update rules without redeploying your app

- keep booking logic consistent across platforms

---

Step 5: Build the booking flow (API-first)

A typical embedded scheduling flow:

1. **Fetch available times** for an event type within a date range

2. Render slots in your UI (with the user’s time zone)

3. User selects a slot and enters details

4. **Create booking**

5. Confirm success + show calendar invite details

Time zone handling tips

- Store everything in UTC internally

- Display in the viewer’s time zone

- Persist the selected time zone with the booking (useful for reschedules)

Prevent double-booking

Double-booking can happen when:

- two people book the same slot at nearly the same time

- calendars are updated between availability fetch and booking creation

Mitigations:

- rely on a booking transaction/lock at booking creation

- re-check conflicts at confirmation time

- use idempotency keys (if supported) to avoid duplicate creates on retries

---

Step 6: Create Google Calendar events reliably

When creating events via Google Calendar API:

- Prefer `conferenceDataVersion=1` + `conferenceData.createRequest` for Google Meet links

- Set `attendees` correctly and enable `sendUpdates` based on your UX

- Include stable identifiers in `description` or `extendedProperties.private`:

- booking ID

- your internal user ID

- event type ID

This makes reconciliation easier when webhooks arrive or users edit events manually.

**Pro tip:** If you support reschedules/cancellations, you need a stable mapping between booking records and Google event IDs.

---

Step 7: Use webhooks to keep your app in sync

Polling is expensive and fragile. Webhooks give you immediate updates.

You’ll typically want webhook events for:

- booking created

- booking rescheduled

- booking cancelled

- no-show / status changes (if your workflow supports it)

Then:

- update your database

- notify your users

- update CRM/support tooling

If you already use automation tooling, you can also route webhooks into workflow engines (e.g., n8n) for non-critical side effects.

---

Step 8: Security and compliance checklist

A quick checklist that prevents most production issues:

- **Use PKCE** where appropriate for OAuth flows

- **Encrypt tokens at rest** and limit access to token tables

- Implement **least-privilege scopes**

- Add **audit logging** for calendar connections and booking creation

- Handle **revoked consent** (Google returns errors; prompt reconnect)

- Don’t trust client time zones; validate on the server

---

Common pitfalls (and how to avoid them)

1) “Availability looks wrong”

Usually caused by:

- wrong time zone conversions

- not considering buffers

- not checking all conflict calendars

- ignoring recurring events

Fix: centralize time zone conversion and test with recurring + all-day events.

2) “Meet links aren’t created”

Often caused by:

- missing conference creation fields

- wrong OAuth scope

- using an API project without Google Meet enabled

Fix: verify scopes and use `conferenceDataVersion` properly.

3) “Bookings work, but updates don’t sync”

Usually:

- missing webhooks

- losing the mapping between booking ID and Google event ID

Fix: persist IDs and treat webhooks as first-class.

---

When it makes sense to use Cal.com in this stack

If your app needs:

- a robust booking layer (rules, buffers, availability)

- an API-first scheduling experience

- customization/white-labeling

- optional self-hosting

…then it’s worth exploring [PRODUCT_LINK]Cal.com for developers[/PRODUCT_LINK] as the scheduling component while Google Calendar remains the calendar provider.

---

Conclusion

Building “scheduling with Google Calendar” into your app is ultimately a systems problem: OAuth, tokens, time zones, event mapping, and synchronization. The most reliable implementations separate concerns:

- **Google OAuth + Calendar API** for identity and calendar access

- a dedicated scheduling layer for booking logic, availability, and workflow consistency

If you design around webhook-driven sync, careful token handling, and stable event identifiers, you’ll end up with a scheduling experience users trust—without drowning in calendar edge cases.

More from Cal.com