Save floor-plan geometry for a batch of tables and rooms
/api/tables/layoutWhere the floor-plan editor autosaves (migrations 0091 and 0093). A batch on purpose: a drag session touches several tables (and, since 0093, the room zones around them) and one debounced save carries them all. Positions and sizes are in grid units (one unit is a nominal 25cm; see lib/booking/floorplan.ts). Null posX/posY means "not placed" (both or neither, mirroring the database constraints); a table's null width/height means "keep deriving the size from seatsMax", while a DRAWN room must carry its size (there is no seat count to derive one from). An id deleted concurrently is skipped and simply not counted in updated, never an error.
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.
At least one of tables / rooms must be non-empty.
Response Body
application/json
application/json
application/json
application/json
curl -X PATCH "https://example.com/api/tables/layout" \ -H "Content-Type: application/json" \ -d '{}'{ "ok": true, "updated": 0}