Appointments engine

Archive a staff member (admin, or manage_staff)

post/api/providers/{id}/archive

The third state alongside active and deleted, and the one to reach for when somebody leaves: unlike DELETE it works on a staff member who has bookings, and unlike the free active toggle it stops the seat being billed.

Deliberately reversible. Only the photo is thrown away; bio, phone, service links and working hours all survive untouched, and a linked login is suspended rather than unlinked, so POST /api/providers/{id}/reactivate has nothing to re-enter or re-link. All of it happens inside one book_archive_provider() call (migration 0086), so a partial failure cannot leave a login suspended with the card still reading as active, or the reverse.

The person leaves the seat count (seatsUsed() excludes them) and joins a separate archived count, free on every plan up to the plan's own limit (SeatPlan.archivedLimit in billing/config.ts: Free 3, Solo 5, Growth 10, Pro 20, Custom unlimited). At the limit this answers 402, and nothing already archived is ever removed to make room. The tier is re-read from the database here rather than trusted from the caller.

Authorization

sessionCookie
sb-qxrvgfkjyvbngipqvslu-auth-token<token>

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

id*string

Provider id.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/api/providers/string/archive"
{  "ok": true}