Create a level (floor)
/api/levelsThe first tier of the floor hierarchy; a level groups areas and/or tables that sit directly on it. Lands at the end of the list (sort_order = max+1, migration 0111) and busts the cached public booking config, matching services/groups. Levels are only ever actually IN that config when locationPickerEnabled is on, same reasoning as tables.
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/levels" \ -H "Content-Type: application/json" \ -d '{ "name": "string" }'{ "ok": true, "level": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08" }}Delete a table (admin) DELETE
`book_reservations.table_id` is ON DELETE RESTRICT, so a table with sittings against it keeps its history and cannot be deleted.
Reorder levels (floors) PATCH
The body is every level in its new order, and array position IS the new sort_order (migration 0111): the same shape and write pattern as PATCH /api/areas. Not re-gated by `planAllows('floors')`: that check belongs to CREATING a level; every level being reordered here already exists and already cleared it.