Ban somebody
const url = 'https://api.sloose.com/staff/people/c1d2e3f4/ban';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"reason":"example","expiresAt":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.sloose.com/staff/people/c1d2e3f4/ban \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "reason": "example", "expiresAt": "example" }'Backoffice route: a staff session, or ADMIN_TOKEN. A ban is on the person, not on a membership: every session they hold in every organisation answers 403 BANNED at once, and so does a new sign-in. Their existing sessions are ended too, so nothing keeps working until it expires. Staff cannot be banned — take the role away first, which is a deliberate second step. Written down as user.ban.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The person
Example
c1d2e3f4The person
Request Bodyrequired
Section titled “Request Bodyrequired”object
Why. Required, and shown to nobody but staff.
When the ban lifts itself: an ISO date (midnight UTC) or an ISO timestamp with Z or an offset. Omitted means it does not.
Examplegenerated
{ "reason": "example", "expiresAt": "example"}Responses
Section titled “Responses”Banned, and signed out.
object
Browsers signed out, as sessions/revoke counts them: a CRM tab’s own session is its browser’s.
Example
{ "banned": true}The request — its body or its query — did not match the schema. issues carries the Zod issue list.
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}A bearer that is neither the token nor a live session (code: AUTH_REQUIRED).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}A customer’s session, an API token, or no bearer at all — not staff, and not the ADMIN_TOKEN (code: ADMIN_REQUIRED).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}No such person, or it is not visible to this session.
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}That person is staff (code: STAFF_CANNOT_BE_BANNED).
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}The restore switch is on (code: MAINTENANCE): every route but /health and /robots.txt is refused before anything is read, except the operator’s own POST /staff/people/{id}/delete with the ADMIN_TOKEN. Sloose is down for maintenance. Please try again in a few minutes.
object
Example
{ "code": "MAINTENANCE"}Headers
Section titled “Headers”Seconds until asking again is worth it (300 while the switch is on).