Source: https://cli.nylas.com/guides/calendar-availability-booking-page

# Calendar Availability API for a Booking Page

You want to show open time slots from a real calendar on a website so visitors can book a meeting. This guide generates free slots as JSON, renders them on a page, creates the event on selection without double-booking, and handles timezones — prototyped end to end from the terminal.

Written by [Hazik](https://cli.nylas.com/authors/hazik) Director of Product Management

Reviewed by [Qasim Muhammad](https://cli.nylas.com/authors/qasim-muhammad)

Updated June 9, 2026

> **TL;DR:** Generate open slots with `nylas calendar availability find --json`, serve that JSON to your frontend, and book the chosen slot with `nylas calendar events create`. One re-check between “show” and “book” is what keeps two visitors from grabbing the same slot — the double-booking section has it.

## How do I generate open booking slots from a calendar?

You generate open slots with `nylas calendar availability find`, which scans one or more participants' calendars and returns the time windows when everyone is free. Pass the meeting length with `--duration` (minutes) and the slot granularity with `--interval`, then take JSON out.

```bash
# 30-minute slots on 15-minute boundaries, next 7 days, as JSON
nylas calendar availability find \
  --participants you@example.com \
  --duration 30 --interval 15 \
  --start "tomorrow 9am" --end "tomorrow 5pm" \
  --json
```

The defaults are sensible: a 30-minute duration, 15-minute intervals, and a 7-day search window starting at the next hour. Because the command reads live free/busy, a slot that's already booked never appears in the output — you're rendering the real calendar, not a cached copy.

## How do I expose those slots to a website?

Expose the slots by serving the JSON the command emits behind a small endpoint your frontend calls. A scheduled job regenerates the feed every few minutes so the page stays close to live; the browser fetches the static JSON and renders clickable times. This keeps your calendar credentials server-side and never in the client.

```bash
#!/usr/bin/env bash
set -euo pipefail

# Regenerate the public slot feed (run on a 5-minute cron)
# No --end means the default 7-day search window from now
nylas calendar availability find \
  --participants you@example.com \
  --duration 30 --json \
  > /var/www/booking/slots.json
```

Cache the feed with a short TTL — 2 to 5 minutes balances freshness against calendar API calls. A stale feed is acceptable for display because the booking step re-checks availability before committing, which is the real source of truth.

## How do I prevent two visitors booking the same slot?

You prevent double-booking by re-checking availability at the moment of booking, not relying on the slot list the visitor saw. Between rendering the feed and the click, another visitor may have taken the slot, and the calendar is eventually consistent, so a just-created event can lag a read by a second or two. Re-verify, then create.

```bash
#!/usr/bin/env bash
set -euo pipefail
SLOT_START="2026-06-12 14:00"; SLOT_END="2026-06-12 14:30"

# Re-check the exact 30-minute window still fits before committing.
# availability find returns the slots that fit; 0 means the window is taken.
FREE=$(nylas calendar availability find \
  --participants you@example.com \
  --duration 30 --start "$SLOT_START" --end "$SLOT_END" --json | jq 'length')

if [ "$FREE" -gt 0 ]; then
  nylas calendar events create --title "Intro call" \
    --start "$SLOT_START" --end "$SLOT_END" \
    --participant visitor@example.com
else
  echo "slot just taken — offer the next one"
fi
```

## How do I handle timezones for a public booking page?

Handle timezones by storing every slot in UTC and converting to the visitor's local zone in the browser. A booking page serves people in many zones, and an off-by-one-hour slot is the most common scheduling bug. When you create the event, the `--lock-timezone` flag pins it to a fixed zone so a DST shift doesn't move the meeting.

Show the slot in the visitor's zone, confirm it back in both zones (“2:00 PM your time / 5:00 PM host time”), and let the calendar invite carry the canonical timezone. The CLI's [cross-timezone scheduling](https://cli.nylas.com/guides/schedule-across-timezones-cli) guide covers the find-time math when host and guest span continents.

## When should I move from the CLI to the Nylas API?

The CLI is the fastest way to prototype and run the whole flow from a server, and it's enough for internal tools and low-volume booking pages. When you need an embeddable widget, per-user OAuth at scale, or a hosted scheduling page, move the same model to the Nylas Scheduler and Calendar API — the free/busy and event semantics are identical, so nothing you learned here is wasted.

The honest trade-off: a shell-and-cron feed has no built-in UI, queue, or retry logic, so it suits dozens of bookings a day, not thousands. Treat this guide as the working prototype that proves the flow, then graduate the hot path to the API when traffic justifies it.

## Next steps

- [Check calendar availability from the terminal](https://cli.nylas.com/guides/check-calendar-availability-cli) — free/busy checks for a single person or a group
- [Round-robin scheduling](https://cli.nylas.com/guides/round-robin-scheduling-cli) — distribute bookings across a team fairly
- [Schedule across timezones](https://cli.nylas.com/guides/schedule-across-timezones-cli) — find times that work for participants on different continents
- [Find a meeting time](https://cli.nylas.com/guides/find-meeting-time-cli) — the availability-find command in depth
- [Command reference](https://cli.nylas.com/docs/commands) — every flag, subcommand, and example
- [Google Calendar API: freebusy.query](https://developers.google.com/calendar/api/v3/reference/freebusy/query) — the free/busy primitive behind slot generation
- [Microsoft Graph: event resource](https://learn.microsoft.com/en-us/graph/api/resources/event) — the Outlook side of creating a booked event
- [RFC 5545 — iCalendar](https://datatracker.ietf.org/doc/html/rfc5545) — the spec the calendar invite is built on
