API reference
People
The people who may use Cloudraw: invite, update, suspend, quarantine and remove them.
- GETList people
- POSTCreate a person
- POSTBulk invite people
- GETGet a person
- PATCHUpdate a person
- DELETEDelete a person
- GETGet a person's effective access
- PATCHChange group membership
- POSTInvite a person
- POSTSign a person out of the browser portal
- POSTQuarantine a person
- DELETERelease a person from quarantine
- POSTUnlock a person's sign-in
List people
GET/v0/tenants/{tenant_id}/people
Returns every person in the workspace with their groups, sign-in state, last activity and device count. The list is not paginated (it is bounded by your plan's seat limit); filter with group or q. People who already have a sign-in account but are not listed yet are added in the background, so a later call may show more.
Token: read-only or full access · Created by: owner or security admin
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
Query parameters
- groupstring
Only members of this group id.
- qstring
Case-insensitive text search in e-mail and name.
Responses
200 All matching people.
application/json
- itemsarray of Personrequired
items fields
- idstringrequired
Person id.
- emailstringrequired
E-mail address; unique in the workspace (case-insensitive).
- namestring | null
Display name.
- groupsarray of stringrequired
Ids of the groups this person belongs to. Group membership is what access rules match on.
- created_by_integratorobject | null
Set when an integrator (partner) created this person on your behalf.
created_by_integrator fields
- kindstring
- partner_idstring
- partner_namestring
- memberstring | null
- member_idstring | null
- atstring (date-time)
- idpstring | null
How the person signs in, as recorded at creation:
cloudraw(Cloudraw password + e-mail code),ad,sso, or the value you sent on create. - mfaboolean
Admin-set MFA flag.
- suspendedboolean
Suspended people have no access: their devices lose every grant and their sessions are cut.
- quarantinedboolean
Under a security hold (see Quarantine a person).
- quarantined_atstring | null (date-time)
- quarantine_reasonstring | null
- created_atstring (date-time)
- last_seenstring | null (date-time)
Latest activity: own sign-in, any of their devices, or a browser portal session.
- last_seen_viastring | null
Where
last_seencame from:sign-in,portal, or a device name. - device_countinteger
Enrolled devices linked to this person.
- statestringrequired
active= has been seen at least once;invited= has a sign-in account but has not signed in yet;pending_approval= a self sign-up waiting for an admin. - invited_atstring | null (date-time)
Last invitation e-mail.
- invite_countinteger
Invitations sent so far.
- ad_groups_synced_atstring | null (date-time)
Last refresh of Active Directory groups for this person.
- files_securityobject | null
Protected file shares in the last 24 hours: blocked / malware / denied transfers and files waiting in quarantine. Null when nothing happened.
files_security fields
- quarantine_openinteger
- blocked_24hinteger
- malware_24hinteger
- denied_24hinteger
- lastobject | null
The latest such file event.
- viastring | null
How the person was added, e.g.
self-signup,join-link,bulk-invite,sign-in account; null when created by an admin. - requested_atstring | null (date-time)
For self sign-ups and join links: when they asked to join.
- join_link_idstring | null
The join link they used, if any.
- sign_inobject | null
How this person signs in. Null when it cannot be told yet.
sign_in fields
- methodstring
cloudraw,ad, or the identity provider type (e.g.entra). - second_factorstring | null
email_code,provider(handled by your identity provider) or null. - method_sourcestring
linked= taken from the person's own sign-in account;configured= the workspace setting (not confirmed yet). - linkedboolean | null
Only when the workspace uses its own identity provider: whether this person's account is linked to it (null = not checked yet).
- idp_linksarray of object
One row per sign-in provider configured for the workspace.
idp_links fields
- providerstring
Provider type, e.g.
entraorad. - namestring | null
- linkedboolean | null
null = not checked yet.
- linked_atstring | null (date-time)
- idp_links_checked_atstring | null (date-time)
- sign_in_conflictobject | null
More than one sign-in account uses this e-mail address; an admin must remove the extra one.
sign_in_conflict fields
- accountsinteger
- sincestring (date-time)
- phone_maskedstring | null
Phone number for SMS sign-in codes, masked.
- sms_codesboolean
The person can receive SMS sign-in codes now.
- second_factorsarray of string
Second-step methods the person has set up (cached; null = not looked up yet).
- second_factors_checked_atstring | null (date-time)
- next_pagenull
Always null: the list is not paginated.
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-role tenant-assertion-mismatch
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 tenant-not-found
tenant-not-found: No workspace with this id.
curl -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people" -Headers $headersimport os, uuid, requests
r = requests.get(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"items": [
{
"id": "pz81kd03mna",
"email": "dana.levi@example.com",
"name": "Dana Levi",
"groups": [
"g3k9d0s7aa"
],
"created_by_integrator": null,
"idp": "cloudraw",
"mfa": false,
"suspended": false,
"quarantined": false,
"quarantined_at": null,
"quarantine_reason": null,
"created_at": "2026-09-20T07:41:02.000Z",
"last_seen": "2026-10-13T09:24:11.000Z",
"last_seen_via": "DANA-LAPTOP",
"device_count": 1,
"state": "active",
"invited_at": "2026-09-20T07:41:10.000Z",
"invite_count": 1,
"ad_groups_synced_at": null,
"files_security": null,
"via": null,
"requested_at": null,
"join_link_id": null,
"sign_in": {
"method": "cloudraw",
"second_factor": "email_code",
"method_source": "linked"
},
"idp_links": [],
"idp_links_checked_at": null,
"sign_in_conflict": null,
"phone_masked": null,
"sms_codes": false,
"second_factors": [
"email_code"
],
"second_factors_checked_at": "2026-10-12T18:00:00.000Z"
}
],
"next_page": null
}Create a person
POST/v0/tenants/{tenant_id}/people
Adds a person to the workspace and takes a seat. No e-mail is sent: call Invite a person afterwards to send the sign-in invitation (or use Bulk invite, which creates and invites in one call). Group ids are stored as given; they are not checked against existing groups.
Token: full access · Created by: owner
Idempotency: send Idempotency-Key to retry safely — the same key and body within 24 h returns the first answer.
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
Headers
- Idempotency-Keystring
A unique value (e.g. a UUID) per logical operation. Retrying with the same key and body within 24 hours returns the first answer instead of doing the work twice.
Request body application/json
- emailstring (email)required
E-mail address, unique in the workspace. Up to 160 characters are kept.
- namestring | null
Display name; up to 120 characters are kept.
- groupsarray of string
Group ids (up to 100 kept).
- idpstring | null
Optional label for how the person signs in (up to 60 characters).
- mfaboolean
Admin-set MFA flag. Default false.
Responses
201 The new person.
application/json
- idstringrequired
Person id.
- emailstringrequired
E-mail address; unique in the workspace (case-insensitive).
- namestring | null
Display name.
- groupsarray of stringrequired
Ids of the groups this person belongs to. Group membership is what access rules match on.
- created_by_integratorobject | null
Set when an integrator (partner) created this person on your behalf.
created_by_integrator fields
- kindstring
- partner_idstring
- partner_namestring
- memberstring | null
- member_idstring | null
- atstring (date-time)
- idpstring | null
How the person signs in, as recorded at creation:
cloudraw(Cloudraw password + e-mail code),ad,sso, or the value you sent on create. - mfaboolean
Admin-set MFA flag.
- suspendedboolean
Suspended people have no access: their devices lose every grant and their sessions are cut.
- quarantinedboolean
Under a security hold (see Quarantine a person).
- quarantined_atstring | null (date-time)
- quarantine_reasonstring | null
- created_atstring (date-time)
- last_seenstring | null (date-time)
Latest activity: own sign-in, any of their devices, or a browser portal session.
- last_seen_viastring | null
Where
last_seencame from:sign-in,portal, or a device name. - device_countinteger
Enrolled devices linked to this person.
- statestringrequired
active= has been seen at least once;invited= has a sign-in account but has not signed in yet;pending_approval= a self sign-up waiting for an admin. - invited_atstring | null (date-time)
Last invitation e-mail.
- invite_countinteger
Invitations sent so far.
- ad_groups_synced_atstring | null (date-time)
Last refresh of Active Directory groups for this person.
- files_securityobject | null
Protected file shares in the last 24 hours: blocked / malware / denied transfers and files waiting in quarantine. Null when nothing happened.
files_security fields
- quarantine_openinteger
- blocked_24hinteger
- malware_24hinteger
- denied_24hinteger
- lastobject | null
The latest such file event.
- viastring | null
How the person was added, e.g.
self-signup,join-link,bulk-invite,sign-in account; null when created by an admin. - requested_atstring | null (date-time)
For self sign-ups and join links: when they asked to join.
- join_link_idstring | null
The join link they used, if any.
- sign_inobject | null
How this person signs in. Null when it cannot be told yet.
sign_in fields
- methodstring
cloudraw,ad, or the identity provider type (e.g.entra). - second_factorstring | null
email_code,provider(handled by your identity provider) or null. - method_sourcestring
linked= taken from the person's own sign-in account;configured= the workspace setting (not confirmed yet). - linkedboolean | null
Only when the workspace uses its own identity provider: whether this person's account is linked to it (null = not checked yet).
- idp_linksarray of object
One row per sign-in provider configured for the workspace.
idp_links fields
- providerstring
Provider type, e.g.
entraorad. - namestring | null
- linkedboolean | null
null = not checked yet.
- linked_atstring | null (date-time)
- idp_links_checked_atstring | null (date-time)
- sign_in_conflictobject | null
More than one sign-in account uses this e-mail address; an admin must remove the extra one.
sign_in_conflict fields
- accountsinteger
- sincestring (date-time)
- phone_maskedstring | null
Phone number for SMS sign-in codes, masked.
- sms_codesboolean
The person can receive SMS sign-in codes now.
- second_factorsarray of string
Second-step methods the person has set up (cached; null = not looked up yet).
- second_factors_checked_atstring | null (date-time)
400 valid-email-required groups-must-be-an-array
valid-email-required: email is missing or not an e-mail address.
groups-must-be-an-array: groups is not an array.
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 seat-quota-reached insufficient-scope insufficient-role tenant-assertion-mismatch
seat-quota-reached: All seats of the plan are taken.
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 tenant-not-found
tenant-not-found: No workspace with this id.
409 person-already-exists idempotency-key-reuse
person-already-exists: Another person already has this e-mail address.
idempotency-key-reuse: The same Idempotency-Key was used with a different body within 24 hours.
503 busy
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"email": "omer.katz@example.com",
"name": "Omer Katz",
"groups": [
"g3k9d0s7aa"
]
}'$body = @'
{
"email": "omer.katz@example.com",
"name": "Omer Katz",
"groups": [
"g3k9d0s7aa"
]
}
'@
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN"; "Idempotency-Key" = [guid]::NewGuid().ToString() }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people" -Headers $headers -ContentType "application/json" -Body $bodyimport os, uuid, requests
r = requests.post(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
json={
"email": "omer.katz@example.com",
"name": "Omer Katz",
"groups": [
"g3k9d0s7aa"
]
},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({
"email": "omer.katz@example.com",
"name": "Omer Katz",
"groups": [
"g3k9d0s7aa"
]
}),
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"id": "p4hd8s0qk2l",
"email": "omer.katz@example.com",
"name": "Omer Katz",
"groups": [
"g3k9d0s7aa"
],
"created_by_integrator": null,
"idp": null,
"mfa": false,
"suspended": false,
"quarantined": false,
"quarantined_at": null,
"quarantine_reason": null,
"created_at": "2026-10-13T09:24:11.000Z",
"last_seen": null,
"last_seen_via": null,
"device_count": 0,
"state": "not_invited",
"invited_at": null,
"invite_count": 0,
"ad_groups_synced_at": null,
"files_security": null,
"via": null,
"requested_at": null,
"join_link_id": null,
"sign_in": null,
"idp_links": [],
"idp_links_checked_at": null,
"sign_in_conflict": null,
"phone_masked": null,
"sms_codes": false,
"second_factors": null,
"second_factors_checked_at": null
}Bulk invite people
POST/v0/tenants/{tenant_id}/people:bulk-invite
Creates (or reuses) a person for each e-mail address, adds them to the given groups and sends each one the sign-in invitation. Rows are processed one by one and each gets its own outcome; one bad row does not stop the others. Existing people are added to the groups too, but are not re-invited if they are already active, suspended, waiting for approval or were invited in the last minute. In a workspace that signs in with its own identity provider people are created but no e-mail is sent (federated-sign-in). Audited.
Token: full access · Created by: owner
Rate limit: 10 bulk invites per hour per workspace (counted per clock hour).
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
Request body application/json
- emailsarray of string (email)
E-mail addresses, 1-200.
- peoplearray of object
People with optional names, 1-200 (used instead of
emails).people fields
- emailstring (email)required
- namestring
Display name for a new person.
- groupsarray of string
Group ids every row is added to; each must exist.
Responses
200 Per-row results.
application/json
- resultsarray of objectrequired
One row per input row, in order.
results fields
- emailstringrequired
- person_idstring | null
- outcomestringrequired
- countsobjectrequired
Number of rows per outcome.
400 invalid-bulk-invite
invalid-bulk-invite: No emails / people list, more than 200 rows, or an unknown group id.
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-scope insufficient-role tenant-assertion-mismatch
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 tenant-not-found
tenant-not-found: No workspace with this id.
429 too-many-bulk-invites
too-many-bulk-invites: More than 10 bulk invites this hour; retry_after_s in the body says when the hour ends.
503 busy
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people:bulk-invite" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"people": [
{
"email": "omer.katz@example.com",
"name": "Omer Katz"
},
{
"email": "noa.cohen@example.com"
}
],
"groups": [
"g3k9d0s7aa"
]
}'$body = @'
{
"people": [
{
"email": "omer.katz@example.com",
"name": "Omer Katz"
},
{
"email": "noa.cohen@example.com"
}
],
"groups": [
"g3k9d0s7aa"
]
}
'@
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people:bulk-invite" -Headers $headers -ContentType "application/json" -Body $bodyimport os, uuid, requests
r = requests.post(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people:bulk-invite",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
json={
"people": [
{
"email": "omer.katz@example.com",
"name": "Omer Katz"
},
{
"email": "noa.cohen@example.com"
}
],
"groups": [
"g3k9d0s7aa"
]
},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people:bulk-invite", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"people": [
{
"email": "omer.katz@example.com",
"name": "Omer Katz"
},
{
"email": "noa.cohen@example.com"
}
],
"groups": [
"g3k9d0s7aa"
]
}),
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"results": [
{
"email": "omer.katz@example.com",
"person_id": "p4hd8s0qk2l",
"outcome": "invited"
},
{
"email": "noa.cohen@example.com",
"person_id": null,
"outcome": "seat-quota-reached"
}
],
"counts": {
"invited": 1,
"seat-quota-reached": 1
}
}Get a person
GET/v0/tenants/{tenant_id}/people/{person_id}
Returns one person: groups, sign-in state and method, last activity, device count and security flags.
Token: read-only or full access · Created by: owner or security admin
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Responses
200 The person.
application/json
- idstringrequired
Person id.
- emailstringrequired
E-mail address; unique in the workspace (case-insensitive).
- namestring | null
Display name.
- groupsarray of stringrequired
Ids of the groups this person belongs to. Group membership is what access rules match on.
- created_by_integratorobject | null
Set when an integrator (partner) created this person on your behalf.
created_by_integrator fields
- kindstring
- partner_idstring
- partner_namestring
- memberstring | null
- member_idstring | null
- atstring (date-time)
- idpstring | null
How the person signs in, as recorded at creation:
cloudraw(Cloudraw password + e-mail code),ad,sso, or the value you sent on create. - mfaboolean
Admin-set MFA flag.
- suspendedboolean
Suspended people have no access: their devices lose every grant and their sessions are cut.
- quarantinedboolean
Under a security hold (see Quarantine a person).
- quarantined_atstring | null (date-time)
- quarantine_reasonstring | null
- created_atstring (date-time)
- last_seenstring | null (date-time)
Latest activity: own sign-in, any of their devices, or a browser portal session.
- last_seen_viastring | null
Where
last_seencame from:sign-in,portal, or a device name. - device_countinteger
Enrolled devices linked to this person.
- statestringrequired
active= has been seen at least once;invited= has a sign-in account but has not signed in yet;pending_approval= a self sign-up waiting for an admin. - invited_atstring | null (date-time)
Last invitation e-mail.
- invite_countinteger
Invitations sent so far.
- ad_groups_synced_atstring | null (date-time)
Last refresh of Active Directory groups for this person.
- files_securityobject | null
Protected file shares in the last 24 hours: blocked / malware / denied transfers and files waiting in quarantine. Null when nothing happened.
files_security fields
- quarantine_openinteger
- blocked_24hinteger
- malware_24hinteger
- denied_24hinteger
- lastobject | null
The latest such file event.
- viastring | null
How the person was added, e.g.
self-signup,join-link,bulk-invite,sign-in account; null when created by an admin. - requested_atstring | null (date-time)
For self sign-ups and join links: when they asked to join.
- join_link_idstring | null
The join link they used, if any.
- sign_inobject | null
How this person signs in. Null when it cannot be told yet.
sign_in fields
- methodstring
cloudraw,ad, or the identity provider type (e.g.entra). - second_factorstring | null
email_code,provider(handled by your identity provider) or null. - method_sourcestring
linked= taken from the person's own sign-in account;configured= the workspace setting (not confirmed yet). - linkedboolean | null
Only when the workspace uses its own identity provider: whether this person's account is linked to it (null = not checked yet).
- idp_linksarray of object
One row per sign-in provider configured for the workspace.
idp_links fields
- providerstring
Provider type, e.g.
entraorad. - namestring | null
- linkedboolean | null
null = not checked yet.
- linked_atstring | null (date-time)
- idp_links_checked_atstring | null (date-time)
- sign_in_conflictobject | null
More than one sign-in account uses this e-mail address; an admin must remove the extra one.
sign_in_conflict fields
- accountsinteger
- sincestring (date-time)
- phone_maskedstring | null
Phone number for SMS sign-in codes, masked.
- sms_codesboolean
The person can receive SMS sign-in codes now.
- second_factorsarray of string
Second-step methods the person has set up (cached; null = not looked up yet).
- second_factors_checked_atstring | null (date-time)
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-role tenant-assertion-mismatch
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
curl -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" -Headers $headersimport os, uuid, requests
r = requests.get(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"id": "pz81kd03mna",
"email": "dana.levi@example.com",
"name": "Dana Levi",
"groups": [
"g3k9d0s7aa"
],
"created_by_integrator": null,
"idp": "cloudraw",
"mfa": false,
"suspended": false,
"quarantined": false,
"quarantined_at": null,
"quarantine_reason": null,
"created_at": "2026-09-20T07:41:02.000Z",
"last_seen": "2026-10-13T09:24:11.000Z",
"last_seen_via": "DANA-LAPTOP",
"device_count": 1,
"state": "active",
"invited_at": "2026-09-20T07:41:10.000Z",
"invite_count": 1,
"ad_groups_synced_at": null,
"files_security": null,
"via": null,
"requested_at": null,
"join_link_id": null,
"sign_in": {
"method": "cloudraw",
"second_factor": "email_code",
"method_source": "linked"
},
"idp_links": [],
"idp_links_checked_at": null,
"sign_in_conflict": null,
"phone_masked": null,
"sms_codes": false,
"second_factors": [
"email_code"
],
"second_factors_checked_at": "2026-10-12T18:00:00.000Z"
}Update a person
PATCH/v0/tenants/{tenant_id}/people/{person_id}
Changes a person's name, e-mail, groups, MFA flag or suspension. Send only the fields to change. groups replaces the whole list; to add or remove single groups use Change group membership. Suspending a person immediately cuts all their device and browser sessions, ends their portal sign-ins and revokes temporary access; the answer then carries sessions_cut. Un-suspending restores access through their groups. Audited.
Token: full access · Created by: owner
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Request body application/json
- namestring
Display name; up to 120 characters are kept.
- emailstring (email)
New e-mail address (stored lower-case). This decides which sign-in account belongs to the person.
- groupsarray of string
The complete new list of group ids (up to 100 kept). Active Directory groups cannot be added or removed here.
- mfaboolean
- suspendedboolean
true = suspend (cuts every session now); false = restore.
Responses
200 The updated person.
application/json
400 valid-email-required groups-must-be-an-array
valid-email-required: email is not an e-mail address.
groups-must-be-an-array: groups is not an array.
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-scope insufficient-role tenant-assertion-mismatch
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
409 person-already-exists group-managed-elsewhere
person-already-exists: Another person already has this e-mail address.
group-managed-elsewhere: The change would add or remove an Active Directory group; those take their members from Active Directory.
503 busy
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X PATCH "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"suspended": true
}'$body = @'
{
"suspended": true
}
'@
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Patch -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" -Headers $headers -ContentType "application/json" -Body $bodyimport os, uuid, requests
r = requests.patch(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
json={
"suspended": True
},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"suspended": true
}),
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"id": "pz81kd03mna",
"email": "dana.levi@example.com",
"name": "Dana Levi",
"groups": [
"g3k9d0s7aa"
],
"created_by_integrator": null,
"idp": "cloudraw",
"mfa": false,
"suspended": true,
"quarantined": false,
"quarantined_at": null,
"quarantine_reason": null,
"created_at": "2026-09-20T07:41:02.000Z",
"last_seen": "2026-10-13T09:24:11.000Z",
"last_seen_via": "DANA-LAPTOP",
"device_count": 1,
"state": "suspended",
"invited_at": "2026-09-20T07:41:10.000Z",
"invite_count": 1,
"ad_groups_synced_at": null,
"files_security": null,
"via": null,
"requested_at": null,
"join_link_id": null,
"sign_in": {
"method": "cloudraw",
"second_factor": "email_code",
"method_source": "linked"
},
"idp_links": [],
"idp_links_checked_at": null,
"sign_in_conflict": null,
"phone_masked": null,
"sms_codes": false,
"second_factors": [
"email_code"
],
"second_factors_checked_at": "2026-10-12T18:00:00.000Z",
"sessions_cut": 2
}Delete a person
DELETE/v0/tenants/{tenant_id}/people/{person_id}
Removes the person and frees their seat. Their devices stay enrolled but lose every grant at once, their location history is deleted, and their Cloudraw sign-in account (if any) is deleted too, so they cannot sign in again unless re-invited. Deleting a person who is waiting for approval rejects their sign-up; no e-mail is sent. Audited. The work is done when the call returns: the task is already done.
Token: full access · Created by: owner
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Responses
202 Deleted. The task is already in state done. signin_account says what happened to the person's Cloudraw sign-in account; idp_links_removed whether its identity-provider links are gone.
application/json
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-scope insufficient-role tenant-assertion-mismatch
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
503 busy
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X DELETE "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Delete -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" -Headers $headersimport os, uuid, requests
r = requests.delete(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
timeout=30,
)
r.raise_for_status()
print(r.status_code)const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(res.status);{
"id": "task_8k2m0x9s1d",
"tenant_id": "tq7x2m9k4ab",
"state": "done",
"result_uri": null,
"error": null,
"signin_account": "deleted",
"idp_links_removed": true
}Get a person's effective access
GET/v0/tenants/{tenant_id}/people/{person_id}/access
Explains what a person can reach right now. For each of their enrolled devices it lists the apps and private networks granted (and by which access rule), and the ones a rule would grant through their groups but a device condition blocks (missing posture, untrusted device, suspended person). It also lists the browser portal apps they see and why others are hidden. Computed at call time; nothing is changed.
Token: read-only or full access · Created by: owner or security admin
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Responses
200 Effective access.
application/json
- person_idstringrequired
- suspendedboolean
- groupsarray of string
- devicesarray of objectrequired
devices fields
- device_idstring
- device_namestring | null
- truststring
Device trust right now.
- quarantinedboolean
- posture_freshnessstring
Whether the device's last posture report is recent.
- grantedarray of object
What this device can reach now, and the access rule that grants it.
granted fields
- kindstring
- idstring
- namestring | null
- granted_byobject
granted_by fields
- rule_idstring
- rule_namestring
- blockedarray of object
What a rule would grant through the person's groups but a device condition blocks.
blocked fields
- kindstring
- idstring
- namestring | null
- ruleobject
rule fields
- rule_idstring
- rule_namestring
- missing_posturearray of string
Posture profiles the device does not meet.
- needs_trusted_deviceboolean
- person_suspendedboolean
- portalobjectrequired
portal fields
- tilesarray of object
Browser portal apps the person sees.
tiles fields
- idstring
- namestring
- granted_byobject
granted_by fields
- rule_idstring
- rule_namestring
- hiddenarray of object
hidden fields
- idstring
- namestring
- reasonstring
Why the app is not shown, in plain English.
- lockedobject | null
Set when the app is shown locked (allowed, but not from a browser): what is needed.
- evaluated_atstring (date-time)required
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-role tenant-assertion-mismatch
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
curl -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/access" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/access" -Headers $headersimport os, uuid, requests
r = requests.get(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/access",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/access", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"person_id": "pz81kd03mna",
"suspended": false,
"groups": [
"g3k9d0s7aa"
],
"devices": [
{
"device_id": "dvc_5mxq2b7r8k",
"device_name": "DANA-LAPTOP",
"trust": "trusted",
"quarantined": false,
"posture_freshness": "fresh",
"granted": [
{
"kind": "connection",
"id": "cx9m2v7d1pa",
"name": "Finance ERP",
"granted_by": {
"rule_id": "pr_7xk2m9c0d1",
"rule_name": "Finance to ERP"
}
}
],
"blocked": [
{
"kind": "private_network",
"id": "pn_6b2x9q0wea",
"name": "Office LAN",
"rule": {
"rule_id": "pr_2m9x0k8d1s",
"rule_name": "Finance to office LAN"
},
"missing_posture": [
"pp_3k8x0s2m1d"
],
"needs_trusted_device": false,
"person_suspended": false
}
]
}
],
"portal": {
"tiles": [
{
"id": "pa_4k8x2m0s9d",
"name": "Finance ERP",
"granted_by": {
"rule_id": "pr_7xk2m9c0d1",
"rule_name": "Finance to ERP"
}
}
],
"hidden": [
{
"id": "pa_9d2k0s8x1m",
"name": "File server",
"reason": "browser access (clientless) is off for this app",
"locked": {
"reason": "browser-off",
"requires": []
}
}
]
},
"evaluated_at": "2026-10-13T09:24:11.000Z"
}Change group membership
PATCH/v0/tenants/{tenant_id}/people/{person_id}/groups
Adds the person to and removes them from groups without sending the whole list. Their devices' access is recalculated at once. Group ids are not checked against existing groups. Active Directory groups take their members from Active Directory and cannot be changed here. Audited.
Token: full access · Created by: owner
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Request body application/json
- addarray of string
Group ids to add.
- removearray of string
Group ids to remove.
Responses
200 The person with the new groups.
application/json
- idstringrequired
Person id.
- emailstringrequired
E-mail address; unique in the workspace (case-insensitive).
- namestring | null
Display name.
- groupsarray of stringrequired
Ids of the groups this person belongs to. Group membership is what access rules match on.
- created_by_integratorobject | null
Set when an integrator (partner) created this person on your behalf.
created_by_integrator fields
- kindstring
- partner_idstring
- partner_namestring
- memberstring | null
- member_idstring | null
- atstring (date-time)
- idpstring | null
How the person signs in, as recorded at creation:
cloudraw(Cloudraw password + e-mail code),ad,sso, or the value you sent on create. - mfaboolean
Admin-set MFA flag.
- suspendedboolean
Suspended people have no access: their devices lose every grant and their sessions are cut.
- quarantinedboolean
Under a security hold (see Quarantine a person).
- quarantined_atstring | null (date-time)
- quarantine_reasonstring | null
- created_atstring (date-time)
- last_seenstring | null (date-time)
Latest activity: own sign-in, any of their devices, or a browser portal session.
- last_seen_viastring | null
Where
last_seencame from:sign-in,portal, or a device name. - device_countinteger
Enrolled devices linked to this person.
- statestringrequired
active= has been seen at least once;invited= has a sign-in account but has not signed in yet;pending_approval= a self sign-up waiting for an admin. - invited_atstring | null (date-time)
Last invitation e-mail.
- invite_countinteger
Invitations sent so far.
- ad_groups_synced_atstring | null (date-time)
Last refresh of Active Directory groups for this person.
- files_securityobject | null
Protected file shares in the last 24 hours: blocked / malware / denied transfers and files waiting in quarantine. Null when nothing happened.
files_security fields
- quarantine_openinteger
- blocked_24hinteger
- malware_24hinteger
- denied_24hinteger
- lastobject | null
The latest such file event.
- viastring | null
How the person was added, e.g.
self-signup,join-link,bulk-invite,sign-in account; null when created by an admin. - requested_atstring | null (date-time)
For self sign-ups and join links: when they asked to join.
- join_link_idstring | null
The join link they used, if any.
- sign_inobject | null
How this person signs in. Null when it cannot be told yet.
sign_in fields
- methodstring
cloudraw,ad, or the identity provider type (e.g.entra). - second_factorstring | null
email_code,provider(handled by your identity provider) or null. - method_sourcestring
linked= taken from the person's own sign-in account;configured= the workspace setting (not confirmed yet). - linkedboolean | null
Only when the workspace uses its own identity provider: whether this person's account is linked to it (null = not checked yet).
- idp_linksarray of object
One row per sign-in provider configured for the workspace.
idp_links fields
- providerstring
Provider type, e.g.
entraorad. - namestring | null
- linkedboolean | null
null = not checked yet.
- linked_atstring | null (date-time)
- idp_links_checked_atstring | null (date-time)
- sign_in_conflictobject | null
More than one sign-in account uses this e-mail address; an admin must remove the extra one.
sign_in_conflict fields
- accountsinteger
- sincestring (date-time)
- phone_maskedstring | null
Phone number for SMS sign-in codes, masked.
- sms_codesboolean
The person can receive SMS sign-in codes now.
- second_factorsarray of string
Second-step methods the person has set up (cached; null = not looked up yet).
- second_factors_checked_atstring | null (date-time)
400 add-or-remove-required
add-or-remove-required: Both add and remove are empty or missing.
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-scope insufficient-role tenant-assertion-mismatch
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
409 group-managed-elsewhere
group-managed-elsewhere: One of the groups is an Active Directory group.
503 busy
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X PATCH "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/groups" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"add": [
"g3k9d0s7aa"
],
"remove": [
"g8s2k0d9xm"
]
}'$body = @'
{
"add": [
"g3k9d0s7aa"
],
"remove": [
"g8s2k0d9xm"
]
}
'@
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Patch -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/groups" -Headers $headers -ContentType "application/json" -Body $bodyimport os, uuid, requests
r = requests.patch(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/groups",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
json={
"add": [
"g3k9d0s7aa"
],
"remove": [
"g8s2k0d9xm"
]
},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/groups", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"add": [
"g3k9d0s7aa"
],
"remove": [
"g8s2k0d9xm"
]
}),
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"id": "pz81kd03mna",
"email": "dana.levi@example.com",
"name": "Dana Levi",
"groups": [
"g3k9d0s7aa"
],
"created_by_integrator": null,
"idp": "cloudraw",
"mfa": false,
"suspended": false,
"quarantined": false,
"quarantined_at": null,
"quarantine_reason": null,
"created_at": "2026-09-20T07:41:02.000Z",
"last_seen": "2026-10-13T09:24:11.000Z",
"last_seen_via": "DANA-LAPTOP",
"device_count": 1,
"state": "active",
"invited_at": "2026-09-20T07:41:10.000Z",
"invite_count": 1,
"ad_groups_synced_at": null,
"files_security": null,
"via": null,
"requested_at": null,
"join_link_id": null,
"sign_in": {
"method": "cloudraw",
"second_factor": "email_code",
"method_source": "linked"
},
"idp_links": [],
"idp_links_checked_at": null,
"sign_in_conflict": null,
"phone_masked": null,
"sms_codes": false,
"second_factors": [
"email_code"
],
"second_factors_checked_at": "2026-10-12T18:00:00.000Z"
}Invite a person
POST/v0/tenants/{tenant_id}/people/{person_id}/invite
Sends (or re-sends) the sign-in invitation. Cloudraw creates the person's sign-in account if needed (or reuses the one with their e-mail), sets an e-mail code as their second step, and e-mails a branded "set your password" link together with the Cloudraw Connect download. A re-invite also lifts a sign-in lockout. Not available when the workspace signs in with its own identity provider: people then use their existing account. Audited.
Token: full access · Created by: owner
Rate limit: One invitation per person per minute.
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Responses
202 The invitation was sent.
application/json
- person_idstringrequired
- emailstring
- statestringrequired
- invited_atstring (date-time)
- invite_countinteger
- sign_inobject
sign_in fields
- methodstring
- second_factorstring
400 email-required
email-required: The person has no valid e-mail address.
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-scope insufficient-role tenant-assertion-mismatch
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
409 person-suspended federated-sign-in sign-in-conflict
person-suspended: The person is suspended; un-suspend them first.
federated-sign-in: The workspace signs in with its own identity provider; no invitation is needed.
sign-in-conflict: Several sign-in accounts in the workspace use this e-mail address; remove the extra one first. Nothing was sent.
429 invite-rate-limited
invite-rate-limited: An invitation was sent to this person less than a minute ago. Wait Retry-After seconds.
502 invite-failed
invite-failed: The invitation could not be sent right now; nothing was changed. Retry.
503 sso-not-configured busy
sso-not-configured: Sign-in is not available on the platform right now.
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/invite" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/invite" -Headers $headersimport os, uuid, requests
r = requests.post(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/invite",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/invite", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"person_id": "p4hd8s0qk2l",
"email": "omer.katz@example.com",
"state": "invited",
"invited_at": "2026-10-13T09:24:11.000Z",
"invite_count": 1,
"sign_in": {
"method": "cloudraw",
"second_factor": "email_code"
}
}Sign a person out of the browser portal
POST/v0/tenants/{tenant_id}/people/{person_id}/portal-signout
Ends the person's browser portal sign-ins everywhere and cuts their open browser app sessions. They can sign in again right away; to keep them out, suspend or quarantine them instead. Device (Cloudraw Connect) sessions are not affected. Audited.
Token: full access · Created by: owner
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Responses
200 What was ended.
application/json
- person_idstringrequired
- portal_sessions_endedintegerrequired
Browser portal sign-ins that were ended.
- browser_sessions_cutintegerrequired
Open browser app sessions that were cut.
- overlaystring
unavailable= open browser sessions could not be checked right now (portal sign-ins were still ended).
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-scope insufficient-role tenant-assertion-mismatch
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
503 busy
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/portal-signout" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/portal-signout" -Headers $headersimport os, uuid, requests
r = requests.post(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/portal-signout",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/portal-signout", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"person_id": "pz81kd03mna",
"portal_sessions_ended": 1,
"browser_sessions_cut": 1,
"overlay": "ok"
}Quarantine a person
POST/v0/tenants/{tenant_id}/people/{person_id}/quarantine
Puts the person under a security hold: they are suspended, every device and browser session is cut, portal sign-ins end and temporary access is revoked, until you release them. Unlike a plain suspension it records when and why, and raises a security alert in the workspace. Calling it again on a quarantined person updates the time and reason. Audited.
Token: full access · Created by: owner
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Request body application/json
- reasonstring
Why; shown in the console and the alert. Up to 300 characters are kept.
Responses
200 The quarantined person.
application/json
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-scope insufficient-role tenant-assertion-mismatch
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
503 busy
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "Credentials reported as phished"
}'$body = @'
{
"reason": "Credentials reported as phished"
}
'@
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine" -Headers $headers -ContentType "application/json" -Body $bodyimport os, uuid, requests
r = requests.post(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
json={
"reason": "Credentials reported as phished"
},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"reason": "Credentials reported as phished"
}),
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"id": "pz81kd03mna",
"email": "dana.levi@example.com",
"name": "Dana Levi",
"groups": [
"g3k9d0s7aa"
],
"created_by_integrator": null,
"idp": "cloudraw",
"mfa": false,
"suspended": true,
"quarantined": true,
"quarantined_at": "2026-10-13T09:24:11.000Z",
"quarantine_reason": "Credentials reported as phished",
"created_at": "2026-09-20T07:41:02.000Z",
"last_seen": "2026-10-13T09:24:11.000Z",
"last_seen_via": "DANA-LAPTOP",
"device_count": 1,
"state": "suspended",
"invited_at": "2026-09-20T07:41:10.000Z",
"invite_count": 1,
"ad_groups_synced_at": null,
"files_security": null,
"via": null,
"requested_at": null,
"join_link_id": null,
"sign_in": {
"method": "cloudraw",
"second_factor": "email_code",
"method_source": "linked"
},
"idp_links": [],
"idp_links_checked_at": null,
"sign_in_conflict": null,
"phone_masked": null,
"sms_codes": false,
"second_factors": [
"email_code"
],
"second_factors_checked_at": "2026-10-12T18:00:00.000Z",
"sessions_cut": 3
}Release a person from quarantine
DELETE/v0/tenants/{tenant_id}/people/{person_id}/quarantine
Ends the security hold and restores the person's access through their groups. Note: releasing also clears the suspension, even if the person was suspended before the quarantine. Audited.
Token: full access · Created by: owner
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Responses
200 The released person.
application/json
- idstringrequired
Person id.
- emailstringrequired
E-mail address; unique in the workspace (case-insensitive).
- namestring | null
Display name.
- groupsarray of stringrequired
Ids of the groups this person belongs to. Group membership is what access rules match on.
- created_by_integratorobject | null
Set when an integrator (partner) created this person on your behalf.
created_by_integrator fields
- kindstring
- partner_idstring
- partner_namestring
- memberstring | null
- member_idstring | null
- atstring (date-time)
- idpstring | null
How the person signs in, as recorded at creation:
cloudraw(Cloudraw password + e-mail code),ad,sso, or the value you sent on create. - mfaboolean
Admin-set MFA flag.
- suspendedboolean
Suspended people have no access: their devices lose every grant and their sessions are cut.
- quarantinedboolean
Under a security hold (see Quarantine a person).
- quarantined_atstring | null (date-time)
- quarantine_reasonstring | null
- created_atstring (date-time)
- last_seenstring | null (date-time)
Latest activity: own sign-in, any of their devices, or a browser portal session.
- last_seen_viastring | null
Where
last_seencame from:sign-in,portal, or a device name. - device_countinteger
Enrolled devices linked to this person.
- statestringrequired
active= has been seen at least once;invited= has a sign-in account but has not signed in yet;pending_approval= a self sign-up waiting for an admin. - invited_atstring | null (date-time)
Last invitation e-mail.
- invite_countinteger
Invitations sent so far.
- ad_groups_synced_atstring | null (date-time)
Last refresh of Active Directory groups for this person.
- files_securityobject | null
Protected file shares in the last 24 hours: blocked / malware / denied transfers and files waiting in quarantine. Null when nothing happened.
files_security fields
- quarantine_openinteger
- blocked_24hinteger
- malware_24hinteger
- denied_24hinteger
- lastobject | null
The latest such file event.
- viastring | null
How the person was added, e.g.
self-signup,join-link,bulk-invite,sign-in account; null when created by an admin. - requested_atstring | null (date-time)
For self sign-ups and join links: when they asked to join.
- join_link_idstring | null
The join link they used, if any.
- sign_inobject | null
How this person signs in. Null when it cannot be told yet.
sign_in fields
- methodstring
cloudraw,ad, or the identity provider type (e.g.entra). - second_factorstring | null
email_code,provider(handled by your identity provider) or null. - method_sourcestring
linked= taken from the person's own sign-in account;configured= the workspace setting (not confirmed yet). - linkedboolean | null
Only when the workspace uses its own identity provider: whether this person's account is linked to it (null = not checked yet).
- idp_linksarray of object
One row per sign-in provider configured for the workspace.
idp_links fields
- providerstring
Provider type, e.g.
entraorad. - namestring | null
- linkedboolean | null
null = not checked yet.
- linked_atstring | null (date-time)
- idp_links_checked_atstring | null (date-time)
- sign_in_conflictobject | null
More than one sign-in account uses this e-mail address; an admin must remove the extra one.
sign_in_conflict fields
- accountsinteger
- sincestring (date-time)
- phone_maskedstring | null
Phone number for SMS sign-in codes, masked.
- sms_codesboolean
The person can receive SMS sign-in codes now.
- second_factorsarray of string
Second-step methods the person has set up (cached; null = not looked up yet).
- second_factors_checked_atstring | null (date-time)
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-scope insufficient-role tenant-assertion-mismatch
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
409 person-not-quarantined
person-not-quarantined: The person is not quarantined.
503 busy
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X DELETE "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Delete -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine" -Headers $headersimport os, uuid, requests
r = requests.delete(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
timeout=30,
)
r.raise_for_status()
print(r.status_code)const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(res.status);{
"id": "pz81kd03mna",
"email": "dana.levi@example.com",
"name": "Dana Levi",
"groups": [
"g3k9d0s7aa"
],
"created_by_integrator": null,
"idp": "cloudraw",
"mfa": false,
"suspended": false,
"quarantined": false,
"quarantined_at": null,
"quarantine_reason": null,
"created_at": "2026-09-20T07:41:02.000Z",
"last_seen": "2026-10-13T09:24:11.000Z",
"last_seen_via": "DANA-LAPTOP",
"device_count": 1,
"state": "active",
"invited_at": "2026-09-20T07:41:10.000Z",
"invite_count": 1,
"ad_groups_synced_at": null,
"files_security": null,
"via": null,
"requested_at": null,
"join_link_id": null,
"sign_in": {
"method": "cloudraw",
"second_factor": "email_code",
"method_source": "linked"
},
"idp_links": [],
"idp_links_checked_at": null,
"sign_in_conflict": null,
"phone_masked": null,
"sms_codes": false,
"second_factors": [
"email_code"
],
"second_factors_checked_at": "2026-10-12T18:00:00.000Z"
}Unlock a person's sign-in
POST/v0/tenants/{tenant_id}/people/{person_id}/unlock
Lifts a sign-in lockout (too many wrong codes or passwords) without sending a new invitation. Only for people with a Cloudraw sign-in account; people who sign in through your directory or identity provider are unlocked there. Audited.
Token: full access · Created by: owner
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
- person_idstringrequired
Person id (from List people).
Responses
200 Unlocked.
application/json
- idstringrequired
Person id.
- unlockedbooleanrequired
- was_lockedboolean
False when the sign-in was not locked to begin with.
401 unauthorized invalid-token token-expired
unauthorized: No Authorization: Bearer crw_… header was sent.
invalid-token: The token is unknown or was revoked.
token-expired: The token is past its expiry date. Create a new one.
403 insufficient-scope insufficient-role tenant-assertion-mismatch
insufficient-scope: The token is read-only and this call changes something.
insufficient-role: The token's role ceiling does not allow this call.
tenant-assertion-mismatch: The token belongs to another workspace than {tenant_id}.
404 person-not-found tenant-not-found
person-not-found: No person with this id in the workspace.
tenant-not-found: No workspace with this id.
409 no-cloudraw-sign-in
no-cloudraw-sign-in: The person has no Cloudraw sign-in account (they sign in with your directory or identity provider).
502 unlock-failed
unlock-failed: The sign-in service could not unlock the account right now. Retry in a minute.
503 busy
busy: Cloudraw is switching servers or cannot save right now. Retry after Retry-After seconds.
curl -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/unlock" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/unlock" -Headers $headersimport os, uuid, requests
r = requests.post(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/unlock",
headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
timeout=30,
)
r.raise_for_status()
print(r.json())const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/unlock", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"id": "pz81kd03mna",
"unlocked": true,
"was_locked": true
}