API reference
Reports
Protection status of the workspace and the monthly customer report.
Get the monthly report
GET/v0/tenants/{tenant_id}/customer-report
Builds the monthly access report for one calendar month (UTC): people, devices, connectors, published apps and networks, sessions, configuration changes and incidents. By default it answers a printable HTML page (A4); with format=json it answers only the headline numbers. The report is built on demand from current data and the month's audit log, so it is not cached and nothing is saved.
Token: read-only or full access · Created by: owner or security admin
Path parameters
- tenant_idstringrequired
Your workspace id (Settings → Workspace in the console; it is also in every console URL).
Query parameters
- monthstring
Month to report,
YYYY-MMwith a month from01to12. Missing: the current month (UTC). Any other value:400 invalid-month. - formatstring
jsonanswers the summary as JSON; anything else (or omitted) answers the HTML report.
Responses
200 With format=json: the summary. Otherwise: the full report as an HTML page (text/html).
application/json
- monthstringrequired
YYYY-MMof the report. - labelstringrequired
Month name and year, e.g. "September 2026".
- statsobjectrequired
stats fields
- peopleintegerrequired
People in the workspace.
- devicesintegerrequired
Enrolled devices that have connected at least once.
- sessionsintegerrequired
Access sessions started in the month.
- incidentsintegerrequired
Alerts opened in the month.
- changesintegerrequired
Kinds of configuration change made in the month.
text/html
400 invalid-month
invalid-month: month is not YYYY-MM with a month from 01 to 12 (for example 2026-13).
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.
500 report-failed
report-failed: The report could not be built; retry later.
curl -sS -X GET "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/customer-report" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/customer-report" -Headers $headersimport os, uuid, requests
r = requests.get(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/customer-report",
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/customer-report", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"month": "2026-09",
"label": "September 2026",
"stats": {
"people": 18,
"devices": 21,
"sessions": 412,
"incidents": 2,
"changes": 6
}
}Get protection status
GET/v0/tenants/{tenant_id}/protection-status
One line per protection (second step at sign-in, device trust, access rules, allowed apps, recording, browser controls, file protection, web filtering, remembered Windows sign-in): whether it is configured, and whether Cloudraw really applies it everywhere it is configured. partial comes with a scope naming where it is applied, and coverage counts how many of the configured items are covered. Read-only: nothing is created or saved. If the sign-in service cannot be reached, the second_step item is left out of the answer rather than guessed.
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 Protection status.
application/json
- checked_atstring (date-time)required
- itemsarray of ProtectionStatusItemrequired
One item per protection, in a fixed order. An item whose state cannot be read right now is left out.
items fields
- keystringrequired
- configuredbooleanrequired
The protection is switched on / configured somewhere in the workspace.
- enforcementstringrequired
not_available= your plan or this service does not provide it. - scopestring | nullrequired
Only when
enforcementispartial: where the protection IS applied. Otherwise null. - coverageone ofrequired
How many of the things it is configured on (rules, apps, devices, file servers) are really covered; null for workspace-wide protections.
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/protection-status" \
-H "Authorization: Bearer $CLOUDRAW_TOKEN"$headers = @{ Authorization = "Bearer $env:CLOUDRAW_TOKEN" }
Invoke-RestMethod -Method Get -Uri "https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/protection-status" -Headers $headersimport os, uuid, requests
r = requests.get(
"https://cdapi.cloudraw.com/v0/tenants/tq7x2m9k4ab/protection-status",
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/protection-status", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.CLOUDRAW_TOKEN}`,
},
});
if (!res.ok) throw new Error((await res.json()).code);
console.log(await res.json());{
"checked_at": "2026-10-13T09:24:11.000Z",
"items": [
{
"key": "second_step",
"configured": true,
"enforcement": "partial",
"scope": "workspace_sign_in_only",
"coverage": {
"enforced": 21,
"total": 23
}
},
{
"key": "device_trust",
"configured": true,
"enforcement": "enforced",
"scope": null,
"coverage": null
},
{
"key": "access_rules",
"configured": true,
"enforcement": "enforced",
"scope": null,
"coverage": {
"enforced": 12,
"total": 12
}
},
{
"key": "app_firewall",
"configured": true,
"enforcement": "partial",
"scope": "client_min_version",
"coverage": {
"enforced": 14,
"total": 17
}
},
{
"key": "recording",
"configured": true,
"enforcement": "partial",
"scope": "browser_sessions_only",
"coverage": {
"enforced": 1,
"total": 3
}
},
{
"key": "browser_controls",
"configured": true,
"enforcement": "partial",
"scope": "browser_sessions_only",
"coverage": {
"enforced": 1,
"total": 4
}
},
{
"key": "file_protection",
"configured": false,
"enforcement": "not_enforced",
"scope": null,
"coverage": null
},
{
"key": "web_filtering",
"configured": false,
"enforcement": "not_available",
"scope": null,
"coverage": null
},
{
"key": "remembered_sign_in",
"configured": false,
"enforcement": "not_enforced",
"scope": null,
"coverage": null
}
]
}