> ## Documentation Index
> Fetch the complete documentation index at: https://docs.servicebooked.ca/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect Cal.com

> Use Cal.com as your booking backbone — works with any calendar (Outlook, iCloud, Exchange, Google) and syncs bookings into ServiceBooked.

[Cal.com](https://cal.com) is an open-source scheduler that sits in front of your real calendar. It supports Google Calendar, Outlook, iCloud, Exchange, and others. If you're not on Google Calendar, Cal.com is the recommended path.

## How it works with ServiceBooked

Two integration points:

1. **The AI Receptionist links customers to your Cal.com booking page** when they want to schedule. Customers pick their slot in Cal.com's interface.
2. **A webhook from Cal.com tells ServiceBooked when a booking happens** — we update the customer's contact in your CRM, log the appointment, and add it to your inbox timeline.

This way, your real calendar (Outlook, iCloud, etc.) stays the source of truth; ServiceBooked stays informed; the AI Receptionist knows where to send people for booking.

## Set up

<Steps>
  <Step title="Get your Cal.com booking link">
    From your Cal.com dashboard, copy the public booking link for the event type you want customers to book (e.g., "30-min consultation"). Looks like `https://cal.com/your-name/30min`.
  </Step>

  <Step title="Paste it in ServiceBooked">
    Open **Settings → Integrations** in your ServiceBooked dashboard. Find the **Cal.com** section. Paste the booking link in the **Cal.com booking URL** field. Save.

    From this point on, when the AI Receptionist is in a conversation and the customer wants to book, the AI Receptionist will share your Cal.com link.
  </Step>

  <Step title="Set up the webhook (so bookings sync back)">
    Without the webhook, Cal.com can take bookings — but ServiceBooked won't know they happened. To wire that up:

    1. Still in **Settings → Integrations → Cal.com**, click **Generate webhook secret**. Copy the secret value (you'll only see it once).
    2. **Copy the webhook URL shown right above the secret** — it's unique to your account and looks like `https://app.servicebooked.ca/api/webhooks/calcom/<your-org-id>`. Use the exact value from that field (don't type it by hand).
    3. In your Cal.com dashboard, go to **Settings → Developer → Webhooks → Create**. Paste the URL, paste the secret, and subscribe to the events:
       * `BOOKING_CREATED`
       * `BOOKING_RESCHEDULED`
       * `BOOKING_CANCELLED`
    4. Save the webhook in Cal.com.
  </Step>

  <Step title="Test">
    Book a test appointment via your Cal.com link. Within seconds, you should see:

    * The contact land in your **Contacts** with the booker's info
    * The appointment appear in **Calendar** view
    * A new conversation in **Inbox** with the booking detail

    If nothing shows up, double-check the webhook secret matches and that the webhook URL is correct.
  </Step>
</Steps>

## Let customers self-book from your website

Everything above is about the **AI Receptionist booking for the customer** inside a conversation. If you'd rather also give visitors a **self-serve booking calendar right on your website** — a month grid with time slots they pick themselves, like the one on a "Schedule a call" page — use **Cal.com's inline embed**. It's Cal.com's own widget, and because you've already connected Cal.com to ServiceBooked, those self-booked appointments still flow into your CRM.

<Note>
  This embed comes from **Cal.com**, not from ServiceBooked's chat widget. The two can coexist: the chat bubble lets people book by talking to the AI, and the embedded calendar lets people pick a slot themselves — both hit the same Cal.com event type and both sync back to ServiceBooked.
</Note>

<Steps>
  <Step title="Grab the embed code from Cal.com">
    In your Cal.com dashboard, open the event type you want on your site (e.g. "30-min meeting"), click **Embed**, and choose **Inline Embed**. Cal.com generates a snippet — a small `<script>` plus a target `<div>` — pointing at that event's `calLink` (e.g. `your-name/30min`). Copy it.

    (Prefer a button that pops the calendar open instead of an always-visible grid? Choose **Floating pop-up** or **Element click** on the same Embed screen — same sync behaviour.)
  </Step>

  <Step title="Paste it into your website page">
    Drop the snippet onto the page where you want the calendar — a dedicated `/booking` page works well. In most site builders you add it via an "Embed code" / "Custom HTML" block; on a hand-coded site, paste it where you want the calendar to appear. Publish the page.
  </Step>

  <Step title="That's it — it already syncs">
    You **don't** set up a second webhook. A booking made through the embed is a booking on the same Cal.com event type, so it fires the **same webhook you configured above** — the contact, appointment, and a deal appear in ServiceBooked automatically, exactly like an AI-booked one.
  </Step>
</Steps>

**The embed respects your ServiceBooked availability.** If you've connected the **Cal.com API** (the availability push-sync described below), the slots the embed offers come from your Cal.com default schedule — which ServiceBooked keeps in step with your business hours, blackout dates, and holidays. So a visitor self-booking on your site can't pick a time you've marked yourself unavailable, the same as the AI.

### What about Google Calendar?

ServiceBooked's **Google Calendar** integration is built for the AI to book *for* the customer against your live availability — it doesn't produce an embeddable booking page. Google Calendar does have its own **Appointment schedules → "Book now" button** you can embed, but bookings made through Google's native page land only on your Google Calendar; they **won't create a contact or deal in ServiceBooked** (there's no webhook back to us the way Cal.com has). So for a self-serve booking calendar on your website that also feeds your CRM, **use Cal.com** (or [Calendly](/calendar/calendly), which works the same way). Keep Google Calendar connected for the AI-booking + real-time availability side.

## What the AI Receptionist says about booking

When a customer in a conversation wants to schedule, the AI Receptionist links your Cal.com page:

> Great — you can pick a time that works for you here: cal.com/your-name/30min. I'll see your booking come through and we'll lock it in.

If you don't want the AI Receptionist to link out (preferring to handle scheduling manually), turn off Cal.com integration and the AI Receptionist will instead capture the customer's preferred time and surface it as a task for you.

## Webhook secret — security

The webhook secret is what verifies that incoming requests to ServiceBooked are actually from Cal.com (and not someone pretending to be Cal.com to inject fake bookings). Keep it secret — don't paste it into a public chat or commit it to git.

You can rotate the secret any time from **Settings → Integrations → Cal.com → Rotate secret**. Doing so requires updating the secret in Cal.com's webhook settings too.

## Connect the Cal.com API (for availability sync)

Everything above uses your **booking link** — that's all the AI Receptionist needs to send people to Cal.com. But if you want ServiceBooked to **push your hours, blackout dates, and holidays into Cal.com automatically** (so a self-booker can never pick a time you're unavailable), you connect a second, separate thing: the **Cal.com API**. It needs two values — an **API key** and your **default event type id**.

<Note>
  This is a **separate connection** from the booking URL and the webhook above. The booking URL tells the AI where to send people; the API key + event type id let ServiceBooked write your availability *into* Cal.com. You can use one, the other, or both — but the availability sync only runs once the API is connected.
</Note>

<Steps>
  <Step title="Create a Cal.com API key">
    In Cal.com, go to **Settings → Developer → API keys → Add** (or **Create new**). Give it a name like "ServiceBooked", create it, and **copy the key** — Cal.com shows the full value only once. It looks like `cal_live_xxxxxxxxxxxxxxxx`.
  </Step>

  <Step title="Find your default event type id">
    Open the event type you want customers to book (e.g. "30 min meeting") in Cal.com. Look at the browser URL — it ends in a number:

    ```
    cal.com/event-types/1234567?tabName=setup
                         ^^^^^^^
    ```

    That number (`1234567` in this example) is your **event type id**. This is the event ServiceBooked treats as your default when it syncs availability.
  </Step>

  <Step title="Paste both into ServiceBooked">
    Open **Settings → Integrations → Cal.com** in your ServiceBooked dashboard, find the **Cal.com API (direct booking)** section, and paste in the **API key** and the **event type id**. Save.
  </Step>

  <Step title="Save your hours to run the first sync">
    The sync fires whenever you save availability. Go to **Settings → Business**, make sure your hours / blackout dates / holidays are set, and **Save**. ServiceBooked pushes them into your Cal.com default schedule.

    <Check>
      Back on the Integrations page you'll see a **"last synced"** timestamp. In Cal.com, your **default schedule** should now match your ServiceBooked hours — including split days (e.g. 9–10 AM and 12–5 PM with a midday break) rather than a flat 9–5.
    </Check>
  </Step>
</Steps>

<Warning>
  If the Integrations page shows a **sync error** (and Cal.com still shows the old/flat hours), the fix is almost always to **re-enter your API key** — disconnect and paste it again in Settings → Integrations → Cal.com, then re-save your hours. A stored key can occasionally become unreadable; re-entering it re-saves it cleanly. If it still fails, generate a fresh key in Cal.com and paste that.
</Warning>

## Keep Cal.com in sync with your hours, holidays, and blackout dates

Once the **Cal.com API** is connected (above), ServiceBooked automatically pushes your availability into your Cal.com **default schedule** every time you save it:

* **Business hours** (including split days like lunch breaks) become the schedule's weekly availability.
* **Blackout dates** and **detected public holidays** (next 12 months) become "unavailable" date overrides.

That means a customer booking directly on your Cal.com page can't pick a time you've marked yourself unavailable in ServiceBooked — the same rules the AI Receptionist already follows.

Two things to know:

* **ServiceBooked owns the default schedule once connected.** Availability edits made inside Cal.com are overwritten the next time you save hours, blackouts, or holiday settings in ServiceBooked. Make availability changes in ServiceBooked, not Cal.com.
* **Only the default schedule is synced.** If an event type is pinned to a different Cal.com schedule, it isn't touched.

The Integrations page shows when availability was last synced, and surfaces a warning if a sync fails so you know to re-save (or check your API key).

## Multiple event types

If you have multiple Cal.com event types (e.g., "30-min quote" and "1-hour install consultation"), pick the most common one as your default. The AI Receptionist will mention the others in conversation if relevant ("if you'd rather a longer call to walk through specifics, here's the 1-hour link…").

A first-class "AI picks the right event type based on conversation" feature is on the roadmap.

## Disconnecting

To disconnect: clear the booking URL field in **Settings → Integrations → Cal.com** and disable the webhook in your Cal.com dashboard. Existing bookings remain in ServiceBooked; future ones just stop syncing.

## Next

<CardGroup cols={2}>
  <Card title="Calendly setup" icon="calendar-check" href="/calendar/calendly">
    Same idea but for Calendly users.
  </Card>

  <Card title="ICS feed" icon="rss" href="/calendar/ics-feed">
    A read-only feed of your ServiceBooked appointments you can subscribe to from any calendar app.
  </Card>
</CardGroup>
