Developer Guide: Build a “Book a Meeting” Flow in Slack with Outlook Calendar and the Cal.com API
Learn how to implement a Slack “Book a meeting” experience that checks real availability in Outlook, generates time options, and confirms bookings via the Cal.com API. This guide covers architecture, OAuth considerations, Slack UX patterns, and practical request/response examples you can adapt to your own app.
Create a Slack app with a slash command or shortcut that opens a Block Kit modal to collect invitee, duration, and title. Your backend verifies Slack signatures, fetches Outlook free/busy via Microsoft Graph, suggests time slots, and then confirms the booking through the Cal.com API.
You’ll typically need a Slack app (commands, modals, interactive components), a backend service to handle signed Slack requests and OAuth, Microsoft Graph to read Outlook availability, and the Cal.com API to apply scheduling rules and create the booking.
The guide recommends using Microsoft Graph’s scheduling endpoint (GetSchedule) to retrieve free/busy blocks because it’s the cleanest way to generate candidate slots. An alternative is CalendarView, but it requires fetching events and computing gaps yourself.
A common pattern is a second Slack modal that contains a static select menu listing 3–8 suggested time slots. Each option can encode the slot start time (ISO string) plus duration, and the UI should clearly show the user’s time zone.
Cal.com acts as the scheduling layer that centralizes rules like buffers, booking limits, meeting types, and host routing. Your backend calls the Cal.com booking endpoint to validate the slot, create the booking, and return confirmation details like calendar invites and conferencing links.
You’ll need Slack app scopes such as `commands`, `chat:write`, and `users:read`, plus a Microsoft Entra (Azure) app registration with a redirect URI and calendar permissions like `Calendars.Read` or `Calendars.ReadWrite`. You also need Cal.com API access via an API key or OAuth, depending on your setup.
Common approaches include using the Slack profile email, adding an explicit “Connect Outlook” step to store Microsoft refresh tokens, or using a service account that can book on behalf of others. The guide notes that for internal tooling, an explicit connect step is often the best trade-off.
Slack can retry interactive requests when your server is slow, so idempotency is important. Use an idempotency key such as the Slack `trigger_id` plus the selected slot to ensure you don’t create duplicate bookings.
You must verify Slack requests using the timestamp and HMAC signature (`X-Slack-Request-Timestamp` and `X-Slack-Signature`). The guide also recommends encrypting OAuth tokens at rest, using least-privilege Graph scopes, rate limiting, and carefully testing time zone/DST handling.
Developer Guide: Build a “Book a Meeting” Flow in Slack with Outlook Calendar and the Cal.com API
Scheduling is one of those workflows that *should* be simple—but in practice it’s a tangle of back-and-forth messages, time zones, and double-booking risk. If your team lives in Slack and your organization runs on Microsoft 365, the ideal experience is: **type a command, pick a time, done**.
This guide walks through a practical approach to building a **“Book a Meeting” in Slack** feature that uses **Outlook Calendar availability** and books the meeting through the **Cal.com API**.
We’ll focus on developer concerns: architecture, OAuth, Slack UX patterns, and how to wire up booking creation end-to-end.
---
What you’re building (user experience)
A lightweight Slack flow:
1. A user types `/book` (or clicks a shortcut).
2. Slack opens a modal asking **who**, **how long**, and **what it’s about**.
3. Your backend fetches availability (Outlook free/busy via Microsoft Graph, plus scheduling rules).
4. Slack shows 3–8 suggested time slots.
5. User selects a slot → your backend confirms the booking via API.
6. Slack posts confirmation with calendar invite + meeting link.
---
Recommended architecture
**Components**:
- **Slack App**
- Slash command or message shortcut
- Modals (Block Kit)
- Interactive components (buttons/select menus)
- **Backend service** (Node/TS, Python, etc.)
- Handles Slack requests (signed)
- Manages OAuth tokens (Microsoft)
- Calls scheduling/booking APIs
- **Microsoft Graph**
- Reads Outlook calendar availability
- **Scheduling layer (Cal.com API)**
- Applies booking rules, buffers, meeting types, routing/hosts
- Creates the actual booking and returns confirmation details
If you’re new to Cal’s model, start with the concept of “event types,” booking rules, and API-first scheduling from [PRODUCT_LINK]the Cal.com scheduling infrastructure[/PRODUCT_LINK].
---
Prerequisites
Before coding, you’ll want:
1. **Slack App** configured with:
- Interactivity enabled
- Slash command (e.g., `/book`) or a global shortcut
- OAuth scopes typically including: `commands`, `chat:write`, `users:read` (plus anything else you need)
2. **Microsoft Entra (Azure) App Registration** for Graph:
- OAuth redirect URI to your backend
- Permissions for calendar access (commonly `Calendars.Read` or `Calendars.ReadWrite` depending on your design)
3. **Cal.com API access**
- An API key or OAuth approach depending on your setup
- An event type configured that represents the meeting you’re booking
For API details and models, reference [PRODUCT_LINK]Cal.com’s API-first scheduling platform[/PRODUCT_LINK].
---
Step 1: Design the Slack interaction (Block Kit)
Option A: Slash command `/book`
- Pros: fast, familiar.
- Cons: less discoverable than shortcuts.
Option B: Shortcut “Book a meeting”
- Pros: more discoverable, can be context-aware.
- Cons: more UI plumbing.
A common pattern is:
1. User triggers the command/shortcut
2. You open a modal:
**Modal fields** (minimum viable):
- Invitee (Slack user select)
- Duration (15/30/45/60)
- Title/agenda
- Time zone (optional; default to user profile)
Then, on submission:
- Generate availability options
- Show a second modal with selectable time slots
---
Step 2: Verify Slack requests (don’t skip this)
Slack signs requests with a timestamp and HMAC signature. Verify:
- `X-Slack-Request-Timestamp` is recent
- `X-Slack-Signature` matches your signing secret
This is non-negotiable—interactive endpoints are a popular target.
---
Step 3: Get Outlook availability (Microsoft Graph)
You have two common approaches:
Approach 1: GetSchedule (free/busy)
Use Microsoft Graph’s scheduling endpoints to retrieve free/busy blocks for one or more users. This is typically the cleanest way to generate time slot candidates.
You’ll:
- Use OAuth to obtain an access token for the user (or service account with appropriate permissions)
- Query for availability in a time window (e.g., next 5 business days)
**Key implementation considerations**:
- Time zones: normalize internally (e.g., store and compute in UTC)
- Working hours: fetch from mailbox settings or define in your app
- Recurring events: free/busy already accounts for these
Approach 2: CalendarView (events)
Fetch events and compute gaps yourself. More control, more code.
In most “book a meeting” scenarios, **GetSchedule** + a slot generator is enough.
---
Step 4: Generate candidate time slots
Once you have busy blocks, generate slots:
- Define search window: e.g., `now + 2 hours` through `now + 5 days`
- Business hours: e.g., 09:00–17:00
- Slot size: match duration
- Rules:
- Round to nearest 15 minutes
- Exclude lunch hours or focus time
- Add buffers (e.g., 10 minutes before/after)
Return a short list of best options (3–8) rather than flooding the user.
**Tip:** If you want these rules centralized (buffers, limits, capacity, host selection), keep them in your scheduling layer so Slack stays a thin client. That’s a common reason teams choose [PRODUCT_LINK]the Cal.com API for custom scheduling[/PRODUCT_LINK].
---
Step 5: Present time options in Slack
Use a second modal with:
- A static select menu for “Available times”
- Each option value encodes the slot start time (ISO string) + duration
Example option label:
- `Tue, Jan 9 — 2:30 PM (30 min)`
Keep the UI readable:
- Show the user’s time zone explicitly
- Offer a “More times” button if you want pagination
---
Step 6: Create the booking via Cal.com API
At this point you have:
- Organizer / host identity (could be mapped to an Outlook user)
- Invitee identity (Slack user mapped to email)
- Start time + duration
- Title/agenda
You’ll call the booking endpoint in the Cal.com API to:
- Validate the slot is still available
- Create the booking
- Trigger calendar event creation and conferencing details (depending on configuration)
**What to store**:
- Slack `channel_id`, `user_id`
- Booking ID
- Start/end in UTC
- External references (Outlook event ID, if available)
Idempotency (important)
Slack can retry requests if your server is slow. Use an idempotency key (e.g., Slack `trigger_id` + selected slot) so you don’t create duplicate bookings.
---
Step 7: Send confirmation back to Slack
After booking succeeds:
- Update the modal with success state **or** close it and post a message
- Include:
- Confirmed date/time
- Invitee
- Meeting link (if available)
- Reschedule/cancel links (if your flow supports it)
A clean message template:
- **Booked:** Project sync (30 min)
- **When:** Tue 2:30–3:00 PM PT
- **With:** Alex
- **Link:** (meeting URL)
---
OAuth and identity mapping: the part that usually hurts
You’ll need a consistent way to map:
- Slack user → email address
- Email address → Microsoft identity
- Microsoft identity → scheduling host (Cal.com user / team / event type)
Common strategies:
1. **Slack profile email** (fastest)
- Use Slack API to fetch user profile email
- Works well if Slack is tied to corporate email
2. **Explicit connect step** (more robust)
- Ask users to “Connect Outlook” once
- Store Microsoft refresh token securely
3. **Service account** (admin-driven)
- Central mailbox can book on behalf of others (requires careful permission setup)
For teams building internal tooling, (2) is usually the best trade-off.
---
Security and compliance checklist
- Verify Slack signatures on every request
- Encrypt OAuth tokens at rest
- Use least-privilege Graph scopes
- Log booking attempts with correlation IDs
- Implement rate limiting (Slack and Graph will both throttle you)
- Handle time zone conversion carefully (test DST boundaries)
---
Example flow (pseudo-sequence)
1. `/book @alex 30m "Project sync"`
2. Backend:
- Resolve Slack users → emails
- Fetch Outlook free/busy for organizer (and optionally invitee)
- Generate slots
3. Slack modal shows selectable slots
4. User selects `2026-02-10T22:30:00Z`
5. Backend calls Cal.com booking API
6. Backend posts confirmation
If you’re comparing build-vs-buy for the scheduling layer, it’s worth reading [PRODUCT_LINK]this open-source scheduling option: Cal.com[/PRODUCT_LINK] to understand what you can offload (buffers, event types, team scheduling, white-label booking pages) while keeping Slack as the front door.
---
Conclusion
A great Slack “Book a Meeting” experience is mostly about **orchestrating three things well**: identity, availability, and booking confirmation. Outlook (via Microsoft Graph) gives you the calendar reality; Slack gives you the workflow surface; and a scheduling API gives you a reliable place to enforce rules and create bookings without re-building an entire scheduling product.
If you keep the Slack UX minimal, treat time zones and retries seriously, and centralize scheduling rules, you’ll end up with a flow that feels native to how teams already work—no tab switching, no back-and-forth, and fewer scheduling mistakes.