Delete a service group (admin, or manage_services)
/api/service-groups/{id}Never blocks and never takes services with it: the composite FK's column-scoped on delete set null (group_id) (0054) un-groups them in the same statement. That column list is load-bearing; a bare composite set null would null company_id too and fail the delete outright (the 0039 lesson). Gated to admin, or a staff login granted manage_services (migration 0082), same as every other service-catalog write.
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
Path Parameters
Group id.
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X DELETE "https://example.com/api/service-groups/string"{ "ok": true}Update a service group PATCH
Full replacement of the group's editable fields, same PATCH-in-name-only semantics as PATCH /api/services/{id}. RLS scopes the update, so an id from another org matches zero rows and returns 404.
Create a staff member POST
Creates the provider row, then its service links and working hours. If the second step fails the provider is deleted again (its cascade takes any partial links with it), so a failure leaves nothing behind. Returns the id so a follow-up avatar upload has something to hang off.