Create a service
/api/servicesAdds a bookable service (a haircut, a consultation). company_id comes from the verified JWT claim and is never read from the body. Busts the cached public booking config for this org.
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
curl -X POST "https://example.com/api/services" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "durationMinutes": 5, "color": "string" }'{ "ok": true, "service": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08" }}API reference
All 259 public operations, grouped by product area.
Reorder and/or regroup services PATCH
The body is one category's (or "Uncategorized"'s, via a null groupId) full shelf in its new order: position in the array becomes the new `sort_order`, and every listed id is written to `groupId`. A drag that only reorders within one category sends that category's own id back unchanged; a drag that moves a service into a different (or no) category sends the destination's id and its full resulting id list, including whichever service just arrived from elsewhere, so this one request is the only write a cross-category move needs. Same shape as PATCH /api/service-groups; an id that is not this org's simply matches zero rows under RLS.