Skip to content

Reports & Analytics

Breeze provides a full reporting and analytics subsystem for generating on-demand or scheduled fleet reports and querying real-time analytics data. Reports are scoped to organizations and enforce multi-tenant access at every layer – organization-scoped users see only their own data, partner-scoped users can access reports for any organization they manage, and system-scoped users have unrestricted access.

The system is split into two complementary route groups:

  • /reports – Saved report definitions, ad-hoc generation, run history, and raw data endpoints for device inventory, software, alerts, compliance, and performance metrics.
  • /analytics – Time-series queries, custom dashboards with widgets, capacity planning, SLA tracking, executive summaries, and OS distribution breakdowns.

Every report has a type that determines which data is queried and how the output is structured.

Type Description Key columns / metrics
device_inventory Full hardware and software asset listing per device hostname, OS, agent version, CPU model, RAM, disk, serial number
software_inventory All installed software across targeted devices software name, version, publisher, install date, device hostname
alert_summary Alert history with severity breakdown title, severity, status, triggered/acknowledged/resolved timestamps, rule name
compliance Device health and compliance posture hostname, OS, status, last seen, compliance flag, identified issues
performance Aggregated CPU, RAM, and disk metrics per device avg/max CPU %, avg/max RAM %, avg/max disk %
executive_summary High-level fleet overview with device counts, alert stats, OS distribution, and site breakdown online/offline totals, health %, critical/high alert counts, resolution rate
security_compliance_posture Per-control security and compliance evidence for one organization, built for cyber-insurance applications and vendor security questionnaires EDR/AV coverage, disk encryption %, firewall %, patch currency %, password policy, local-admin exposure, MFA/PAM posture, backup, DNS filtering, optional CIS pass-rate (see Security & Compliance Posture Report)

When creating a saved report, you provide a config object that controls date ranges, filters, column selection, and sorting.

The config.dateRange object supports preset shortcuts or custom boundaries:

Preset Meaning
last_7_days Data from the past 7 days
last_30_days Data from the past 30 days
last_90_days Data from the past 90 days
custom Use the explicit start and end ISO date strings

The config.filters object narrows the data:

Filter Applies to Accepts
siteIds device_inventory, compliance Array of site UUIDs
deviceIds software_inventory Array of device UUIDs
osTypes device_inventory windows, macos, linux
status alert_summary Array of status strings
severity alert_summary Array of severity strings
Format Description
csv Comma-separated values (default)
pdf Formatted PDF document
excel Excel spreadsheet (.xlsx)

Breeze supports two generation flows: ad-hoc (stateless) and saved (tracked with run history).

Use POST /reports/generate to produce report data immediately without creating a saved report definition. The response contains the generated data inline.

Terminal window
curl -X POST /api/v1/reports/generate \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "device_inventory",
"format": "csv",
"orgId": "ORG_UUID",
"config": {
"dateRange": { "preset": "last_30_days" },
"filters": {
"osTypes": ["windows", "linux"]
}
}
}'

The response includes:

{
"type": "device_inventory",
"format": "csv",
"generatedAt": "2026-02-18T12:00:00.000Z",
"data": {
"rows": [...],
"rowCount": 42
}
}

For saved reports, trigger generation with POST /reports/:id/generate. This creates a report run, computes the data, and stores the result as a point-in-time snapshot – all in the same request, so the response comes back already completed (or failed). The snapshot is what you download later, so the file always reflects the data as of when the run executed rather than re-querying live.

  1. Create a saved report definition with POST /reports (see the API reference below).
  2. Trigger generation with POST /reports/:id/generate. The response returns the new runId with status: "completed" once the snapshot is stored.
  3. Download the result with GET /reports/runs/:runId/download?format=csv (or pdf / excel).
Terminal window
# Trigger generation for a saved report
curl -X POST /api/v1/reports/REPORT_UUID/generate \
-H "Authorization: Bearer $TOKEN"

Response:

{
"message": "Report generation started",
"runId": "a1b2c3d4-...",
"status": "pending"
}

Saved reports support recurring schedules. When you set the schedule field, the report will be generated automatically on the configured cadence.

Schedule Behavior
one_time No recurring generation (default). Must be triggered manually.
daily Generated once per day
weekly Generated once per week
monthly Generated once per month

Set the schedule when creating or updating a report:

Terminal window
curl -X POST /api/v1/reports \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Weekly Compliance Report",
"type": "compliance",
"orgId": "ORG_UUID",
"schedule": "weekly",
"format": "pdf",
"config": {
"filters": { "siteIds": ["SITE_UUID"] }
}
}'

Each time a saved report is generated, a report run record tracks the process through a status lifecycle.

Status Meaning
pending The run has been created and is queued for processing
running The report is actively being generated
completed Generation succeeded; outputUrl contains the download path
failed Generation failed; errorMessage contains the reason

The run record stores:

Field Description
id Unique run identifier (UUID)
reportId The parent saved report definition
status Current lifecycle status
startedAt Timestamp when processing began
completedAt Timestamp when processing finished (success or failure)
outputUrl Download path for the generated file (set on completed)
errorMessage Error description (set on failed)
rowCount Number of data rows in the output

The Security & Compliance Posture report (security_compliance_posture) packages your security evidence for one organization into a single document – purpose-built for filling out cyber-insurance applications and answering vendor security questionnaires. It joins the security data Breeze already collects into per-control answers with percent-implemented rollups: EDR/MDR and native antivirus coverage, the list of unprotected devices, disk-encryption and host-firewall coverage, patch currency, antivirus-definition freshness, password-complexity posture, local-admin exposure, MFA and privileged-access posture, backup coverage, DNS filtering, identity-provider connection, and an optional CIS hardening pass-rate.

It is scoped to a single organization (with an optional site filter) and is honest about gaps: a control that hasn’t been assessed is reported as N/A, never as a misleading 0% or a falsely favorable score. The PDF renders as a branded scorecard (overall score out of 100 with a STRONG / GOOD / FAIR / AT RISK band and a per-control grid) and carries point-in-time, not-a-certification disclaimers.


When a report run reaches the completed status, download its stored snapshot from GET /reports/runs/:id/download. Pass the desired format as a query parameter – ?format=csv, ?format=pdf, or ?format=excel. Because the run captured the data at generation time, the download is stable: re-downloading the same run always yields the same data. Downloading a run that hasn’t completed returns 409 Conflict.

Terminal window
# Download a completed run as CSV
curl "/api/v1/reports/runs/RUN_UUID/download?format=csv" \
-H "Authorization: Bearer $TOKEN" -OJ

CSV and Excel files are produced on the server; PDF is rendered in the browser from the same snapshot. When retrieving a single report via GET /reports/:id, the response includes the five most recent runs, making it easy to find the latest completed download.


The /analytics route group provides real-time operational intelligence beyond static reports.

POST /analytics/query executes a flexible time-series query across device metrics.

Terminal window
curl -X POST /api/v1/analytics/query \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"deviceIds": ["DEVICE_UUID_1", "DEVICE_UUID_2"],
"metricTypes": ["cpu", "ram"],
"startTime": "2026-02-01T00:00:00Z",
"endTime": "2026-02-18T00:00:00Z",
"aggregation": "avg",
"interval": "hour"
}'

Supported aggregations: avg, min, max, sum, count, p95, p99.

Supported intervals: minute, hour, day, week, month.

An optional groupBy array lets you split the series by additional dimensions.

Dashboards are per-organization containers for widgets. Each widget has a type and a config object that determines what data it renders.

Terminal window
curl -X POST /api/v1/analytics/dashboards \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"orgId": "ORG_UUID",
"name": "NOC Overview",
"description": "Primary network operations dashboard",
"layout": {}
}'

GET /analytics/executive-summary returns a high-level organizational overview including device totals (online/offline), a 12-week enrollment trend, and configurable period types.

Query parameter Values Default
periodType daily, weekly, monthly monthly
range Freeform string
startDate ISO date string
endDate ISO date string

GET /analytics/os-distribution returns the count of active devices grouped by osType and osVersion, excluding decommissioned devices.

GET /analytics/capacity returns capacity predictions based on current metric trends. Accepts optional deviceId and metricType query parameters to narrow scope.

SLA definitions set uptime or performance targets that are evaluated over a window.

Field Description
name Human-readable SLA name
targetPercentage Target compliance percentage (0–100)
evaluationWindow daily, weekly, or monthly
scope device, site, or organization
filters Additional scoping filters (JSON)

Compliance history for an SLA is retrieved via GET /analytics/sla/:id/compliance, which returns period-by-period entries with a status of met, breached, or warning.


The /reports/data/* endpoints provide raw, paginated data used to power report views and dashboards. These are read-only query endpoints that accept common filters.

Endpoint Returns
GET /reports/data/device-inventory Device list with hardware details (CPU, RAM, disk, serial number, manufacturer, model)
GET /reports/data/software-inventory Installed software list with per-title device counts in a summary array
GET /reports/data/alerts-summary Alert statistics: counts by severity, by status, daily trend (last 30 days), and top 10 alerting rules
GET /reports/data/compliance Compliance overview with device status breakdown, OS distribution, agent version spread, and identified issues (stale devices, outdated agents)
GET /reports/data/metrics Performance metrics: fleet-wide averages for CPU/RAM/disk plus the top 10 consumers for each metric

All data endpoints accept these common query parameters:

Parameter Description
orgId Filter to a specific organization (required for partner scope)
siteId Filter to a specific site
startDate Start of date range (ISO string)
endDate End of date range (ISO string)
limit Page size (default 100, max 1000)
offset Pagination offset

Method Endpoint Description
GET /reports List saved reports. Filter by type, schedule, orgId. Paginated.
POST /reports Create a saved report definition with name, type, config, schedule, and format.
GET /reports/:id Get a single report with its 5 most recent runs.
PUT /reports/:id Update report name, config, schedule, or format.
DELETE /reports/:id Delete a report and all associated runs.
Method Endpoint Description
POST /reports/generate Ad-hoc generation. Returns data inline.
POST /reports/:id/generate Trigger async generation for a saved report. Returns a runId.
Method Endpoint Description
GET /reports/runs List runs. Filter by reportId, status. Paginated.
GET /reports/runs/:id Get a single run with parent report metadata and download URL.
GET /reports/runs/:id/download Download the run’s stored snapshot. Requires ?format=csv|pdf|excel. Returns 409 if the run is not completed.
Method Endpoint Description
GET /reports/data/device-inventory Raw device inventory with hardware join.
GET /reports/data/software-inventory Raw software inventory with per-title summary.
GET /reports/data/alerts-summary Alert breakdown by severity, status, daily trend, top rules.
GET /reports/data/compliance Compliance overview, stale device detection, agent version audit.
GET /reports/data/metrics Fleet performance averages and top-10 resource consumers.
Method Endpoint Description
POST /analytics/query Execute a time-series metrics query with aggregation and interval.
GET /analytics/dashboards List dashboards. Filter by orgId. Paginated.
POST /analytics/dashboards Create a dashboard.
GET /analytics/dashboards/:id Get dashboard with all widgets.
PATCH /analytics/dashboards/:id Update dashboard name, description, or layout.
DELETE /analytics/dashboards/:id Delete dashboard and all its widgets.
POST /analytics/dashboards/:id/widgets Add a widget to a dashboard.
PATCH /analytics/widgets/:id Update widget name, type, config, or layout.
DELETE /analytics/widgets/:id Remove a widget from its dashboard.
GET /analytics/capacity Capacity planning predictions.
GET /analytics/sla List SLA definitions. Filter by orgId. Paginated.
POST /analytics/sla Create an SLA definition.
GET /analytics/sla/:id/compliance Get compliance history for an SLA.
GET /analytics/executive-summary Executive fleet summary with enrollment trends.
GET /analytics/os-distribution OS type/version distribution for active devices.

POST /reports/:id/generate computes the report and stores its snapshot in the same request, so a run normally comes back completed immediately. If it comes back failed, inspect the run’s errorMessage field (via GET /reports/runs/:id) for the cause – most often a configuration problem such as an invalid date range or a scope the caller can’t access.

“Organization context required” (403) on report endpoints

Section titled ““Organization context required” (403) on report endpoints”

This error occurs when an organization-scoped token is used but the token lacks an orgId claim. Verify that the JWT includes the orgId field. Partner-scoped users must pass orgId explicitly as a query parameter or in the request body.

Data endpoint returns empty results despite existing devices

Section titled “Data endpoint returns empty results despite existing devices”

The /reports/data/* endpoints join against related tables (deviceHardware, deviceSoftware, deviceMetrics). If devices exist but related data has not been collected yet (e.g., hardware inventory has not been reported by the agent), joins may exclude those devices or return null fields. Check that agents are running and have submitted at least one heartbeat with hardware and software data.

The compliance report flags a device as non-compliant if its status is decommissioned or if it has not been seen in the last 7 days. Devices that are powered off or in maintenance for extended periods will lower the compliance score. The compliance data endpoint also identifies stale_devices (not seen in 7+ days) and outdated_agents (running a version other than the most common version) as separate issues. Review the issues array in the response to understand which factors are contributing to the score.