Place a furniture-set piece (a bar, a multi-tabletop banquette)
/api/tables/furniture-setIndependent booking (2026-09-10): a piece that renders as ONE object on the floor plan but is backed by N real, separately-bookable rows: one per bar stool, or one per banquette tabletop. Creates a new book_table_link_groups row (kind='furniture_set') and N book_tables rows in one atomic insert; the first row's id is deliberately set equal to the group's own id (the anchor, the only member that ever carries real geometry; see that row's own comment for why no extra column was needed to mark it).
Deliberately its own route, not a branch inside POST /api/link-groups: that route gates on the Venue Pro table_combining feature, and a furniture-set piece must be placeable on every plan tier. A separate route makes that impossible to leak in by accident. MAX_COMBINED_TABLES (the ordinary combine cap) does not apply to this group's kind either, so a whole 12-seat bar can still be booked as one party.
Authorization
sessionCookie The dashboard's Supabase Auth session cookie, set at sign-in. Large sessions are split across
numbered chunks (…auth-token.0, .1), so treat this as a cookie family rather than one name.
Every request re-validates it against the Auth server (getUser()), never by decoding the cookie
locally: a JWT nothing has checked is not a credential. Tenancy is then read from the verified
app_metadata.company_id claim and enforced by row-level security; it is never read from request
input, on any route, ever.
role (admin / staff) is deliberately not in RLS. It gates specific actions in route code,
the operations marked admin below, so hiding a button in the UI is cosmetic only, and a route's
own check is the enforcement.
In: cookie
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/tables/furniture-set" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "shape": "rect" }'{ "ok": true, "linkGroupId": "856ba7c8-3373-4364-b044-8aea0515333c", "anchorId": "6915c716-ecd7-4d6a-967e-f688b69cd207", "tables": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", "seats_min": 0, "seats_max": 0 } ]}Create a range of tables in one request POST
Generates `prefix + separator + n` for every n from `from` to `to` inclusive (capped at 50 per batch) and inserts them as one atomic statement. Rejects the whole batch; nothing is created; if any generated name already exists in this org; table names are not unique in the schema, so this is an app-level check on a fresh read, not a database constraint.
List a furniture-set piece's configured combos GET
Every staff-configured subset of one piece's real member rows that MAY combine into one reservation (book_furniture_set_combos + ...combo_members, 2026-09-11). By default a furniture-set piece's members never auto-combine (see reservation-slots.ts's own comment), so an empty list here means every member of that piece is bookable only on its own until staff configure one.