POST /api/v1/bookings
Booking takes two calls: read the open slots, then book one of them.
1. Read open slots
GET /api/v1/booking-types/{id}/slots returns the start times the public booking page would offer, after the host's other meetings, CRM appointments and connected-calendar busy time. Requires read:bookings.
GET /api/v1/booking-types/cmq8type0alk34567890/slots?from=2026-10-05&to=2026-10-12&timezone=Europe/London HTTP/1.1
Authorization: Bearer alk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| Parameter | Default | Description |
|---|---|---|
from | now | Start of the window. A bare date is midnight UTC |
to | 7 days after from | End of the window (exclusive). At most 62 days after from |
timezone | UTC | IANA time zone used for inviteeLocal |
{
"timezone": "Europe/London",
"slots": [
{ "startAt": "2026-10-05T13:00:00.000Z", "endAt": "2026-10-05T13:30:00.000Z", "hostLocal": "2026-10-05T09:00:00", "inviteeLocal": "2026-10-05T14:00:00" }
]
}A slot carries times only. Nothing in the response says why other times are busy.
2. Book a slot
Pass a slot's startAt back exactly as it was returned. Requires write:bookings.
POST /api/v1/bookings HTTP/1.1
Content-Type: application/json
Authorization: Bearer alk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{
"bookingTypeId": "cmq8type0alk34567890",
"startAt": "2026-10-05T13:00:00.000Z",
"inviteeName": "Dana Reed",
"inviteeEmail": "dana@example.com",
"inviteeTimezone": "Europe/London",
"answers": { "size": "40" }
}| Field | Required | Notes |
|---|---|---|
bookingTypeId | Yes | |
startAt | Yes | A slot's startAt, verbatim |
inviteeName, inviteeEmail | Yes | |
inviteeTimezone | Yes | IANA time zone, used in the invitee's emails |
inviteePhone | When the location is PHONE_HOST_CALLS | |
inviteeNotes | No | Up to 5,000 characters |
guests | No | Up to 10 emails, if the meeting type allows guests |
answers | When the form has required questions | Keyed by question id (see the type's questions) |
The booking then behaves exactly like one made on the public page: the invitee is matched to a contact or becomes a new lead, a MEETING task goes on the CRM calendar, and the confirmation and calendar invitation are emailed.
Response: 201
{ "booking": { "id": "cmq9book0alk34567890", "status": "CONFIRMED", "...": "..." }, "taskId": "cmq7task0alk34567890" }taskId is null only if the CRM task could not be written. The booking still stands.
Two callers booking the same time get one booking and one 409: That time has just been booked. Please pick another one. Read the slots again and pick another.