Venues
Venue management for operators. Every endpoint here is operator (client
role, venue-scoped) unless noted - send an Authorization: Bearer token from the
Authentication flow. Venue-scoped calls also check
that your account can access the target venue and return 404 if not.
| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET | /api/my-venues |
List venues you can access | operator |
| POST | /api/my-venues |
Create a venue | operator |
| PUT | /api/my-venues/:id |
Update venue settings | operator |
| PUT | /api/my-venues/:id/status |
Switch draft/live | operator |
| POST | /api/my-venues/:id/request-listing |
Request Sidedoor app listing | operator |
| POST | /api/my-venues/:id/withdraw-listing |
Withdraw a pending listing | operator |
| GET | /api/my-venues/:id/stats |
Per-venue stats | operator |
| GET | /api/my-stats |
Cross-venue operator stats | operator |
| GET | /api/my-venues/:id/sisters |
List sister venues | operator |
| POST | /api/my-venues/:id/sisters |
Link a sister venue | operator |
| DELETE | /api/my-venues/:id/sisters/:sisterId |
Unlink a sister venue | operator |
| POST | /api/venues/:id/logo |
Upload a venue logo | operator |
List venues
Section titled “List venues”GET /api/my-venues returns the full venue records your account can access.
curl "https://thesidedoor.co/api/my-venues" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch("https://thesidedoor.co/api/my-venues", { headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` },});const { data } = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "data": [ { "id": "VENUE_ID", "name": "The Blue Room", "status": "live", "app_listing_status": "approved" } ]}Create a venue
Section titled “Create a venue”POST /api/my-venues. Only name and address are required; the rest are
optional. food_types is stored only when venue_type is restaurant or
cafe. New venues are created status: "live" with app_listing_status: "pending".
curl -X POST "https://thesidedoor.co/api/my-venues" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"The Blue Room","address":"12 Example Street, London","venue_type":"bar","phone":"+442071234567","email":"hello@blueroom.example","backdoor_capacity":120,"queue_skip_price":10}'const res = await fetch("https://thesidedoor.co/api/my-venues", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ name: "The Blue Room", address: "12 Example Street, London", venue_type: "bar", phone: "+442071234567", email: "hello@blueroom.example", backdoor_capacity: 120, queue_skip_price: 10, }),});const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "name" => "The Blue Room", "address" => "12 Example Street, London", "venue_type" => "bar", "phone" => "+442071234567", "email" => "hello@blueroom.example", "backdoor_capacity" => 120, "queue_skip_price" => 10, ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "id": "VENUE_ID", "status": "live", "app_listing_status": "pending" }Update venue settings
Section titled “Update venue settings”PUT /api/my-venues/:id. Send only the fields you want to change - any field left
out keeps its current value. The main body fields:
| Field | Type | Notes |
|---|---|---|
venue_type |
string | e.g. bar, restaurant, cafe, club |
food_types |
array|string|null | stored only for restaurant/cafe; null clears |
phone, email |
string | contact details |
backdoor_capacity |
int | door capacity |
queue_skip_price |
number | queue-skip charge |
surge_threshold, surge_price |
number | surge pricing trigger + price |
last_entry_time |
string | e.g. "02:00" |
max_plus_ones |
int | default 3 |
members_only |
int | 0–2 |
opening_hours |
object | validated; stored as JSON |
guest_list_enabled |
bool | enable guest-list bookings |
tables_enabled |
bool | enable table bookings |
paid_guest_list_enabled |
bool | charge for guest list |
booking_policy |
string|null | default booking policy id |
default_booking_duration |
int | minutes, default 120 |
default_party_min, default_party_max |
int | default 1 / 10 |
booking_cutoff_value, booking_cutoff_unit |
int, string | how late bookings close |
booking_start_value, booking_start_unit |
int, string | how far ahead bookings open |
website, description |
string | empty string clears |
marketing_sender_name, marketing_reply_to |
string | branded-email sender |
instagram_url, tiktok_url, twitter_url |
string | social links |
curl -X PUT "https://thesidedoor.co/api/my-venues/VENUE_ID" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"tables_enabled":true,"guest_list_enabled":true,"default_booking_duration":120,"default_party_min":1,"default_party_max":10,"last_entry_time":"02:00","website":"https://blueroom.example"}'const res = await fetch("https://thesidedoor.co/api/my-venues/VENUE_ID", { method: "PUT", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ tables_enabled: true, guest_list_enabled: true, default_booking_duration: 120, default_party_min: 1, default_party_max: 10, last_entry_time: "02:00", website: "https://blueroom.example", }),});const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID");curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "tables_enabled" => true, "guest_list_enabled" => true, "default_booking_duration" => 120, "default_party_min" => 1, "default_party_max" => 10, "last_entry_time" => "02:00", "website" => "https://blueroom.example", ]),]);$data = json_decode(curl_exec($ch), true);{ "success": true }Switch draft/live
Section titled “Switch draft/live”PUT /api/my-venues/:id/status with { "status": "draft" | "live" }. Going
live requires name, address, venue_type, phone, email,
backdoor_capacity, last_entry_time and a logo to be set - otherwise you get a
400 listing the missing fields. Switching a live venue back to draft is
blocked (409) while it has upcoming reservations.
curl -X PUT "https://thesidedoor.co/api/my-venues/VENUE_ID/status" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"status":"live"}'const res = await fetch("https://thesidedoor.co/api/my-venues/VENUE_ID/status", { method: "PUT", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ status: "live" }),});const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID/status");curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["status" => "live"]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "status": "live" }Request or withdraw an app listing
Section titled “Request or withdraw an app listing”A live venue can request to be listed in the Sidedoor consumer app.
POST /api/my-venues/:id/request-listing moves app_listing_status to
pending; POST /api/my-venues/:id/withdraw-listing withdraws a still-pending
request back to none. Neither takes a body.
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/request-listing" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch( "https://thesidedoor.co/api/my-venues/VENUE_ID/request-listing", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` }, },);const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID/request-listing");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$data = json_decode(curl_exec($ch), true);{ "app_listing_status": "pending" }Venue stats
Section titled “Venue stats”GET /api/my-venues/:id/stats returns revenue, booking counts and a 14-day
chart for a single venue.
curl "https://thesidedoor.co/api/my-venues/VENUE_ID/stats" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch("https://thesidedoor.co/api/my-venues/VENUE_ID/stats", { headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` },});const stats = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID/stats");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$stats = json_decode(curl_exec($ch), true);{ "venue": { "id": "VENUE_ID", "name": "The Blue Room" }, "revenue": { "today": 240, "week": 1680, "month": 7200, "alltime": 54000 }, "bookings": { "pending": 3, "approved": 41, "cancelled": 2, "total": 46, "today_count": 5 }, "unique_guests": 512, "chart": [{ "booking_date": "2026-06-20", "status": "approved", "count": 4 }]}Operator stats
Section titled “Operator stats”GET /api/my-stats aggregates across all your venues.
curl "https://thesidedoor.co/api/my-stats" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"const res = await fetch("https://thesidedoor.co/api/my-stats", { headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` },});const stats = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-stats");curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);$stats = json_decode(curl_exec($ch), true);{ "venues": 3, "total_guests": 1840, "month_guests": 210, "revenue": 0, "partner": null}Sister venues
Section titled “Sister venues”Sister links are symmetric and let guests discover related venues. GET /api/my-venues/:id/sisters lists them; POST adds one with { sister_venue_id }
(you must be able to access both venues, and a venue cannot sister itself); DELETE /api/my-venues/:id/sisters/:sisterId removes both directions of the link.
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/sisters" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"sister_venue_id":"SISTER_VENUE_ID"}'const res = await fetch("https://thesidedoor.co/api/my-venues/VENUE_ID/sisters", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ sister_venue_id: "SISTER_VENUE_ID" }),});const data = await res.json();$ch = curl_init("https://thesidedoor.co/api/my-venues/VENUE_ID/sisters");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["sister_venue_id" => "SISTER_VENUE_ID"]),]);$data = json_decode(curl_exec($ch), true);{ "success": true }To unlink:
curl -X DELETE "https://thesidedoor.co/api/my-venues/VENUE_ID/sisters/SISTER_VENUE_ID" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN"await fetch( "https://thesidedoor.co/api/my-venues/VENUE_ID/sisters/SISTER_VENUE_ID", { method: "DELETE", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}` }, },);$ch = curl_init( "https://thesidedoor.co/api/my-venues/VENUE_ID/sisters/SISTER_VENUE_ID");curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$token}"],]);curl_exec($ch);{ "success": true }Upload a logo
Section titled “Upload a logo”POST /api/venues/:id/logo. As with all Sidedoor image uploads, send the image
as a base64 data URL in a JSON field named data (multipart is not accepted).
Max 500 KB. The response returns the stored logo_url. A logo is required before
a venue can go live.
curl -X POST "https://thesidedoor.co/api/venues/VENUE_ID/logo" \ -H "Authorization: Bearer $SIDEDOOR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"data":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."}'const res = await fetch("https://thesidedoor.co/api/venues/VENUE_ID/logo", { method: "POST", headers: { Authorization: `Bearer ${process.env.SIDEDOOR_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ data: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...", }),});const { logo_url } = await res.json();$dataUrl = "data:image/png;base64," . base64_encode(file_get_contents("logo.png"));$ch = curl_init("https://thesidedoor.co/api/venues/VENUE_ID/logo");curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$token}", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["data" => $dataUrl]),]);$data = json_decode(curl_exec($ch), true);{ "success": true, "logo_url": "/assets/venue-logo/VENUE_ID/a1b2c3d4e5f6.png" }