Skip to content

Bundles, promo codes & tags

The catalogue resources that dress up bookings: bundles of paid add-ons, promo codes for discounts, and tags for classifying guests and reservations. This page also covers copy-from, which clones a settings scope from another of your venues. Every endpoint is under /api/my-venues/:venueId/… and is operator (client role, venue-scoped) - send an Authorization: Bearer token from the Authentication flow. Prices are integer pence.

Method Path Purpose Auth
GET/POST /api/my-venues/:venueId/bundles List/create bundles operator
PUT/DELETE /api/my-venues/:venueId/bundles/:id Update/delete a bundle operator
POST /api/my-venues/:venueId/bundles/:id/items Add a bundle item operator
PUT/DELETE /api/my-venues/:venueId/bundles/:id/items/:itemId Update/delete an item operator
POST /api/my-venues/:venueId/bundles/:id/items/:itemId/image Upload item image operator
POST /api/my-venues/:venueId/copy-from Copy a settings scope from another venue operator
GET/POST /api/my-venues/:venueId/promo-codes List/create promo codes operator
PUT/DELETE /api/my-venues/:venueId/promo-codes/:id Update/delete a promo code operator
POST /api/my-venues/:venueId/promo-codes/:id/reset Reset redemption count operator
GET /api/my/tag-catalogue Account-wide default tags operator
GET /api/my-venues/:venueId/tag-catalogue Venue tag catalogue operator
POST/DELETE /api/my-venues/:venueId/tags Add/remove a custom tag operator
POST /api/my-venues/:venueId/tag-categories Add a custom category operator
PATCH /api/my-venues/:venueId/tag-categories Update category visibility operator

A bundle has a name and an optional applicable_profiles array ("tables", "events"; omit to apply to both). Items live under it, each with a name, price (pence), optional max_qty and image_url.

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/bundles" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"VIP Package","applicable_profiles":["tables"]}'
{ "success": true, "id": "bnd_vip" }

Then POST /api/my-venues/:venueId/bundles/:id/items to add an item:

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/bundles/bnd_vip/items" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Bottle of Champagne","price":12000,"max_qty":5}'
{ "success": true, "id": "itm_champ" }

Update an item with PUT .../bundles/:id/items/:itemId and delete it with DELETE .../bundles/:id/items/:itemId. To give an item a picture, POST .../bundles/:id/items/:itemId/image with a base64 data URL in a data field (max 2 MB); the response returns { "success": true, "url": "…" } and stores it as the item’s image_url.

POST /api/my-venues/:venueId/copy-from clones a scope of settings from a source venue you also own into this one. This overwrites the target scope. Provide source_venue_id and a scope.

Allowed scope values: bundles, shifts, access-rules, availability, tables, queue, payment-policies, access-profiles, admission-rules, promo-codes, client-tags, reservation-tags.

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/copy-from" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"source_venue_id":"SOURCE_VENUE_ID","scope":"bundles"}'
{ "success": true, "copied": 4 }

A promo code has a name, a unique code (uppercased server-side), a discount_pct (0–100) and optional max_uses and expires_at. A duplicate code for the same venue returns 409.

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/promo-codes" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Summer Launch","code":"SUMMER25","discount_pct":25,"max_uses":100,"expires_at":"2026-09-01T00:00:00.000Z"}'
{ "success": true, "id": "promo_summer" }

Update with PUT .../promo-codes/:id and delete with DELETE .../promo-codes/:id. To zero the redemption counter without deleting the code:

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/promo-codes/promo_summer/reset" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN"
{ "success": true }

Tags come in two kinds: guest (CRM labels) and reservation (booking labels). Platform defaults are read-only; you can add venue-custom tags and categories on top. GET /api/my-venues/:venueId/tag-catalogue?kind=guest returns the merged view (defaults + custom + category flags); GET /api/my/tag-catalogue returns just the account-wide defaults.

POST /api/my-venues/:venueId/tag-categories creates a category with kind and name. Category visibility is tuned later with PATCH /api/my-venues/:venueId/tag-categories (allow_guest_select, show_on_slip, show_in_summary).

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/tag-categories" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"kind":"guest","name":"VIP"}'
{ "success": true }

Then POST /api/my-venues/:venueId/tags adds a tag under it with kind, category and label:

Terminal window
curl -X POST "https://thesidedoor.co/api/my-venues/VENUE_ID/tags" \
-H "Authorization: Bearer $SIDEDOOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"kind":"guest","category":"VIP","label":"Regular"}'
{ "success": true }

Remove a custom tag with DELETE /api/my-venues/:venueId/tags - pass kind, category and label as query-string parameters (platform defaults cannot be removed).