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
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 requirebookings:manage and a location grant:
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.
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":
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.
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 delayedbooking.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.