Skip to content

Bookings & reservations

The operator-side booking API drives the live reservation floor: create table and guest-list bookings on a guest’s behalf, move a booking through its lifecycle, seat it on the floor, run the door, and capture or release card-hold deposits. Unless noted, every endpoint requires the operator role (client) and is scoped to venues you can access; most also accept an organiser for events they run. These are staff endpoints - guest self-service booking lives in the widget endpoints.

Method Path Purpose Auth
POST /api/my-venues/:venueId/staff-bookings Create a staff table booking operator
POST /api/my-venues/:venueId/staff-guestlist-bookings Create a staff guest-list booking operator
POST /api/bookings/:id/assign-table Seat a booking on a table operator
POST /api/bookings/:id/auto-assign Auto-pick and seat a table operator
POST /api/bookings/:id/unassign-table Remove the table assignment operator
PATCH /api/bookings/:id/details Edit party size, tags, comments operator
POST /api/bookings/:id/lifecycle Set paid / in-use / check-in flags operator
POST /api/bookings/:id/lock Lock or unlock a table assignment operator
POST /api/bookings/:id/duration Override the booking duration operator
POST /api/bookings/:id/close Close out a seated booking operator
PATCH /api/bookings/:id/status Set booking status operator
POST /api/bookings/:id/approve Approve a pending booking operator
POST /api/bookings/:id/reject Reject a booking operator
POST /api/bookings/:id/unreject Undo a rejection (→ pending) operator
POST /api/bookings/:id/staff-cancel Cancel a booking as staff operator
POST /api/check-in Check a guest in with a QR code operator
POST /api/door-reject Reject a guest at the door operator
POST /api/bookings/:id/hold/capture Capture a card hold (full/partial) operator
POST /api/bookings/:id/hold/release Release a card hold operator
POST /api/bookings/:id/hold/request Email the guest a deposit link operator
POST /api/bookings/:id/hold/intent Create a MOTO card-entry hold operator
GET /api/bookings/:id Read one booking (detail + QR) session
GET /api/bookings/:id/history Read a booking’s audit trail operator
GET /api/my-reservations/calendar Floor calendar across venues operator
GET /api/my-venues/:venueId/reservations List venue reservations for a date operator
POST /api/my-venues/:venueId/reservations Create a venue reservation operator
PUT /api/my-venues/:venueId/reservations/:resId Update a venue reservation operator
DELETE /api/my-venues/:venueId/reservations/:resId Delete a venue reservation operator

Book a table on a guest’s behalf. Requires a user_id (see Guests to find or create one) and a table_id.

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/staff-bookings" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"user_id": "usr_abc",
"table_id": "tbl_12",
"reservation_date": "2026-07-17",
"reservation_time": "20:00",
"party_size": 4,
"duration_mins": 120,
"reservation_tags": ["birthday"],
"notes": "Window table if possible"
}'
{ "success": true, "booking_id": "bkg_9a1" }

Add a guest to a list for an access rule. time defaults to the rule’s start time when omitted.

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/staff-guestlist-bookings" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"user_id": "usr_abc",
"access_rule_id": "rul_7",
"booking_date": "2026-07-17",
"party_size": 2,
"reservation_tags": ["vip"]
}'
{ "success": true, "booking_id": "bkg_9a2" }

Assign a specific table, or let Sidedoor auto-pick one. new_time moves the booking as you drag it; allow_blocked overrides a blocked table.

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/assign-table" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"table_id":"tbl_12","new_time":"20:30"}'
{ "success": true, "table_id": "tbl_12", "booking_time": "20:30" }

POST /api/bookings/:id/auto-assign takes no body and returns the picked table.

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/auto-assign" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{ "success": true, "table_id": "tbl_08" }

POST /api/bookings/:id/unassign-table (no body) clears the assignment.

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/unassign-table" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{ "success": true }

Update the party size, reservation tags or comments. Send at least one field; changing party_size also syncs the guest count.

Terminal window
curl -X PATCH "https://thesidedoor.co/api/bookings/BOOKING_ID/details" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"party_size":6,"reservation_tags":["birthday","allergy"],"comments":"Nut allergy"}'
{ "success": true }

Toggle the front-of-house flags on a seated booking: paid (with optional paid_amount in pence), in_use, and check_in.

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/lifecycle" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"paid":true,"paid_amount":12000,"in_use":true}'
{ "success": true }

Lock a table so auto-assign won’t move it (locked: true/false/null to clear the override), override the duration in minutes, or close out a booking.

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/lock" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"locked":true}'
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/duration" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"duration_mins":150}'
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/close" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"closed_at_wallclock":"2026-07-17T23:15:00"}'
{ "success": true, "locked": 1 }

Set a booking’s status directly to one of pending, approved, rejected, cancelled or checked_in. reason is used when rejecting. Terminal states (checked_in, cancelled) return 409.

Terminal window
curl -X PATCH "https://thesidedoor.co/api/bookings/BOOKING_ID/status" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"approved"}'
{ "success": true, "status": "approved" }

Dedicated verbs for the approval queue. approve and unreject (undo a rejection → pending) take no body; reject takes an optional reason; staff-cancel cancels the booking (returns 409 once checked in).

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/approve" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/reject" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason":"Fully booked"}'
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/staff-cancel" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{
"success": true,
"booking": {
"id": "bkg_9a1",
"status": "approved",
"approved_by_name": "Front Desk",
"approved_at": "2026-07-15T09:12:00Z"
}
}

On the door, check a guest in against their QR code, or reject them. The reason on door-reject must be one of at_capacity, barred, attitude, dresswear or unspecified.

Terminal window
curl -X POST "https://thesidedoor.co/api/check-in" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"booking_id":"BOOKING_ID","qr_code":"eyJ2IjoxLCJi..."}'
{
"success": true,
"booking": { "id": "bkg_9a1", "status": "checked_in" },
"checked_in_at": "2026-07-17T21:04:00Z",
"checked_in_by_name": "Door"
}

To reject at the door:

Terminal window
curl -X POST "https://thesidedoor.co/api/door-reject" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"booking_id":"BOOKING_ID","reason":"dresswear"}'
{
"success": true,
"reason": "Dress code",
"refunded": false,
"door_rejected_by_name": "Door",
"door_rejected_at": "2026-07-17T21:06:00Z"
}

When a booking policy takes a card-hold deposit, staff can capture it (in full or partially), release it, email the guest a deposit link, or take a card in person over the phone (MOTO).

Omit amount_pence to capture the full authorised amount, or pass a smaller value for a partial capture.

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/hold/capture" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"amount_pence":5000}'
{ "success": true, "status": "captured", "amount_pence": 5000 }

POST /api/bookings/:id/hold/release (no body) voids the authorisation.

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/hold/release" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{ "success": true, "status": "released" }

Email the guest a hosted Checkout deposit link. amount_pence is required (min 50); set notify with an email to send it.

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/hold/request" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"amount_pence":5000,"description":"Table deposit","notify":true,"email":"guest@example.com"}'
{
"success": true,
"checkout_url": "https://checkout.stripe.com/c/pay/cs_...",
"amount_pence": 5000,
"emailed": true
}

POST /api/bookings/:id/hold/intent returns a manual-capture PaymentIntent for keying a card at the desk. Confirm it client-side with Stripe.js and the returned publishable_key.

Terminal window
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/hold/intent" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"amount_pence":5000}'
{
"client_secret": "pi_..._secret_...",
"intent_id": "pi_...",
"publishable_key": "pk_live_...",
"amount_pence": 5000
}

GET /api/bookings/:id returns the full booking with its guest, table, QR code and edit/cancel flags. Any authenticated user may call it, gated by role, venue access or ownership.

Terminal window
curl "https://thesidedoor.co/api/bookings/BOOKING_ID" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{
"booking": {
"id": "bkg_9a1",
"status": "approved",
"party_size": 4,
"table_number": "12",
"seating_area_name": "Terrace",
"venue_name": "The Attic",
"duration_mins": 120
},
"user_name": "Sam Lee",
"user_phone": "+44...",
"membership_tier": "black",
"qr_code": "eyJ2IjoxLCJi...",
"qr_expires_in_ms": 60000,
"is_editable": true
}

GET /api/bookings/:id/history returns the chronological audit trail.

Terminal window
curl "https://thesidedoor.co/api/bookings/BOOKING_ID/history" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{
"events": [
{ "at": "2026-07-15T09:00:00Z", "type": "created", "actor": "Front Desk", "details": null },
{ "at": "2026-07-15T09:12:00Z", "type": "approved", "actor": "Front Desk", "details": null },
{ "at": "2026-07-17T21:04:00Z", "type": "checked_in", "actor": "Door", "details": null }
]
}

GET /api/my-reservations/calendar returns the whole floor - venues, areas, tables, reservations, bookings, orphans and blockouts - for a date range. It is ETag-cached; send If-None-Match for a 304.

Terminal window
curl "https://thesidedoor.co/api/my-reservations/calendar?from=2026-07-17&to=2026-07-17&venue=VENUE_ID" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{
"venues": [{ "id": "ven_123", "name": "The Attic", "grid_colors": {} }],
"areas": [{ "id": "area_1", "venue_id": "ven_123", "name": "Terrace" }],
"tables": [{ "id": "tbl_12", "venue_id": "ven_123", "area_id": "area_1", "table_number": "12", "capacity": 4 }],
"reservations": [
{ "id": "res_1", "source": "venue_reservation", "table_id": "tbl_12", "guest_name": "Sam Lee", "party_size": 4, "start_time": "20:00", "end_time": "22:00", "status": "confirmed" }
],
"orphans": [],
"blockouts": []
}

Lightweight floor reservations for named walk-in and phone guests, scoped to a venue.

Terminal window
curl "https://thesidedoor.co/api/my-venues/VENUE_ID/reservations?date=2026-07-17" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{
"data": [
{ "id": "res_1", "table_id": "tbl_12", "table_number": "12", "guest_name": "Sam Lee", "party_size": 4, "reservation_time": "20:00", "status": "confirmed" }
]
}

table_id, guest_name, reservation_date and reservation_time are required.

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/reservations" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"table_id": "tbl_12",
"guest_name": "Sam Lee",
"guest_phone": "+44...",
"party_size": 4,
"reservation_date": "2026-07-17",
"reservation_time": "20:00",
"duration_mins": 120,
"reservation_tags": ["anniversary"],
"notes": "Quiet corner"
}'
{ "success": true, "id": "res_1" }

PUT accepts any subset of the create fields (plus status); DELETE takes no body.

Terminal window
curl -X PUT "https://thesidedoor.co/api/my-venues/VENUE_ID/reservations/RES_ID" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"party_size":6,"status":"confirmed"}'
curl -X DELETE "https://thesidedoor.co/api/my-venues/VENUE_ID/reservations/RES_ID" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{ "success": true }