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.
Endpoints
Section titled “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 |
Create a staff table booking
Section titled “Create a staff table booking”Book a table on a guest’s behalf. Requires a user_id (see
Guests to find or create one) and a table_id.
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" }'const res = await fetch( "https://thesidedoor.co/api/my-venues/VENUE_ID/staff-bookings", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ 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", }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID/staff-bookings");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "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", ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "booking_id": "bkg_9a1" }Create a staff guest-list booking
Section titled “Create a staff guest-list booking”Add a guest to a list for an access rule. time
defaults to the rule’s start time when omitted.
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"] }'const res = await fetch( "https://thesidedoor.co/api/my-venues/VENUE_ID/staff-guestlist-bookings", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ user_id: "usr_abc", access_rule_id: "rul_7", booking_date: "2026-07-17", party_size: 2, reservation_tags: ["vip"], }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID/staff-guestlist-bookings");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "user_id" => "usr_abc", "access_rule_id" => "rul_7", "booking_date" => "2026-07-17", "party_size" => 2, "reservation_tags" => ["vip"], ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "booking_id": "bkg_9a2" }Seat a booking
Section titled “Seat a booking”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.
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"}'const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/assign-table", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ table_id: "tbl_12", new_time: "20:30" }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/assign-table");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "table_id" => "tbl_12", "new_time" => "20:30", ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "table_id": "tbl_12", "booking_time": "20:30" }Auto-assign a table
Section titled “Auto-assign a table”POST /api/bookings/:id/auto-assign takes no body and returns the picked table.
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/auto-assign" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/auto-assign", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` } },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/auto-assign");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "success": true, "table_id": "tbl_08" }Unassign a table
Section titled “Unassign a table”POST /api/bookings/:id/unassign-table (no body) clears the assignment.
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/unassign-table" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"await fetch("https://thesidedoor.co/api/bookings/BOOKING_ID/unassign-table", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` },});$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/unassign-table");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "success": true }Edit booking details
Section titled “Edit booking details”Update the party size, reservation tags or comments. Send at least one field;
changing party_size also syncs the guest count.
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"}'const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/details", { method: "PATCH", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ party_size: 6, reservation_tags: ["birthday", "allergy"], comments: "Nut allergy", }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/details");curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "party_size" => 6, "reservation_tags" => ["birthday", "allergy"], "comments" => "Nut allergy", ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true }Lifecycle flags
Section titled “Lifecycle flags”Toggle the front-of-house flags on a seated booking: paid (with optional
paid_amount in pence), in_use, and check_in.
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}'const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/lifecycle", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ paid: true, paid_amount: 12000, in_use: true }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/lifecycle");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "paid" => true, "paid_amount" => 12000, "in_use" => true, ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true }Lock, duration and close
Section titled “Lock, duration and close”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.
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"}'await fetch("https://thesidedoor.co/api/bookings/BOOKING_ID/lock", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ locked: true }),});
await fetch("https://thesidedoor.co/api/bookings/BOOKING_ID/duration", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ duration_mins: 150 }),});$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/duration");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["duration_mins" => 150]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "locked": 1 }Set status
Section titled “Set status”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.
curl -X PATCH "https://thesidedoor.co/api/bookings/BOOKING_ID/status" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"status":"approved"}'const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/status", { method: "PATCH", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ status: "approved" }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/status");curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["status" => "approved"]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "status": "approved" }Approve, reject, unreject, cancel
Section titled “Approve, reject, unreject, cancel”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).
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"await fetch("https://thesidedoor.co/api/bookings/BOOKING_ID/approve", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` },});
await fetch("https://thesidedoor.co/api/bookings/BOOKING_ID/reject", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ reason: "Fully booked" }),});$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/approve");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "success": true, "booking": { "id": "bkg_9a1", "status": "approved", "approved_by_name": "Front Desk", "approved_at": "2026-07-15T09:12:00Z" }}Door: check-in and reject
Section titled “Door: check-in and reject”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.
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..."}'const res = await fetch("https://thesidedoor.co/api/check-in", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ booking_id: "BOOKING_ID", qr_code: "eyJ2IjoxLCJi...", }),});const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/check-in");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "booking_id" => "BOOKING_ID", "qr_code" => "eyJ2IjoxLCJi...", ]),]);$data = json_decode(curl_exec($ch), true);{ "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:
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"}'const res = await fetch("https://thesidedoor.co/api/door-reject", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ booking_id: "BOOKING_ID", reason: "dresswear" }),});const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/door-reject");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "booking_id" => "BOOKING_ID", "reason" => "dresswear", ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "reason": "Dress code", "refunded": false, "door_rejected_by_name": "Door", "door_rejected_at": "2026-07-17T21:06:00Z"}Card holds
Section titled “Card holds”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).
Capture a hold
Section titled “Capture a hold”Omit amount_pence to capture the full authorised amount, or pass a smaller
value for a partial capture.
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}'const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/hold/capture", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ amount_pence: 5000 }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/hold/capture");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["amount_pence" => 5000]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "status": "captured", "amount_pence": 5000 }Release a hold
Section titled “Release a hold”POST /api/bookings/:id/hold/release (no body) voids the authorisation.
curl -X POST "https://thesidedoor.co/api/bookings/BOOKING_ID/hold/release" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/hold/release", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` } },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/hold/release");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "success": true, "status": "released" }Request a hold by email
Section titled “Request a hold by email”Email the guest a hosted Checkout deposit link. amount_pence is required
(min 50); set notify with an email to send it.
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"}'const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/hold/request", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ amount_pence: 5000, description: "Table deposit", notify: true, email: "guest@example.com", }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/hold/request");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "amount_pence" => 5000, "description" => "Table deposit", "notify" => true, "email" => "guest@example.com", ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "checkout_url": "https://checkout.stripe.com/c/pay/cs_...", "amount_pence": 5000, "emailed": true}Take a card in person (MOTO)
Section titled “Take a card in person (MOTO)”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.
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}'const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/hold/intent", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ amount_pence: 5000 }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/hold/intent");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["amount_pence" => 5000]),]);$data = json_decode(curl_exec($ch), true);{ "client_secret": "pi_..._secret_...", "intent_id": "pi_...", "publishable_key": "pk_live_...", "amount_pence": 5000}Read a booking
Section titled “Read a booking”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.
curl "https://thesidedoor.co/api/bookings/BOOKING_ID" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch("https://thesidedoor.co/api/bookings/BOOKING_ID", { headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` },});const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "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}Booking history
Section titled “Booking history”GET /api/bookings/:id/history returns the chronological audit trail.
curl "https://thesidedoor.co/api/bookings/BOOKING_ID/history" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch( "https://thesidedoor.co/api/bookings/BOOKING_ID/history", { headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` } },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/bookings/BOOKING_ID/history");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "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 } ]}Floor calendar
Section titled “Floor calendar”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.
curl "https://thesidedoor.co/api/my-reservations/calendar?from=2026-07-17&to=2026-07-17&venue=VENUE_ID" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch( "https://thesidedoor.co/api/my-reservations/calendar?from=2026-07-17&to=2026-07-17&venue=VENUE_ID", { headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` } },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-reservations/calendar?from=2026-07-17&to=2026-07-17&venue=VENUE_ID");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "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": []}Venue reservations
Section titled “Venue reservations”Lightweight floor reservations for named walk-in and phone guests, scoped to a venue.
List reservations for a date
Section titled “List reservations for a date”curl "https://thesidedoor.co/api/my-venues/VENUE_ID/reservations?date=2026-07-17" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch( "https://thesidedoor.co/api/my-venues/VENUE_ID/reservations?date=2026-07-17", { headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` } },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID/reservations?date=2026-07-17");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "data": [ { "id": "res_1", "table_id": "tbl_12", "table_number": "12", "guest_name": "Sam Lee", "party_size": 4, "reservation_time": "20:00", "status": "confirmed" } ]}Create a reservation
Section titled “Create a reservation”table_id, guest_name, reservation_date and reservation_time are required.
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" }'const res = await fetch( "https://thesidedoor.co/api/my-venues/VENUE_ID/reservations", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ 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", }), },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID/reservations");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "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", ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "id": "res_1" }Update or delete a reservation
Section titled “Update or delete a reservation”PUT accepts any subset of the create fields (plus status); DELETE takes no
body.
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"await fetch( "https://thesidedoor.co/api/my-venues/VENUE_ID/reservations/RES_ID", { method: "PUT", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ party_size: 6, status: "confirmed" }), },);$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID/reservations/RES_ID");curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["party_size" => 6, "status" => "confirmed"]),]);$data = json_decode(curl_exec($ch), true);{ "success": true }