CloudrawAPI v0
Menu

API reference

Devices

Computers and phones running Cloudraw Connect: health, trust, quarantine.

List devices

GET/v0/tenants/{tenant_id}/devices

read-only token

Returns every device in the workspace with its owner, live status, trust decision, health and whether it can reach anything right now (access / blocked_by). Live status is read fresh on each call, so the answer can take a few seconds; when it cannot be read, status_known is false and the last known values are returned. Public IPs are always masked.

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

Responses

200 All devices (not paginated).

application/json

  • itemsarray of Devicerequired
    items fields
    • idstringrequired

      Device id.

    • namestringrequired

      Device name in the workspace (lowercase, - separated).

    • short_idstring

      Last 6 characters of the id, for display.

    • identity_idstring | null

      Id of the device's network identity.

    • osstring | null

      Operating system label, e.g. "Windows 11 Pro".

    • os_namestring | null
    • os_versionstring | null
    • hostnamestring | null

      Computer name reported by the device (kept while offline).

    • client_appstring | null

      Client app name, normally "Cloudraw Connect".

    • public_ip_maskedstring | null

      Last public IP seen from the device, masked. The full address is only shown in the console (audited).

    • public_ip_versioninteger | null

      One of: 4, 6, .

    • public_ip_atstring | null (date-time)
    • public_ip_sourcestring | null
    • hostname_sharedboolean

      Another enrolled device or connector reports the same computer name (e.g. cloned machines).

    • hostname_shared_witharray of object
      hostname_shared_with fields
      • kindstring

        One of: device, connector.

      • idstring
      • short_idstring
      • namestring | null
    • person_idstring | null

      Person the device belongs to.

    • person_namestring | null
    • created_by_integratorobject | null

      Set when an integrator (partner) you approved created this record from its own account; null otherwise.

      created_by_integrator fields
      • kindstring

        Always partner.

      • partner_idstring
      • partner_namestring
      • memberstring | null

        Which of the integrator's staff.

      • member_idstring | null
      • atstring (date-time)
    • onlinebooleanrequired

      Connected right now.

    • status_knownboolean

      false = Cloudraw could not read the live status just now; online and last_seen are the last known values.

    • last_seenstring | null (date-time)
    • accessstringrequired

      Can this device reach anything right now?

      One of: allowed, blocked.

    • blocked_bystring | null

      Why it is blocked; null when allowed.

      One of: quarantine, admin, sign_in_required, trust_rules, person_deleted, person_suspended, .

    • quarantinedboolean
    • quarantined_atstring | null (date-time)
    • quarantine_reasonstring | null
    • trustobjectrequired
      trust fields
      • statestringrequired

        Trust decision right now.

        One of: trusted, untrusted.

      • reasonstring

        Plain-English reason for the decision.

      • unmetarray of DeviceTrustUnmet

        What keeps the device from being trusted (empty when trusted or when no rule applies).

        unmet fields
        • kindstringrequired

          posture, group, person, device, network, reauth …

        • fieldstring | null

          The condition field, e.g. disk_encrypted, country, last_auth_at.

        • opstring | null
        • valueany

          What the rule wants.

        • gotany

          What the device reported (null = not reported).

        • textstringrequired

          Plain-English explanation, safe to show to the device user.

      • evaluated_atstring (date-time)

        When this decision was computed (now).

      • sourcestringrequired

        default = the workspace has no trust rules yet; manual = set by an admin; rule = your trust rules; policy = a workspace policy (sign-in required, person suspended).

        One of: default, manual, rule, policy.

      • manualstring | null

        One of: trusted, untrusted, .

    • healthDeviceHealth
      health fields
      • statestringrequired

        One of: not_reported, ok, requirements_not_met, stale.

      • summarystringrequired

        One line for people, e.g. "Meets all 3 required checks".

      • staleboolean
      • requirementsarray of object

        Checks that YOUR trust and access rules require of this device.

        requirements fields
        • fieldstring
        • labelstring
        • expectedboolean
        • metboolean
        • textstring | null
      • recommendationsarray of object

        Good-practice checks that fail but no rule requires.

        recommendations fields
        • fieldstring
        • labelstring
        • textstring
      • factsarray of object

        Plain facts (domain joined, MDM enrolled …).

        facts fields
        • fieldstring
        • labelstring
        • valueboolean
      • reported_atstring | null (date-time)
    • postureone of
    • bitlockerobject | null

      BitLocker readiness reported by the device (status PASS | WARN | ROADBLOCK, findings with fix text, stale flag). Advice only, never an access decision. Null until reported.

    • web_filterobject | null

      Web filter state reported by Cloudraw Connect (0.4.12+): state on | off | paused_multi_workspace | unknown, enabled, multi_workspace, reason, message (plain text when paused), counters blocked monitored warned requests, received_at. paused_multi_workspace = the device is in more than one Cloudraw workspace, so web filtering is paused on it. Null until reported.

    • app_firewallobject
      app_firewall fields
      • capableboolean

        The device runs a Cloudraw Connect version that enforces allowed applications.

      • client_versionstring | null
    • connectobject
      connect fields
      • versionstring | null

        Cloudraw Connect app version.

      • lateststring

        Latest published version.

      • update_availableboolean | null
      • reportedboolean
    • connect_versionstring | null

      Cloudraw Connect app version from its own health report (same as connect.version); null = never reported. Not inventory.client_version (that is the tunnel).

    • connect_version_reported_atstring | null (date-time)

      When Cloudraw received the health report that carried connect_version (null with it).

    • inventoryobject
      inventory fields
      • client_versionstring | null
      • hostnamestring | null
      • osstring | null
      • os_versionstring | null
    • remote_assistobject

      Remote assistance availability for this device.

      remote_assist fields
      • availableboolean
      • eligibleboolean
      • modesarray of string
      • reasonstring | null
    • statestring

      Always approved.

    • created_atstring | null (date-time)
    • enrolled_atstring | null (date-time)

      When the device first joined.

    • enrollment_usedboolean

      The device ever came up (enrolled, seen online or reported).

    • created_viastring

      How the device was added.

      One of: admin-enrolment, sign-in, fleet-token.

    • enrolled_byobject | null
      enrolled_by fields
      • kindstring

        One of: admin, fleet_token, person.

      • idstring | null
      • labelstring
    • deliverystring | null

      Enrollment method: sso (sign-in), provision (fleet token), or what the admin chose at creation (token, code, qr, email).

    • last_auth_atstring | null (date-time)

      Last time the device's person signed in on it (sign-in enrolled devices).

    • last_resource_sync_atstring | null (date-time)
    • sync_requestedboolean
  • next_pagenull

    Always null: the list is bounded by the device quota and returned whole.

  • connect_lateststring

    Latest published Cloudraw Connect version.

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/devices" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices" -Headers $headers
Python
import os, uuid, requests

r = requests.get(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices",
    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/devices", {
  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": "dvc_5mxq2b7r8k",
      "name": "dana-laptop",
      "short_id": "2b7r8k",
      "identity_id": "Xk3m9PqR2",
      "os": "Windows 11 Pro",
      "os_name": "Windows",
      "os_version": "Windows 11 Pro",
      "hostname": "NW-LT-0142",
      "client_app": "Cloudraw Connect",
      "public_ip_masked": "203.0.113.x",
      "public_ip_version": 4,
      "public_ip_at": "2026-10-13T09:15:02.000Z",
      "public_ip_source": "device-api",
      "hostname_shared": false,
      "hostname_shared_with": [],
      "person_id": "pz81kd03mna",
      "person_name": "Dana Levi",
      "created_by_integrator": null,
      "online": true,
      "status_known": true,
      "last_seen": "2026-10-13T09:24:11.000Z",
      "access": "allowed",
      "blocked_by": null,
      "quarantined": false,
      "quarantined_at": null,
      "quarantine_reason": null,
      "trust": {
        "state": "trusted",
        "reason": "matched trust rule \"Managed laptops\"",
        "unmet": [],
        "evaluated_at": "2026-10-13T09:24:11.000Z",
        "source": "rule",
        "manual": null
      },
      "health": {
        "state": "ok",
        "summary": "Meets all 2 required checks",
        "stale": false,
        "requirements": [
          {
            "field": "disk_encrypted",
            "label": "Disk encrypted",
            "expected": true,
            "met": true,
            "text": null
          },
          {
            "field": "firewall_on",
            "label": "Firewall on",
            "expected": true,
            "met": true,
            "text": null
          }
        ],
        "recommendations": [],
        "facts": [
          {
            "field": "domain_joined",
            "label": "Joined to a domain",
            "value": true
          }
        ],
        "reported_at": "2026-10-13T09:15:02.000Z"
      },
      "posture": {
        "compliant": true,
        "checks": {
          "disk_encrypted": true,
          "antivirus_present": true,
          "antivirus_on": true,
          "firewall_on": true,
          "os_up_to_date": true,
          "screen_lock": true,
          "domain_joined": true,
          "workgroup": false,
          "managed": true
        },
        "evaluated_at": "2026-10-13T09:15:02.000Z",
        "source": "device",
        "client_version": "0.4.7",
        "freshness": "fresh",
        "age_s": 549
      },
      "bitlocker": null,
      "web_filter": null,
      "app_firewall": {
        "capable": true,
        "client_version": "0.4.7"
      },
      "connect": {
        "version": "0.4.7",
        "latest": "0.4.7",
        "update_available": false,
        "reported": true
      },
      "connect_version": "0.4.7",
      "connect_version_reported_at": "2026-10-13T08:40:02.000Z",
      "inventory": {
        "client_version": "1.2.4",
        "hostname": "NW-LT-0142",
        "os": "Windows",
        "os_version": "Windows 11 Pro"
      },
      "remote_assist": {
        "available": false,
        "eligible": false,
        "modes": [],
        "reason": "not_available"
      },
      "state": "approved",
      "created_at": "2026-09-20T07:41:00.000Z",
      "enrolled_at": "2026-09-20T07:44:12.000Z",
      "enrollment_used": true,
      "created_via": "sign-in",
      "enrolled_by": {
        "kind": "person",
        "id": "pz81kd03mna",
        "label": "dana.levi@example.com"
      },
      "delivery": "sso",
      "last_auth_at": "2026-10-13T06:58:40.000Z",
      "last_resource_sync_at": "2026-10-13T09:20:00.000Z",
      "sync_requested": false
    }
  ],
  "next_page": null,
  "connect_latest": "0.4.7"
}

Assign a device to a person

PATCH/v0/tenants/{tenant_id}/devices/{device_id}

full-access token

Sets (or clears, with null) the person a device belongs to. The device's group-based access follows immediately: rules granted to the person's groups apply on the next connection. 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

  • device_idstringrequired

    Device id (from GET /devices). A device keeps the id of the enrollment that created it.

    Example: dvc_5mxq2b7r8k

Request body application/json

  • person_idstring | nullrequired

    Person id, or null to detach the device from its person.

Responses

200 The new assignment.

application/json

  • idstringrequired
  • device_namestring
  • person_idstring | nullrequired
  • person_namestring | null
  • previous_person_idstring | null
400 person-id-required

person-id-required: The body has no person_id field (send null to detach).

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 device-not-found person-not-found tenant-not-found

device-not-found: No device with this id in the workspace.

person-not-found: person_id is not a person in this 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 PATCH "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "person_id": "pz81kd03mna"
}'
PowerShell
$body = @'
{
  "person_id": "pz81kd03mna"
}
'@
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Patch -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k" -Headers $headers -ContentType "application/json" -Body $body
Python
import os, uuid, requests

r = requests.patch(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k",
    headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
    json={
        "person_id": "pz81kd03mna"
    },
    timeout=30,
)
r.raise_for_status()
print(r.json())
Node.js
const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "person_id": "pz81kd03mna"
  }),
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());
Response 200 · application/json
{
  "id": "dvc_5mxq2b7r8k",
  "device_name": "dana-laptop",
  "person_id": "pz81kd03mna",
  "person_name": "Dana Levi",
  "previous_person_id": null
}

Remove a device

DELETE/v0/tenants/{tenant_id}/devices/{device_id}

full-access token

Removes a device completely, e.g. a lost or retired laptop: its live connections are cut, its network identity is deleted (it can no longer connect), it is taken out of every access rule that names it, its just-in-time grants end and unused enrollment codes are revoked. A rule whose only device was this one then grants nobody (it never widens). Audited. If the identity cannot be deleted nothing is changed and you get 502; retry.

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

  • device_idstringrequired

    Device id (from GET /devices). A device keeps the id of the enrollment that created it.

    Example: dvc_5mxq2b7r8k

Responses

202 Removed (state is done), with what was cleaned up.

application/json

  • idstringrequired

    Task id.

  • tenant_idstring
  • statestringrequired

    done.

  • result_urinull
  • errornull
  • removedobjectrequired
    removed fields
    • identityboolean

      The device's network identity was deleted.

    • circuits_closedinteger

      Live connections cut.

    • rules_updatedarray of string

      Access rules that named this device and were updated.

    • jit_grants_revokedinteger
    • enrolment_codes_revokedinteger
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 device-not-found tenant-not-found

device-not-found: No device with this id in the workspace.

tenant-not-found: No workspace with this id.

502 unenroll-failed

unenroll-failed: The device could not be removed right now; nothing was changed. Retry.

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/devices/dvc_5mxq2b7r8k" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Delete -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k" -Headers $headers
Python
import os, uuid, requests

r = requests.delete(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k",
    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/devices/dvc_5mxq2b7r8k", {
  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_8k2m0x9s",
  "tenant_id": "tq7x2m9k4ab",
  "state": "done",
  "result_uri": null,
  "error": null,
  "removed": {
    "identity": true,
    "circuits_closed": 1,
    "rules_updated": [
      "pr_7xk2m9c0d1"
    ],
    "jit_grants_revoked": 0,
    "enrolment_codes_revoked": 0
  }
}

Get a device's access history

GET/v0/tenants/{tenant_id}/devices/{device_id}/access-history

read-only token

Which apps and private networks the device used, when and for how long, newest first, plus totals per app. Open sessions are included with live: true. History is kept 30 days; sessions shorter than about 30 seconds may be missing unless the connector reported them. The answer is sent with Cache-Control: no-store.

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

  • device_idstringrequired

    Device id (from GET /devices). A device keeps the id of the enrollment that created it.

    Example: dvc_5mxq2b7r8k

Query parameters

  • daysinteger

    Window in days (1-30).

    Example: 7

  • limitinteger

    Maximum entries returned (1-1000). by_app always covers the whole window.

    Example: 200

  • person_idstring

    Only sessions of this person.

  • connection_idstring

    Only sessions to this app.

  • kindstring

    Only this kind of entry.

  • include_probesboolean

    true = also list the automatic Cloudraw Connect reachability checks, labelled probe: true (for exports); never in by_app.

Responses

200 The device's sessions.

application/json

  • device_idstringrequired
  • daysinteger

    Window used.

  • itemsarray of DeviceAccessHistoryEntryrequired

    Newest first.

    items fields
    • idstringrequired
    • kindstring

      One of: device, browser, other.

    • device_idstring | null
    • device_namestring | null
    • person_idstring | null
    • userstring | null
    • appstring | null

      App or private network name.

    • connection_idstring | null
    • private_network_idstring | null
    • targetobject | null

      {type, host, port} for an app; {type: "private_network", cidrs, translated_cidr} for a private network.

    • viastring

      One of: cloudraw connect, browser, vendor access.

    • dstobject | null

      Exact destination reported by the connector: {proto, ip, port}.

    • bytes_ininteger | null
    • bytes_outinteger | null
    • end_reasonstring | null
    • started_atstring (date-time)required
    • ended_atstring | null (date-time)
    • duration_sinteger | null
    • livebooleanrequired

      The session is still open.

    • probeboolean

      Only with include_probes=true: an automatic Cloudraw Connect reachability check.

    • probe_anomalyboolean

      More than one check-like connection per 2-minute beat for this device + app.

  • by_apparray of object

    Totals per app over the whole window (not only the returned page).

    by_app fields
    • appstring
    • sessionsinteger
    • total_sinteger
  • probes_excludedinteger

    Cloudraw Connect reachability checks left out; 0 with include_probes=true.

  • probes_includedinteger

    Only with include_probes=true: how many listed entries are reachability checks.

  • retention_daysinteger
  • notestring
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 device-not-found tenant-not-found

device-not-found: No device 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/devices/dvc_5mxq2b7r8k/access-history" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/access-history" -Headers $headers
Python
import os, uuid, requests

r = requests.get(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/access-history",
    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/devices/dvc_5mxq2b7r8k/access-history", {
  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
{
  "device_id": "dvc_5mxq2b7r8k",
  "days": 7,
  "items": [
    {
      "id": "ovl_4kx92m",
      "kind": "device",
      "device_id": "dvc_5mxq2b7r8k",
      "device_name": "dana-laptop",
      "person_id": "pz81kd03mna",
      "user": "Dana Levi",
      "app": "ERP",
      "connection_id": "cx9m2v7d1pa",
      "private_network_id": null,
      "target": {
        "type": "rdp",
        "host": "10.20.0.15",
        "port": 3389
      },
      "via": "cloudraw connect",
      "started_at": "2026-10-13T07:02:10.000Z",
      "ended_at": "2026-10-13T08:47:40.000Z",
      "duration_s": 6330,
      "live": false
    }
  ],
  "by_app": [
    {
      "app": "ERP",
      "sessions": 1,
      "total_s": 6330
    }
  ],
  "probes_excluded": 0,
  "retention_days": 30,
  "note": "Sessions shorter than about 30 seconds may be missing. The exact address inside a private network is coming with the connector update."
}

Quarantine a device

POST/v0/tenants/{tenant_id}/devices/{device_id}/quarantine

full-access token

Cuts a device off at once: it is marked untrusted, its network identity is disabled (it cannot connect anywhere), every open session is ended and its just-in-time grants are revoked. Audited and raised as a security alert. Call with ?dry_run=true first to see what it would cut (reachable resources and open sessions) without changing anything. Undo with DELETE …/quarantine.

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

  • device_idstringrequired

    Device id (from GET /devices). A device keeps the id of the enrollment that created it.

    Example: dvc_5mxq2b7r8k

Query parameters

  • dry_runstring

    true or 1: only report the impact, change nothing.

    Example: true

Request body application/json

  • reasonstring

    Why (kept in the audit log and alert; cut at 300 characters).

Responses

200 The impact (dry run) or the result.

application/json

  • dry_runbooleanrequired
  • device_idstringrequired
  • devicestring

    Device name.

  • resourcesarray of object

    What the device can reach now (and loses).

    resources fields
    • kindstring

      One of: connection, smb, private_network.

    • idstring
    • namestring
  • live_sessionsarray of object

    Open sessions of the device; null when they could not be read.

    live_sessions fields
    • idstring
    • appstring | null
    • started_atstring (date-time)
  • overlaystring

    unavailable = live sessions could not be read right now.

    One of: ok, unavailable.

  • already_quarantinedboolean
  • sessions_cutinteger

    Only when dry_run is false.

  • sessions_failedinteger

    Sessions still open after the cut (only when dry_run is false).

  • trustobject

    The device trust after the change (only when dry_run is false).

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 device-not-found tenant-not-found

device-not-found: No device with this id in the workspace.

tenant-not-found: No workspace with this id.

502 quarantine-failed

quarantine-failed: The device could not be quarantined right now. Retry.

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/devices/dvc_5mxq2b7r8k/quarantine" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Laptop reported stolen"
}'
PowerShell
$body = @'
{
  "reason": "Laptop reported stolen"
}
'@
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/quarantine" -Headers $headers -ContentType "application/json" -Body $body
Python
import os, uuid, requests

r = requests.post(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/quarantine",
    headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
    json={
        "reason": "Laptop reported stolen"
    },
    timeout=30,
)
r.raise_for_status()
print(r.json())
Node.js
const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/quarantine", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "reason": "Laptop reported stolen"
  }),
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());
Response 200 · application/json
{
  "dry_run": false,
  "device_id": "dvc_5mxq2b7r8k",
  "device": "dana-laptop",
  "resources": [
    {
      "kind": "connection",
      "id": "cx9m2v7d1pa",
      "name": "ERP"
    }
  ],
  "live_sessions": [
    {
      "id": "ovl_4kx92m",
      "app": "erp",
      "started_at": "2026-10-13T09:02:10.000Z"
    }
  ],
  "overlay": "ok",
  "already_quarantined": false,
  "sessions_cut": 1,
  "sessions_failed": 0,
  "trust": {
    "state": "untrusted",
    "reason": "manually blocked by admin",
    "unmet": [],
    "evaluated_at": "2026-10-13T09:24:11.000Z",
    "source": "manual",
    "manual": "untrusted"
  }
}

Release a device from quarantine

DELETE/v0/tenants/{tenant_id}/devices/{device_id}/quarantine

full-access token

Re-enables the device's network identity and returns its trust to automatic (your trust rules decide again). 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

  • device_idstringrequired

    Device id (from GET /devices). A device keeps the id of the enrollment that created it.

    Example: dvc_5mxq2b7r8k

Responses

200 The device trust after release.

application/json

  • device_idstringrequired
  • statestringrequired

    Trust decision right now.

    One of: trusted, untrusted.

  • reasonstring

    Plain-English reason for the decision.

  • unmetarray of DeviceTrustUnmet

    What keeps the device from being trusted (empty when trusted or when no rule applies).

    unmet fields
    • kindstringrequired

      posture, group, person, device, network, reauth …

    • fieldstring | null

      The condition field, e.g. disk_encrypted, country, last_auth_at.

    • opstring | null
    • valueany

      What the rule wants.

    • gotany

      What the device reported (null = not reported).

    • textstringrequired

      Plain-English explanation, safe to show to the device user.

  • evaluated_atstring (date-time)

    When this decision was computed (now).

  • sourcestringrequired

    default = the workspace has no trust rules yet; manual = set by an admin; rule = your trust rules; policy = a workspace policy (sign-in required, person suspended).

    One of: default, manual, rule, policy.

  • manualstring | null

    Manual override set by an admin; null = automatic (your trust rules decide).

    One of: trusted, untrusted, .

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 device-not-found tenant-not-found

device-not-found: No device with this id in the workspace.

tenant-not-found: No workspace with this id.

409 device-not-quarantined

device-not-quarantined: The device is not quarantined.

502 release-failed

release-failed: The device could not be re-enabled right now; it stays quarantined. Retry.

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/devices/dvc_5mxq2b7r8k/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/devices/dvc_5mxq2b7r8k/quarantine" -Headers $headers
Python
import os, uuid, requests

r = requests.delete(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/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/devices/dvc_5mxq2b7r8k/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
{
  "device_id": "dvc_5mxq2b7r8k",
  "state": "trusted",
  "reason": "matched trust rule \"Managed laptops\"",
  "unmet": [],
  "evaluated_at": "2026-10-13T09:24:11.000Z",
  "source": "rule",
  "manual": null
}

Require sign-in again on a device

POST/v0/tenants/{tenant_id}/devices/{device_id}/require-reauth

full-access tokenidempotent

Forces the person on this device to sign in again (suspected session theft, role change). Until they do, the device is untrusted and loses access that requires trust. Only for devices enrolled through sign-in. Audited.

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

  • device_idstringrequired

    Device id (from GET /devices). A device keeps the id of the enrollment that created it.

    Example: dvc_5mxq2b7r8k

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

Responses

200 Re-authentication is now required.

application/json

  • device_idstringrequired
  • reauth_requiredbooleanrequired
  • trustobject
    trust fields
    • statestring

      Trust decision right now.

      One of: trusted, untrusted.

    • reasonstring

      Plain-English reason for the decision.

    • unmetarray of DeviceTrustUnmet

      What keeps the device from being trusted (empty when trusted or when no rule applies).

      unmet fields
      • kindstringrequired

        posture, group, person, device, network, reauth …

      • fieldstring | null

        The condition field, e.g. disk_encrypted, country, last_auth_at.

      • opstring | null
      • valueany

        What the rule wants.

      • gotany

        What the device reported (null = not reported).

      • textstringrequired

        Plain-English explanation, safe to show to the device user.

    • evaluated_atstring (date-time)

      When this decision was computed (now).

    • sourcestring

      default = the workspace has no trust rules yet; manual = set by an admin; rule = your trust rules; policy = a workspace policy (sign-in required, person suspended).

      One of: default, manual, rule, policy.

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 device-not-found tenant-not-found

device-not-found: No device with this id in the workspace.

tenant-not-found: No workspace with this id.

409 not-a-signed-in-device idempotency-key-reuse

not-a-signed-in-device: The device was enrolled with a code, not through sign-in, so it cannot re-authenticate.

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/devices/dvc_5mxq2b7r8k/require-reauth" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN"; "Idempotency-Key" = [guid]::NewGuid().ToString() }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/require-reauth" -Headers $headers
Python
import os, uuid, requests

r = requests.post(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/require-reauth",
    headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}", "Idempotency-Key": str(uuid.uuid4())},
    timeout=30,
)
r.raise_for_status()
print(r.json())
Node.js
const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/require-reauth", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
    "Idempotency-Key": crypto.randomUUID(),
  },
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());
Response 200 · application/json
{
  "device_id": "dvc_5mxq2b7r8k",
  "reauth_required": true,
  "trust": {
    "state": "untrusted",
    "reason": "sign-in required by your administrator — sign in again to continue",
    "unmet": [
      {
        "kind": "reauth",
        "field": "last_auth_at",
        "op": "required",
        "value": null,
        "got": "2026-10-13T06:58:40.000Z",
        "text": "Sign in again to continue"
      }
    ],
    "evaluated_at": "2026-10-13T09:24:11.000Z",
    "source": "policy"
  }
}

Get a device's trust

GET/v0/tenants/{tenant_id}/devices/{device_id}/trust

read-only token

The trust decision for one device right now, why, what it is missing (unmet) and any manual override.

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

  • device_idstringrequired

    Device id (from GET /devices). A device keeps the id of the enrollment that created it.

    Example: dvc_5mxq2b7r8k

Responses

200 The trust decision.

application/json

  • device_idstringrequired
  • statestringrequired

    Trust decision right now.

    One of: trusted, untrusted.

  • reasonstring

    Plain-English reason for the decision.

  • unmetarray of DeviceTrustUnmet

    What keeps the device from being trusted (empty when trusted or when no rule applies).

    unmet fields
    • kindstringrequired

      posture, group, person, device, network, reauth …

    • fieldstring | null

      The condition field, e.g. disk_encrypted, country, last_auth_at.

    • opstring | null
    • valueany

      What the rule wants.

    • gotany

      What the device reported (null = not reported).

    • textstringrequired

      Plain-English explanation, safe to show to the device user.

  • evaluated_atstring (date-time)

    When this decision was computed (now).

  • sourcestringrequired

    default = the workspace has no trust rules yet; manual = set by an admin; rule = your trust rules; policy = a workspace policy (sign-in required, person suspended).

    One of: default, manual, rule, policy.

  • manualstring | null

    Manual override set by an admin; null = automatic (your trust rules decide).

    One of: trusted, untrusted, .

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 device-not-found tenant-not-found

device-not-found: No device 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/devices/dvc_5mxq2b7r8k/trust" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/trust" -Headers $headers
Python
import os, uuid, requests

r = requests.get(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/trust",
    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/devices/dvc_5mxq2b7r8k/trust", {
  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
{
  "device_id": "dvc_5mxq2b7r8k",
  "state": "trusted",
  "reason": "matched trust rule \"Managed laptops\"",
  "unmet": [],
  "evaluated_at": "2026-10-13T09:24:11.000Z",
  "source": "rule",
  "manual": null
}

Override a device's trust

POST/v0/tenants/{tenant_id}/devices/{device_id}/trust

full-access token

Sets a manual trust override: trusted, untrusted, or auto to remove the override and let your trust rules decide. When the device ends up blocked, its open sessions are ended and its just-in-time grants revoked right away. Audited. A quarantined device must be released first.

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

  • device_idstringrequired

    Device id (from GET /devices). A device keeps the id of the enrollment that created it.

    Example: dvc_5mxq2b7r8k

Request body application/json

  • statestringrequired

    One of: trusted, untrusted, auto.

Responses

200 The trust decision after the change.

application/json

400 invalid-state

invalid-state: state is not trusted, untrusted or auto.

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 device-not-found tenant-not-found

device-not-found: No device with this id in the workspace.

tenant-not-found: No workspace with this id.

409 device-quarantined

device-quarantined: The device is quarantined; release it from quarantine first.

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/devices/dvc_5mxq2b7r8k/trust" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "state": "untrusted"
}'
PowerShell
$body = @'
{
  "state": "untrusted"
}
'@
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Post -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/trust" -Headers $headers -ContentType "application/json" -Body $body
Python
import os, uuid, requests

r = requests.post(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/trust",
    headers={"Authorization": f"Bearer {os.environ['CLOUDRAW_TOKEN']}"},
    json={
        "state": "untrusted"
    },
    timeout=30,
)
r.raise_for_status()
print(r.json())
Node.js
const res = await fetch("https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/trust", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "state": "untrusted"
  }),
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());
Response 200 · application/json
{
  "device_id": "dvc_5mxq2b7r8k",
  "state": "untrusted",
  "reason": "manually blocked by admin",
  "unmet": [],
  "evaluated_at": "2026-10-13T09:24:11.000Z",
  "source": "manual",
  "manual": "untrusted",
  "access_blocked": true,
  "sessions_cut": 1
}

Get fleet compliance

GET/v0/tenants/{tenant_id}/fleet-compliance

read-only token

How many devices meet the health checks your own trust and access rules require. Devices that never reported are not counted in evaluated; a device whose last report is too old counts as not compliant.

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

Responses

200 The roll-up.

application/json

  • total_devicesintegerrequired
  • evaluatedintegerrequired

    Devices that have sent a health report.

  • compliantintegerrequired

    Devices that meet every check your rules require (fresh report).

  • staleinteger

    Devices whose last report is too old.

  • percentinteger | nullrequired

    compliant / evaluated, rounded; null when no device reported.

  • basisstring

    Always workspace-rules: the checks your trust and access rules require.

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/fleet-compliance" \
  -H "Authorization: Bearer $CLOUDRAW_TOKEN"
PowerShell
$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/fleet-compliance" -Headers $headers
Python
import os, uuid, requests

r = requests.get(
    "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/fleet-compliance",
    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/fleet-compliance", {
  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
{
  "total_devices": 23,
  "evaluated": 21,
  "compliant": 18,
  "stale": 1,
  "percent": 86,
  "basis": "workspace-rules"
}