Bookings
Booking lifecycle
Booking statuses, guest and venue permissions, provider limitations, and the live floor.
A booking is a party’s reservation at a location. Its status records the lifecycle; service_state is a separate front-of-house detail and may be null. Use the lifecycle verbs rather than writing either field directly.
Statuses and permissions
| Status | Meaning |
|---|---|
requested |
The venue must accept or decline the request |
confirmed |
The reservation is accepted |
seated |
The party is seated |
completed |
Service has finished |
declined_by_venue |
The venue declined the request |
cancelled_by_guest |
The guest, or a partner acting for the guest, cancelled |
cancelled_by_venue |
The venue cancelled |
cancelled_unattributed |
A provider reported cancellation without identifying the actor |
no_show |
The party did not arrive |
bookings:write authorizes holds, create, change, and guest-side cancellation. It does not authorize venue actions, venue-side cancellation, or walk-ins. An app with bookings:read can read all bookings at its granted locations, not only bookings it created. Venue-internal notes are never included.
Act for the venue
These endpoints require bookings:manage and a location grant:
Endpoint suffix on /v1/bookings/{id} |
Legal transition |
|---|---|
/confirm |
requested → confirmed |
/decline |
requested → declined_by_venue |
/seat |
confirmed → seated |
/complete |
seated → completed |
/no_show |
confirmed → no_show |
Send POST with {} or { "expected_version": 3 }. Each response is the updated full booking. A stale version answers 409 stale_version; an illegal transition answers 409 illegal_transition with details.from_status. The audit records the app acting for the venue on the api_partner channel. The client cannot select its own actor or elevate a bookings:write request.
OpenTable does not support these venue write-backs. It answers 422 capability_unsupported; check the location’s profile capabilities before offering a venue action. Resy and SevenRooms are not served booking gateways.
Cancel as the venue
POST /v1/bookings/{id}/venue_cancel (bookings:manage) cancels a requested or confirmed booking on the venue’s behalf and returns it as cancelled_by_venue, for host-stand and POS apps. POST /v1/bookings/{id}/cancel (bookings:write) is the guest’s cancel and always lands as cancelled_by_guest, whatever scopes the app holds.
{ "expected_version": 1, "idempotency_key": "<unique cancellation key>" }The guest’s cancellation window does not apply to the venue. A stale version answers 409 stale_version; a booking already seated or finished answers 409 not_cancellable with details.reason. The key is scoped to your app, so a retry after a lost response replays the cancel. Maple-native bookings only for now: other bookings answer 422 capability_unsupported.
Seat a walk-in
POST /v1/locations/{locationId}/walk_ins (bookings:manage) seats a party that just arrived and returns the new booking with status: "seated" and channel: "walk_in":
{ "party_size": 2, "guest": { "first_name": "Alex", "last_name": "Quinn", "phone": "+12125551234" }, "notes": "High chair", "idempotency_key": "<unique walk-in key>"}Maple picks the earliest table that fits the party now, as the venue’s own host stand does; there is no force-book. When no table is free, the request answers 409 slot_unavailable, and its message names the next opening; add the party to the waitlist instead. phone must be a number Maple can text. The key is scoped to your app across its locations: a retry with the same key and request returns the same booking even though its table is now taken, and the same key with a different request or location answers 409 idempotency_key_reused. Maple-native locations only (422 capability_unsupported otherwise).
Read the live floor
GET /v1/locations/{locationId}/booking_floor requires bookings:read and is available only at enabled Maple-native locations with authored geometry.
The response contains as_of, time_zone, tables, areas, and summary. Tables report their current state (free, reserved, held, seated, or maintenance), the covering party in current, and their next claim within 24 hours in next.
- A future reservation does not make a table occupied now: it can be
freewith a non-nullnext. current.guestcontains separate first/last names andphone_last_four, never full phone or venue notes. Followbooking_idto read the booking when needed.- Holds have no booking ID. Their
booking_idisnull; internal hold IDs are not exposed on the floor. ends_atisnullwhen a seated party has overstayed its planned turn; the API does not promise when it will leave.listed: falsekeeps an occupied table visible after it was removed from the current plan. Such parties contribute tooff_plan_parties.- Seat bounds or area capacity are
nullwhen not known. A combination’s party counts once in area occupancy, not once per table.
Read on demand or poll at intervals of at least 15 seconds. Use booking webhooks as a change signal and the floor as a reconciliation read. There is no floor webhook in this release. The walk-in queue has its own endpoints; see Run the waitlist.
Events describe changes, payloads describe dispatch-time state
Each booking transition has its own stable event identity per recipient app/environment. The embedded booking is its latest state when the event is first recorded for that recipient, not a historical transition snapshot. For example, a delayed booking.created event can embed a booking already cancelled. previous_status is null in this version.
Dedupe deliveries by event ID. Reconcile booking state by id and version; do not infer historical state solely from the event name or assume delivery order.