Skip to content

See an organisation as one of its members

POST
/staff/orgs/{orgId}/impersonate
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 organisation 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 (STAFF_VIEW on the routes that act on the person rather than the organisation), except POST /auth/session/refresh and POST /auth/impersonation/end.

Pass write: true for a view that acts as the member for real within this organisation — every row it writes in the organisation is theirs, and the organisation cannot tell from the data that it was not. It still makes none of the person’s own writes outside the organisation — making an organisation, accepting an invitation, asking another organisation for access, ending one of their sessions, moving the session, changing their second factor — each refused with 403 STAFF_VIEW. Nor, within the organisation, does it grant a credential or access that would outlast it — an API token, an invitation, an approved access request, a raised role, an app’s grant — or close the organisation: each refused with 403 IMPERSONATION_REFUSED (an app’s grant as OAuth’s access_denied). That variant needs a reason and confirm set to the organisation’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.

orgId
required

The organisation

string
Example
org_9f3c

The organisation

Media typeapplication/json
object
userId

The member to see the organisation as. Defaults to its most senior member.

string
reason

Why, for the record.

string
<= 500 characters
write

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.

boolean
confirm

The organisation’s own name, typed out. Required when write is true.

string
Examplegenerated
{
"userId": "example",
"reason": "example",
"write": true,
"confirm": "example"
}

The session, read-only unless write was asked for, and where to open it.

Media typeapplication/json
object
session
required
object
token
required

A session token for the member. Read-only unless write on this response is true.

string
orgId
required
string
userId
required
string
role
required
string
Allowed values: owner admin builder operator
exp
required

Expiry, seconds since the epoch. Does not slide.

number
write
required

Whether this view may write, or only read.

boolean
member
required
object
email
required
string
displayName
required
string | null
expiresAt
required
string
widgetUrl
required

The widget, outside the CRM, with the session in the fragment — open it in a new tab.

string
Example
{
"session": {
"role": "owner"
}
}

The request — its body or its query — did not match the schema. issues carries the Zod issue list.

Media typeapplication/json

The error envelope every non-2xx answer uses.

object
error
required

Human-readable explanation.

string
code

Machine-readable reason. Absent on a few legacy 400s.

string
key
additional properties
Examplegenerated
{
"error": "example",
"code": "example"
}

A bearer that is neither the token nor a live session (code: AUTH_REQUIRED).

Media typeapplication/json

The error envelope every non-2xx answer uses.

object
error
required

Human-readable explanation.

string
code

Machine-readable reason. Absent on a few legacy 400s.

string
key
additional properties
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).

Media typeapplication/json

The error envelope every non-2xx answer uses.

object
error
required

Human-readable explanation.

string
code

Machine-readable reason. Absent on a few legacy 400s.

string
key
additional properties
Examplegenerated
{
"error": "example",
"code": "example"
}

No such member of this organisation, or it is not visible to this session.

Media typeapplication/json

The error envelope every non-2xx answer uses.

object
error
required

Human-readable explanation.

string
code

Machine-readable reason. Absent on a few legacy 400s.

string
key
additional properties
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.

Media typeapplication/json
object
error
required
string
code
required
string
Allowed value: MAINTENANCE
Example
{
"code": "MAINTENANCE"
}
Retry-After
integer

Seconds until asking again is worth it (300 while the switch is on).

Report a problem with this page

sloose.com