Skip to main content
Required permission: Booking → Read to list links, slots and bookings; Booking → Write to publish a link, take a booking or cancel one.
Booking is its own permission, and not part of Calendar.Creating a booking link publishes a page on the open internet that lets strangers put meetings on your calendar. That is a bigger decision than reading what is on it, so it is a separate box to tick — the same reasoning that keeps Sending separate from Messages.Booking links a key creates belong to the organization. A key never sees a member’s personal booking links or the bookings taken on them.

How the pieces fit

You never write a slot. Slots are what is left after the rules meet the calendar, so they are always derived and never stored.
Times are a clock, days are numbers. "10:00" rather than 600 minutes past midnight, because nobody writes an integration in minutes since midnight. Days stay numeric with Sunday at 0 — that is what EXTRACT(DOW) and JavaScript’s getDay() both use, and inventing a third vocabulary would mean translating twice.end_time may be "24:00", meaning midnight at the far end of the day. 00:00 would read as the start of the same day and close the window before it opened.
Slugs are unique across all of Ruber, not just your organization — they are paths on one shared domain. A taken slug answers 400 and says nothing about who holds it. A window too short to hold one meeting is refused with a sentence naming the problem, not a constraint name: “The window from 09:00 to 09:30 is shorter than the 60-minute meeting it is meant to hold.”

Read, change, close

{id} may be the slug. It is the half you already have — it is in the URL you published — so a request whose only purpose is translating one identifier into another is not needed. PATCH changes only the fields you name, and the three rule fields are checked together against the result: shortening the window and shortening the meeting are each fine alone and impossible in the wrong order.
To take a page down, set active: false — do not delete it.Deleting a link that has bookings would delete the record of every meeting taken through it while leaving the meetings themselves on the calendar. So it is refused while any booking stands, and the answer says how many there are.active: false closes the page immediately and keeps everything.
The endpoint that makes booking usable from a program. Everything else about a link can be derived from its record; which times are actually free cannot, because it depends on the whole calendar.
bookable_between is why an empty list is not always “fully booked”.A link’s own lead_minutes and horizon_days bound what it will ever offer. Ask for next year and you get nothing — not because the day is busy, but because the page is not open that far ahead. Those two edges are reported so you can tell the difference.
These are the same slots the public page shows, from the same code. Opening hours, the buffer, the lead time, the horizon and every event already on the calendar — including repeating ones, expanded — all apply.

Take a booking

starts_at must be exactly one of the offered slots — take it from /slots rather than constructing it. A time that is not on offer is refused with the next one that is:
Everyone in the organization is notified, exactly as they are for a booking taken through the public page.

Being told about bookings

Subscribe to booking.created and booking.cancelled rather than polling GET /v1/bookings on a timer. Both routes raise them — a guest on /book/{slug} and a call to this API — because the event is raised when the booking row appears rather than by either caller. Since nearly every booking comes from the public page, an integration that only watched its own writes would miss almost all of them. Personal booking links raise nothing, for the same reason a key cannot read them. See the warning on the Webhooks page.

List and cancel

Cancelled bookings are hidden by default: a cancelled meeting is not on anybody’s calendar, so including it would answer “what is booked” with things that are not.
Cancelling gives the time back.DELETE /v1/bookings/{id} stamps cancelled_at, marks the calendar event cancelled, and puts the slot back on offer — the same time can be booked again by somebody else.The record is kept rather than deleted, because “who booked this and then cancelled” is a real question. The event is marked cancelled rather than removed, so the owner can still see what was in their day and who called it off; deleting it would make the meeting vanish with no trace, which is how somebody turns up anyway.
Cancelling something already cancelled succeeds and changes nothing. You asked for it to be cancelled, and it is.

Not available yet

The public booking page itself is not an API. /book/{slug} is a page for people. A guest booking through it does not need a key, and this API is the owner’s side of the same data. Confirmation and reminder emails are sent by the app on the schedule it already uses. There is no way to trigger, suppress or re-send one here. Rescheduling is a cancel and a new booking. There is no single call that moves one, because the new time has to be checked against the slots exactly as a first booking would be.

Errors

See Errors for the full response shape.