See an org as one of its members
const url = 'https://api.sloose.com/staff/orgs/org_9f3c/impersonate';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"userId":"example","reason":"example","write":true,"confirm":"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/orgs/org_9f3c/impersonate \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "userId": "example", "reason": "example", "write": true, "confirm": "example" }'Backoffice route, staff session only — the shared ADMIN_TOKEN is refused with 403 SESSION_REQUIRED. Mints a session for a member of the org that lasts an hour and does not slide. Read-only by default: every request that is not a GET is refused with 403 IMPERSONATION_READ_ONLY, except POST /auth/session/refresh and POST /auth/impersonation/end.
Pass write: true for a view that acts as the member for real — every row it writes is theirs, and the org cannot tell from the data that it was not. That variant needs a reason and confirm set to the org’s own name, and is refused rather than downgraded if either is missing.
The widget shows who is looking, and says so more loudly when the view can write. Staff session only — the admin token cannot look as somebody, since nobody would be on the record. Written down as impersonate.start against the member, with write in the detail.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The org
Example
org_9f3cThe org
Request Body
Section titled “Request Body”object
The member to see the org as. Defaults to its most senior member.
Why, for the record.
Ask for a view that may write. reason and confirm are then required, and the request is refused — never quietly downgraded to read-only — if either is missing. Omit for a read-only view.
The org’s own name, typed out. Required when write is true.
Examplegenerated
{ "userId": "example", "reason": "example", "write": true, "confirm": "example"}Responses
Section titled “Responses”The session, read-only unless write was asked for, and where to open it.
object
object
A session token for the member. Read-only unless write on this response is true.
Expiry, seconds since the epoch. Does not slide.
Whether this view may write, or only read.
object
The widget, outside the CRM, with the session in the fragment — open it in a new tab.
Example
{ "session": { "role": "owner" }}The request body 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 member of this org, 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"}