API reference
Devices
Computers and phones running Cloudraw Connect: health, trust, quarantine.
List devices
GET/v0/tenants/{tenant_id}/devices
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).
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
- 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
- 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;
onlineandlast_seenare the last known values. - last_seenstring | null (date-time)
- accessstringrequired
Can this device reach anything right now?
- blocked_bystring | null
Why it is blocked; null when allowed.
- quarantinedboolean
- quarantined_atstring | null (date-time)
- quarantine_reasonstring | null
- trustobjectrequired
trust fields
- statestringrequired
Trust decision right now.
- 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). - manualstring | null
- healthDeviceHealth
health fields
- statestringrequired
- 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+):
stateon|off|paused_multi_workspace|unknown,enabled,multi_workspace,reason,message(plain text when paused), countersblockedmonitoredwarnedrequests,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.
- enrolled_byobject | null
enrolled_by fields
- kindstring
- 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 -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices" -Headers $headersimport 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())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());{
"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}
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).
- device_idstringrequired
Device id (from
GET /devices). A device keeps the id of the enrollment that created it.
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 -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"
}'$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 $bodyimport 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())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());{
"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}
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).
- device_idstringrequired
Device id (from
GET /devices). A device keeps the id of the enrollment that created it.
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 -sS -X DELETE "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Delete -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k" -Headers $headersimport 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)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);{
"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
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).
- device_idstringrequired
Device id (from
GET /devices). A device keeps the id of the enrollment that created it.
Query parameters
- daysinteger
Window in days (1-30).
- limitinteger
Maximum entries returned (1-1000).
by_appalways covers the whole window. - 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 inby_app.
Responses
200 The device's sessions.
application/json
- device_idstringrequired
- daysinteger
Window used.
- itemsarray of DeviceAccessHistoryEntryrequired
Newest first.
items fields
- idstringrequired
- kindstring
- 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
- 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 -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/access-history" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/access-history" -Headers $headersimport 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())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());{
"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
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).
- device_idstringrequired
Device id (from
GET /devices). A device keeps the id of the enrollment that created it.
Query parameters
- dry_runstring
trueor1: only report the impact, change nothing.
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
- 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. - already_quarantinedboolean
- sessions_cutinteger
Only when
dry_runis false. - sessions_failedinteger
Sessions still open after the cut (only when
dry_runis false). - trustobject
The device trust after the change (only when
dry_runis 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 -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"
}'$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 $bodyimport 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())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());{
"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
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).
- device_idstringrequired
Device id (from
GET /devices). A device keeps the id of the enrollment that created it.
Responses
200 The device trust after release.
application/json
- device_idstringrequired
- statestringrequired
Trust decision right now.
- 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). - manualstring | null
Manual override set by an admin; null = automatic (your trust rules decide).
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 -sS -X DELETE "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/quarantine" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Delete -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/quarantine" -Headers $headersimport 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)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);{
"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
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).
- device_idstringrequired
Device id (from
GET /devices). A device keeps the id of the enrollment that created it.
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.
Responses
200 Re-authentication is now required.
application/json
- device_idstringrequired
- reauth_requiredbooleanrequired
- trustobject
trust fields
- statestring
Trust decision right now.
- 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).
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 -sS -X POST "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/require-reauth" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"$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 $headersimport 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())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());{
"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
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).
- device_idstringrequired
Device id (from
GET /devices). A device keeps the id of the enrollment that created it.
Responses
200 The trust decision.
application/json
- device_idstringrequired
- statestringrequired
Trust decision right now.
- 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). - manualstring | null
Manual override set by an admin; null = automatic (your trust rules decide).
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 -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/trust" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/devices/dvc_5mxq2b7r8k/trust" -Headers $headersimport 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())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());{
"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
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).
- device_idstringrequired
Device id (from
GET /devices). A device keeps the id of the enrollment that created it.
Request body application/json
- statestringrequired
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 -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"
}'$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 $bodyimport 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())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());{
"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
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).
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 -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/fleet-compliance" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/fleet-compliance" -Headers $headersimport 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())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());{
"total_devices": 23,
"evaluated": 21,
"compliant": 18,
"stale": 1,
"percent": 86,
"basis": "workspace-rules"
}