Delete your own account
/api/accountDanger zone. Unlike a one-account-per-company product, a Booking org can have several members, so deleting YOUR account does not always take the workspace with it:
- Last member standing: nobody would be left who could ever sign in and manage or delete the org, so the whole workspace is deleted too.
- Teammates remain: only this user's membership and personal data go; the workspace is shared, not owned.
- Sole admin with staff remaining: refused with 400. Promote a teammate first. This mirrors the "cannot remove the last admin" rule on DELETE /api/members/{id}, so an admin cannot self-delete into an org nobody can administer.
When the workspace does go, its live Stripe subscriptions are cancelled immediately, before the database cascade, and that cancellation has to succeed for the deletion to proceed (see the 502). The Stripe customer and its invoices are deliberately NOT deleted: Australian tax law requires seven years of sales records, so erasure covers the account and retention covers the invoices.
This route is exempted from the onboarding redirect in middleware so a mid-onboarding account can still delete itself.
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 DELETE "https://example.com/api/account" \ -H "Content-Type: application/json" \ -d '{ "confirm": "DELETE" }'{ "ok": true}Remove your own profile photo DELETE
Deletes the object and nulls the metadata field.
List this org's recent imports and exports (admin) GET
The Import & export hub's history, newest first, capped at 25. Reads `book_data_jobs` (migration 0100) through the service-role client, scoped explicitly by `company_id`. Every finished export carries a freshly minted `downloadUrl`: a signed URL into the PRIVATE `data-exports` bucket, valid for 15 minutes. It is generated per request and stored nowhere, because it is a bearer credential for a file containing the venue's entire client list. Sweeps stalled jobs as a side effect (`flagStalledJobs`), which is how a worker that died mid-import becomes visible without a cron of its own. Never 500s on a missing table: migrations here are applied by hand AFTER the deploy, so between the two this route answers 200 with `unavailable: true` rather than a stack trace nobody can act on.