Skip to content

Embed & public widget endpoints

These are the public endpoints behind the Sidedoor widgets you embed on your own website - booking, events, vouchers and the all-in-one combo. They need no bearer token: a widget is identified by its venue (or event) and gated where appropriate by a bot check (Turnstile). For the operator-facing setup - enabling widgets, theming and grabbing the embed URL - see the widgets guide.

Method Path Purpose Auth
GET /api/public/venues/:venueId/booking-widget-config Booking widget config, keys and theme public
GET /api/public/venues/:venueId/availability Open slots for a date and party size public
GET /api/public/venues/:venueId/floorplan Floors and tables for guest table-pick public
POST /api/public/venues/:venueId/book Create a booking (may need payment) public
POST /api/public/venues/:venueId/book/finalize Finalise a deposit after payment public
GET /api/public/venues/:venueId/booking/:bookingId/qr Fetch the booking’s QR code public
GET /api/public/venues/:venueId/events-widget Events widget listing public
GET /api/public/venues/:venueId/events-widget-config Events widget config and keys public
GET /api/public/events/:eventId/booking-options Bundles, ticket types and policy for an event public
POST /api/public/events/:eventId/create-intent Start an event booking public
POST /api/public/events/:eventId/finalize Finalise an event booking after payment public
GET /api/public/venues/:venueId/voucher-config Voucher widget config and keys public
POST /api/public/voucher-purchase/create-intent Start a gift-voucher purchase public
POST /api/public/voucher-purchase/finalize Finalise a voucher purchase, return codes public
GET /api/public/venues/:venueId/guestlist-options Guest-list rates, surge and promo public
POST /api/public/venues/:venueId/guestlist-bookings Join the guest list (spends keys) session
GET /api/public/venues/:venueId/combo-widget-config All-in-one widget config public

GET /api/public/venues/:venueId/booking-widget-config returns the venue’s booking-widget settings, its theme, and the publishable keys the widget needs (Stripe publishable key and Turnstile site key). Fetch this first when bootstrapping a widget.

Terminal window
curl "https://thesidedoor.co/api/public/venues/VENUE_ID/booking-widget-config"
{
"venue": { "id": "VENUE_ID", "name": "The Blue Room" },
"widget": { "enabled": true, "theme_mode": "detailed", "accent_color": "#C0A060" },
"publishable_key": "pk_live_...",
"turnstile_site_key": "0x4AAA..."
}

GET /api/public/venues/:venueId/availability returns bookable slots for a date and party_size. Set type to tables or guestlist. It also returns the applicable rules, bundles and, when the requested time is full, the next available dates.

Terminal window
curl "https://thesidedoor.co/api/public/venues/VENUE_ID/availability?date=2026-07-18&party_size=4&type=tables"
{
"venue": { "id": "VENUE_ID", "name": "The Blue Room" },
"date": "2026-07-18",
"party_size": 4,
"type": "tables",
"slots": [
{ "time": "19:00", "access_rule_id": "rul_dinner", "available": true },
{ "time": "19:30", "access_rule_id": "rul_dinner", "available": true }
],
"party_too_large": false,
"next_available_dates": []
}

For a floorplan where the guest picks their own table, call GET /api/public/venues/:venueId/floorplan with the same date, time and party_size (plus the chosen rule_id); it returns { floors, tables } with per-table availability.

POST /api/public/venues/:venueId/book creates the booking. Pass the slot the guest chose (access_rule_id, rule_type, date, time, party_size), any bundle_selections, the guest’s contact details and - for guest (non-logged-in) callers - a turnstile_token.

The response depends on the venue’s payment policy. With no deposit you get { ok: true, booking_id, status }. When a deposit is required you get { requires_payment: true, payment_client_secret, booking_id } - confirm the payment_client_secret with Stripe on the client, then finalise (below).

Terminal window
curl -X POST "https://thesidedoor.co/api/public/venues/VENUE_ID/book" \
-H "Content-Type: application/json" \
-d '{
"access_rule_id": "rul_dinner",
"rule_type": "tables",
"date": "2026-07-18",
"time": "19:00",
"party_size": 4,
"guest_name": "Sam Guest",
"guest_email": "sam@example.com",
"guest_phone": "+447700900123",
"turnstile_token": "TURNSTILE_TOKEN"
}'
{
"requires_payment": true,
"booking_id": "bkg_456",
"payment_client_secret": "pi_3Nabc_secret_xyz"
}

After the guest confirms the payment_client_secret with Stripe, call POST /api/public/venues/:venueId/book/finalize with the booking_id. It re-reads the payment intent and either confirms the booking or releases it if payment did not complete. It is idempotent - safe to retry.

Terminal window
curl -X POST "https://thesidedoor.co/api/public/venues/VENUE_ID/book/finalize" \
-H "Content-Type: application/json" \
-d '{"booking_id":"bkg_456"}'
{ "ok": true, "booking_id": "bkg_456", "status": "confirmed" }

Once confirmed, fetch the door QR with GET /api/public/venues/:venueId/booking/:bookingId/qr. The code is short-lived - expires_in_ms tells you when to refresh it.

Terminal window
curl "https://thesidedoor.co/api/public/venues/VENUE_ID/booking/bkg_456/qr"
{ "qr_code": "data:image/png;base64,iVBOR...", "issued_at": 1751500000, "expires_in_ms": 60000 }

List a venue’s what’s-on with GET /api/public/venues/:venueId/events-widget (and .../events-widget-config for keys and theme). For a chosen event, read GET /api/public/events/:eventId/booking-options to get bundles, ticket types and policy, then book with POST /api/public/events/:eventId/create-intent.

The create-intent body carries the selection ({ kind, ticket_type_id, quantity, party_size }), guest details and - for guests - a turnstile_token. It returns { free, booking_id }, { requires_payment, ... } or { requires_confirmation }. When payment was needed, complete it and call POST /api/public/events/:eventId/finalize with the payment_intent_id.

Terminal window
curl -X POST "https://thesidedoor.co/api/public/events/EVENT_ID/create-intent" \
-H "Content-Type: application/json" \
-d '{
"selection": { "kind": "ticket", "ticket_type_id": "tkt_ga", "quantity": 2 },
"guest_name": "Sam Guest",
"guest_email": "sam@example.com",
"turnstile_token": "TURNSTILE_TOKEN"
}'
{ "requires_payment": true, "booking_id": "evb_789", "payment_intent_id": "pi_3Nxyz" }

Read GET /api/public/venues/:venueId/voucher-config for settings and keys. Start a purchase with POST /api/public/voucher-purchase/create-intent (amount, quantity, delivery and purchaser details); after payment, call POST /api/public/voucher-purchase/finalize with the intent_id to receive the issued voucher codes.

Terminal window
curl -X POST "https://thesidedoor.co/api/public/voucher-purchase/create-intent" \
-H "Content-Type: application/json" \
-d '{
"venue_id": "VENUE_ID",
"amount_pence": 5000,
"quantity": 1,
"delivery": "recipient",
"recipient_name": "Alex",
"recipient_email": "alex@example.com",
"purchaser_name": "Sam Guest",
"purchaser_email": "sam@example.com"
}'
{ "intent_id": "vin_321", "client_secret": "pi_3Nvou_secret_abc" }

After confirming payment, finalise:

POST /api/public/voucher-purchase/finalize { "intent_id": "vin_321" }
{
"success": true,
"delivery": "recipient",
"vouchers": [
{ "code": "GIFT-4KQ2-9XTP", "amount_pence": 5000, "expires_at": "2027-07-03" }
]
}

Read GET /api/public/venues/:venueId/guestlist-options for the rate, any surge and promo eligibility, then join with POST /api/public/venues/:venueId/guestlist-bookings. This one needs a session - the guest must be signed in, because it spends guest keys rather than taking a card payment. The body is { rule_id, date, party_size, option_kind, promo_code }.

{ "success": true, "booking_id": "bkg_902", "status": "approved", "keys_spent": 2, "auto_approved": true }

GET /api/public/venues/:venueId/combo-widget-config returns which flows are enabled (bookings, events, vouchers) plus the links the combo widget needs to route into each of the flows above.

{
"enabled": { "bookings": true, "events": true, "vouchers": false },
"links": { "bookings": "...", "events": "..." }
}