# Bookings for developers Book with Alvin, MCP clients, the REST API and webhooks. Source: https://docs.getridian.com/scheduling/developers/ Language: en Reviewed: 2026-11-03 Every channel books through the same path as the booking page: Ridian checks free times again, writes the calendar entry and sends the booker the confirmation with management link. ## Alvin Alvin lists your event types, finds free times and shows bookings in the app and in WhatsApp. To book, reschedule or cancel, Alvin shows a proposal that you confirm, as long as Alvin's execution mode is **Ask before changes**, the default. With **Execute automatically**, Alvin carries it out directly. If the time is no longer free or a calendar cannot be read, nothing changes. Alvin also adds time off when you ask (“I'm on vacation next week”) and then hands bookings over to a cover, again as a proposal you confirm. ## MCP With the scopes `bookings:read` and `bookings:write`, MCP clients use these tools: `list_appointment_types`, `find_booking_slots` (up to 31 days), `list_bookings` (up to 92 days), `get_booking`, `book_appointment`, `reschedule_booking`, `cancel_booking` and `anonymize_booking`, and for [time off](https://docs.getridian.com/scheduling/absences/) `list_absences`, `create_absence`, `delete_absence` and `reassign_booking`. Send a fixed `request_id` with `book_appointment`; the same `request_id` returns the same booking instead of a second one. Inputs and outputs are listed in the [MCP reference](https://docs.getridian.com/developers/mcp/). ## REST API In team workspaces, a developer project with an app token reads and books via `https://api.getridian.com/v1`. Turn on access under **Developer > API projects**, **Access** tab; **Scheduling > Bookings > API** shows the status and links there. The project acts for the whole workspace. | Method and path | Scope | Purpose | | --- | --- | --- | | `GET /appointment-types` | `bookings:read` | Event types, including `reminder_minutes_before` | | `GET /appointment-types/{id}/slots?from=&to=` | `bookings:read` | Free times, up to 31 days | | `GET /bookings?from=&to=` | `bookings:read` | Bookings, up to 92 days, up to 100 per page; `status=cancelled` for cancellations | | `GET /bookings/{id}` | `bookings:read` | One booking | | `POST /bookings` | `bookings:write` | Book: `appointment_type_id`, `start`, `booker` (`name`, `email`), `time_zone`, `language`, `request_id` | | `POST /bookings/{id}/reschedule` | `bookings:write` | Reschedule: `start` | | `POST /bookings/{id}/cancel` | `bookings:write` | Cancel: optional `reason` | | `POST /bookings/{id}/anonymize` | `bookings:write` | Remove the booking's personal data, no body; also for cancelled bookings. Returns the booking with `anonymized: true` | Bookings include `series_id` and `series_index` (from 0) for sessions of a recurring series, otherwise `null`; each session is its own booking and is rescheduled or cancelled on its own. `waitlist_length` is the number of people waiting for a group time or course, otherwise `null`. Alvin and MCP return the same fields. Times are ISO date-times with an offset, for example `2026-11-03T08:30:00+01:00`. A time that is no longer free returns `409`; fetch slots again. Paid event types return `402` and are booked on their booking page. ```sh curl https://api.getridian.com/v1/bookings \ -H "Authorization: Bearer $RIDIAN_APP_TOKEN" \ -H "Content-Type: application/json" \ -d '{"appointment_type_id":"…","start":"2026-11-03T08:30:00+01:00","booker":{"name":"Lea Example","email":"lea@example.org"},"time_zone":"Europe/Berlin","request_id":"crm-4711"}' ``` ## Webhooks In team workspaces, Ridian reports bookings to your endpoint, set up under **Developer > Webhooks**: - `booking.created`: a booking is confirmed. Recurring series send one event per session with `series_id` and `series_index`. - `booking.rescheduled`: a booking has a new time; `previous` holds the old one. - `booking.cancelled`: a confirmed booking was cancelled, with `cancelled_by` and `cancellation_reason`. - `booking.reassigned`: a booking went to another person; `host_user_id` is the new one, `previous_host_user_id` the previous one. - `waitlist.joined`: someone is on a waitlist: once confirmed for groups and courses, immediately for a fully booked day. `kind` is `seat` or `day`, plus `start` or `day`, `position` (`seat` only), `person` and `lead_id`. - `waitlist.promoted`: someone moved up or received the payment link; `booking_id` is the new booking. Confirmed moves also send `booking.created`. Each delivery carries `x-ridian-event`, `x-ridian-delivery`, `x-ridian-timestamp` and `x-ridian-signature: v1=` over `x-ridian-timestamp + "." + raw_body`. The key is the signing secret (`ridian_whsec_…`) shown once when you add the webhook. Deduplicate by `x-ridian-delivery` before replying with 2xx. **Developer > Webhooks** lists all webhooks of the workspace with a delivery log: event, time, HTTP status or error reason and next attempt. We delete deliveries 30 days after delivery or after the last attempt.