---
title: "Book a slot: calendar event + Meet link (Google host) or Teams link (Teams-enabled Microsoft 365 work/school host) + invites"
method: POST
path: "/api/public/{handle}/{slug}/book"
tags: ["Public booking"]
---

# Book a slot: calendar event + Meet link (Google host) or Teams link (Teams-enabled Microsoft 365 work/school host) + invites

`POST /api/public/{handle}/{slug}/book`

## Request

- Base URL: `https://whenmeet.me`
- URL: `https://whenmeet.me/api/public/{handle}/{slug}/book`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `__Host-session`
  - none

Anonymous callers pass Turnstile and a per-IP limit (20/h); signed-in callers and PAT holders skip both. The slot is re-validated with fresh data and guarded in one D1 transaction against double booking. The event goes to the owner’s calendar (or, for an "any" team link, the assignee’s). The invitee and guests get reminder emails at the link’s reminders offsets (24 h and 1 h by default); the invitee’s carries the manage link.

## Path parameters

- `handle` string, required
- `slug` string, required

## Request body

- object
  - `startsAt` integer, required: A slot start from …/slots.
  - `name` string, required
  - `email` string, email, required
  - `guests` union: Extra attendees, e.g. a colleague from another company (≤ 10).
    - string[]
    - string: Comma/space separated list.
  - `answers` object: Keyed by question id.
  - `notes` string
  - `tz` string: Invitee IANA zone (email formatting).
  - `utm` object: Up to 10 utm_* keys (^utm_[a-z_]{1,20}$); malformed ones are dropped.
  - `turnstileToken` string: Required for anonymous callers when Turnstile is configured.

## Response `200`

Booked.

- object
  - `bookingId` string
  - `meetingId` string
  - `startsAt` integer: unix ms
  - `endsAt` integer: unix ms
  - `title` string
  - `conferenceUrl` string, nullable
  - `conference` 'meet' | 'teams' | 'null', nullable: The video the booking actually got.
  - `meetingUrl` string: Shareable meeting page (/m/<id>).
  - `manageUrl` string: Invitee cancel / reschedule link (/booking/<id>?t=<token>). Keep it private.
  - `assignedTo` object, nullable
    - `name` string, nullable

## Other responses

- `400`: invalid_body | invalid_starts_at | invalid_name | invalid_email | invalid_guests | too_many_guests | missing_answer | invalid_answers | invalid_notes.
- `403`: turnstile_failed.
- `404`: not_found.
- `409`: slot_unavailable | host_unavailable.
- `429`: rate_limited.
- `502`: provider_failed (nothing was booked).

---

[API](https://skmtc.dev/whenmeet/apis/whenmeet-me-api.md) · [All operations](https://skmtc.dev/whenmeet/apis/whenmeet-me-api/llms.txt) · [OpenAPI document](https://skmtc.dev/whenmeet/apis/whenmeet-me-api/revisions/202b80022215?raw)
