CloudrawAPI v0
Menu

API reference

People

The people who may use Cloudraw: invite, update, suspend, quarantine and remove them.

List people

GET/v0/tenants/{tenant_id}/people

read-only token

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).

    Example: tq7x2m9k4ab

Query parameters

  • groupstring

    Only members of this group id.

    Example: g3k9d0s7aa

  • qstring

    Case-insensitive text search in e-mail and name.

    Example: dana

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_seen came 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.

      One of: pending_approval, suspended, active, invited, not_invited.

    • 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).

        One of: linked, configured.

      • 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. entra or ad.

      • 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).

      One of: email_code, sms_code, authenticator_app, security_key, passkey.

    • 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
curl -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people" -Headers $headers
Python
import 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())
Node.js
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());
Response 200 · application/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

full-access tokenidempotent

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).

    Example: tq7x2m9k4ab

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.

    Example: 6f1c2b9e-3d4a-4c1e-9b8f-0a7d5e2c1b3f

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_seen came 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.

    One of: pending_approval, suspended, active, invited, not_invited.

  • 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).

      One of: linked, configured.

    • 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. entra or ad.

    • 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).

    One of: email_code, sms_code, authenticator_app, security_key, passkey.

  • 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
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"
  ]
}'
PowerShell
$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 $body
Python
import 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())
Node.js
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());
Response 201 · application/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

full-access tokenrate limited

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).

    Example: tq7x2m9k4ab

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

      One of: invited, invalid-email, duplicate, seat-quota-reached, pending-approval, suspended, already-active, recently-invited, federated-sign-in, failed.

  • 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
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"
  ]
}'
PowerShell
$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 $body
Python
import 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())
Node.js
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());
Response 200 · application/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}

read-only token

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

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_seen came 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.

    One of: pending_approval, suspended, active, invited, not_invited.

  • 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).

      One of: linked, configured.

    • 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. entra or ad.

    • 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).

    One of: email_code, sms_code, authenticator_app, security_key, passkey.

  • 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
curl -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" -Headers $headers
Python
import 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())
Node.js
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());
Response 200 · application/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}

full-access token

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

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
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
}'
PowerShell
$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 $body
Python
import 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())
Node.js
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());
Response 200 · application/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}

full-access token

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

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
curl -sS -X DELETE "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Delete -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna" -Headers $headers
Python
import 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)
Node.js
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);
Response 202 · application/json
{
  "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

read-only token

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

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.

      One of: trusted, untrusted.

    • quarantinedboolean
    • posture_freshnessstring

      Whether the device's last posture report is recent.

      One of: fresh, stale, none.

    • grantedarray of object

      What this device can reach now, and the access rule that grants it.

      granted fields
      • kindstring

        One of: connection, private_network.

      • 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

        One of: connection, private_network.

      • 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
curl -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/access" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/access" -Headers $headers
Python
import 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())
Node.js
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());
Response 200 · application/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

full-access token

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

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_seen came 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.

    One of: pending_approval, suspended, active, invited, not_invited.

  • 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).

      One of: linked, configured.

    • 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. entra or ad.

    • 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).

    One of: email_code, sms_code, authenticator_app, security_key, passkey.

  • 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
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"
  ]
}'
PowerShell
$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 $body
Python
import 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())
Node.js
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());
Response 200 · application/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

full-access tokenrate limited

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

Responses

202 The invitation was sent.

application/json

  • person_idstringrequired
  • emailstring
  • statestringrequired

    One of: invited.

  • 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
curl -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/invite" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/invite" -Headers $headers
Python
import 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())
Node.js
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());
Response 202 · application/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

full-access token

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

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).

    One of: ok, unavailable.

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
curl -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/portal-signout" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/portal-signout" -Headers $headers
Python
import 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())
Node.js
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());
Response 200 · application/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

full-access token

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

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
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"
}'
PowerShell
$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 $body
Python
import 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())
Node.js
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());
Response 200 · application/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

full-access token

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

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_seen came 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.

    One of: pending_approval, suspended, active, invited, not_invited.

  • 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).

      One of: linked, configured.

    • 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. entra or ad.

    • 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).

    One of: email_code, sms_code, authenticator_app, security_key, passkey.

  • 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
curl -sS -X DELETE "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Delete -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/quarantine" -Headers $headers
Python
import 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)
Node.js
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);
Response 200 · application/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"
}

Unlock a person's sign-in

POST/v0/tenants/{tenant_id}/people/{person_id}/unlock

full-access token

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).

    Example: tq7x2m9k4ab

  • person_idstringrequired

    Person id (from List people).

    Example: pz81kd03mna

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
curl -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/unlock" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/people/pz81kd03mna/unlock" -Headers $headers
Python
import 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())
Node.js
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());
Response 200 · application/json
{
  "id": "pz81kd03mna",
  "unlocked": true,
  "was_locked": true
}