Skip to main content
Bookings use your app’s location grants, not its POS connection. A booking integration can coexist with another app receiving orders at the same location. The surface rolls out per location; ask Maple to enable your test location first. Set MAPLE_BASE to your environment’s base URL, including /v1, and MAPLE_KEY to a matching credential. See Environments. You need bookings:read for discovery and reads, and bookings:write for holds and guest-side writes.

1. Read the booking profile

Check enabled, provider, and capabilities. Native locations have a hold_ttl_seconds of 300 by default. Provider-managed locations report null because the provider owns expiry; always use the hold’s expires_at.

2. Search availability

start and end are venue-local wall-clock times, not UTC instants. Choose a future window no longer than 31 days:
Each data entry contains an opaque slot_token, starts_at in UTC, starts_at_local, and any quoted cancellation policy. Tokens expire after 15 minutes. Save the selected token unchanged; never reconstruct it from the displayed time. A 422 is a business outcome, not an empty result: inspect code and details for party-size bounds, booking-window restrictions, or a large-party inquiry contact.

Experiences

Some venues sell experiences: a prix-fixe menu, a tasting, a ticketed seating. Where the location offers them (booking_profile.capabilities.experiences), availability lists their slots alongside standard ones, in start order. An experience slot names its experience: id, name, description, and prepayment_required. Standard slots have experience: null. To show one experience’s times, pass its id:
Book an experience slot like any other: its slot_token is bound to the experience, so the hold and the booking are for it, and the booking’s experience names it. OpenTable can move an experience booking to another time of the same experience, but not to a different experience or a standard table: that change answers 422 capability_unsupported, so cancel and book the new slot instead. Maple can’t take payment yet, so holding a slot whose experience has prepayment_required: true answers 422 payment_instrument_required. Show those experiences, but offer a standard slot to book. Maple-native locations don’t offer experiences yet: capabilities.experiences is false and experience_id answers 422 capability_unsupported.

3. Hold the slot

Save id as the hold ID. The hold claims capacity until expires_at; create the booking before then. If the guest abandons the flow, release a native hold with DELETE /v1/booking_holds/{holdId}. A consumed hold answers 409 hold_consumed instead of reporting that its capacity was released. Each app may have ten live holds per location, enforced atomically across concurrent requests. Native and provider holds count, including provider acquisitions still awaiting an outcome. A different app cannot release or consume your hold, even if both apps are granted the location; those requests return 404. If a provider hold response is lost, its quota reservation has a conservative 24-hour quarantine after the last possible provider attempt. Once that deadline passes, it no longer consumes quota. The original operation stays recorded and cannot restart after its replay window; this does not clear an uncertain booking create/change/cancel operation. All partner hold IDs use bkh_…. Repeating the same slot_token replays your live hold rather than acquiring another lock. OpenTable release remains a no-op: the provider lock and its quota usage remain until expiry or consumption. Check booking_profile.capabilities.hold_release before promising an early release.

4. Create the booking

The response is the full booking resource. At native locations, its initial status is confirmed or requested, according to the venue’s acceptance policy. Save its id and version. Guest phone is required; the current service accepts dialable North American numbers. The persisted hold supplies the authoritative quote for both native and provider-managed bookings. You can omit slot_token; it remains accepted as an optional field for existing integrations.
A timeout or 409 operation_in_progress does not mean the provider rejected the booking. Retry with the same key and body, never a new key. Maple records the pending command before provider I/O and reconciles uncertain results using the same provider request identity. If details.reason is replay_window_expired, stop automatic retries and contact Maple with details.operation_id. See Replay safety.

5. Change or cancel

For a native change, search again with changing_booking_id=<booking id>. This excludes the booking’s current capacity claim. Send the chosen token to POST /v1/bookings/{id}/change, with a new idempotency_key and optionally expected_version. Provider-managed locations reject changing_booking_id with 422 capability_unsupported. Their direct-change path takes a token from an ordinary availability search instead. OpenTable supports time/party changes, but not guest-note changes or structured intake_answers; those fields return 422 capability_unsupported rather than being silently dropped.
A partner cancellation lands as cancelled_by_guest; a host-stand app with bookings:manage cancels for the venue with POST /v1/bookings/{id}/venue_cancel instead (see Cancel as the venue). A stale version answers 409 stale_version with details.expected and details.actual. Provider-backed writes claim the mirrored booking before provider I/O; a competing write can answer 409 operation_in_progress while that claim is active. A successful replay runs before the version check, so its original expected_version does not prevent replay. Read the booking again before deciding whether to submit a different change. Cancellation and reschedule policy refusals include a reason in details. Version claims serialize writes through Maple; they do not lock out changes made directly in the provider’s own tools.

Find a guest’s booking

When a guest calls or texts about their reservation, look it up by the phone they booked with or the confirmation code they were given, instead of paging through the day:
The phone is normalized before matching, and a lookup without start/end matches bookings at any time, ordered by slot start. It returns ordinary booking resources, ready for a change or cancel. location_id is required. See Listing bookings. At a provider-managed location (OpenTable), a lookup that includes phone first asks the provider, so it also finds a reservation the guest made directly with OpenTable. OpenTable looks reservations up by phone only: a confirmation_code-only lookup finds the provider reservations Maple already knows about, so include the phone when you have it.

Request limits

The default per-app, per-environment budgets are 60 availability searches/minute and 300 other booking requests/minute. The budgets are independent and apply across granted locations. Existing order/menu routes are not included. A 429 includes both a Retry-After header and retry_after in its JSON body; wait before retrying. Maple can adjust these deployment-level budgets.

Follow changes

Subscribe to booking webhooks. Use GET /v1/bookings/{id} for current state, or the incremental list to catch up after downtime. Venue operations and the live-floor read are described in Booking lifecycle.