Reports Reference
Schema, REST endpoints, widget catalogue, grid constraints, and permission reference for the octoja Reports area.
Written By Erdinc Akay
Last updated 26 days ago
The Reports area builds custom PDF reports from a library of widgets. This page documents the behaviours, permissions, layout grid, and widget catalogue that the schema alone cannot express.
For the complete, always-current list of endpoints, parameters, and response fields for the version you are running, use the interactive OpenAPI (Swagger) interface at https://<your-octoja-instance>/openapi/index.html.
For an end-to-end walkthrough of creating a template and generating a PDF, see Create a report template.
REST endpoints
All Reports endpoints live under /api/reports/. The Notes column carries the required permission (octoja uses custom permission policies that are not all expressed in Swagger) plus the non-obvious behaviour.
Behaviours worth knowing
- Clone on create:
cloneFromTemplateIdmust be a GUID-formatted string when present; the new template is a deep copy of the source's rows + widgets. - UpdateValue envelope: the update body wraps each field, e.g.
{ name?: { hasValue: true, value }, rows?: { hasValue: true, value }, orientation?: { hasValue: true, value } }. The update is partial β fields omitted from the body (or sent withouthasValue: true) are left untouched on the stored template, not cleared. - Generate range: the optional
rangeStart/rangeEnd(ISO dates) restrict time-windowed widgets to a reporting period β pass both or neither; omit them for an all-time report.
Schema and fields
The full field list and types for ReportTemplate, ReportRow, and ReportWidget are in Swagger. The fields below carry behaviour the schema cannot convey.
- name β for built-in templates this is an i18n key (e.g.
pages.reports.builtIns.executiveSnapshot.name), localized on display; for custom templates it is the literal user-entered string. - isBuiltIn β response-only / derived. Server-computed from a built-in id allowlist rather than persisted on the entity;
truefor templates that ship with octoja,falsefor tenant-created custom templates. - slug β PDF download filename base. Built-ins only β
executive-snapshotproducesexecutive-snapshot-2026-04-20.pdf; custom templates fall back to a slugifiedname(defaultnull). - iconName β Lucide icon component name on the template card. Built-ins only (default
null). - orientation β
Portrait(default) orLandscape. Landscape fits wide tables such as the hardware inventory; an invalid value returns400 Bad Request. - columnSpan (widget) β number of grid columns occupied (default
1). Bounded per-widget; each widget type declares its ownminColumnSpan,maxColumnSpan, anddefaultColumnSpan, which the editor enforces. - rowSpan (widget) β height in editor rows;
0(default) means "use the widget's default row span". - config (widget) β widget-specific settings whose shape depends on the widget
type; refer to the editor's properties panel for the available options. - backgroundColor (widget) β one of a fixed set of tints (
Indigo,Emerald,Amber,Sky,Rose,Slate); the Callout widget uses the same set. - autoStatusColor (widget) β when
true, data-driven widgets (KPI cards, gauges) tint themselves by the value's severity (green OK, amber Warning, red Critical). No effect on widgets that declare no auto-status thresholds.
A ReportRow has no configurable properties of its own β it groups widgets horizontally and triggers a natural page break when the grid runs out of room.
The four-column grid
The report canvas is a fixed four-column grid. Each widget's columnSpan declares how many of the four columns it occupies. A row can hold any combination of widgets whose columnSpan values sum to four or less. When you add a fifth widget to a row that already sums to four, octoja places it in a new row.
Typical spans: 1 = quarter-width (KPI cards, small gauges); 2 = half-width (info cards, charts); 3 = three-quarters (a wide table beside a narrow card); 4 = full-width (hero charts, tables that need every column).
Widget catalogue
Widgets are grouped into six categories β KPI cards, Charts, Tables, Info cards, Layout, and Checks. The notes below capture each widget's scope-awareness and any non-obvious behaviour; GET /api/reports/widgets/available returns the authoritative live catalogue for the current build. Unless noted otherwise, every data widget is scope-aware (it honours the report's customer / site filters).
KPI cards (Kpi)
Single-value indicators with a coloured header and an optional auto-status tint. The catalogue is large and grows with the product β examples include Total Devices, Online Devices, Open Cases (count of non-closed cases β any status other than Closed), Health Score, Low Disk Devices, Patch Compliance, Certs Expiring β€30d, Check Success Rate, plus activity, backup, monitoring, Lywand, software-inventory, and incident KPIs. All KPI cards are scope-aware.
Charts (Chart)
- Device Age (bar chart) β histogram of devices by age band (e.g. < 1y, 1β3y, 3β5y, > 5y).
- OS Distribution (bar chart) β devices grouped by operating system family.
- Device Kinds (donut) β devices grouped by kind (workstation, server, etc.).
- Disk Usage Buckets (donut) β devices grouped by overall disk-usage bucket.
- Cases by Priority (donut) β non-closed cases grouped by priority. Closed cases are excluded, matching the Open Cases KPI.
- Activity by Source (donut) β activity events grouped by source.
- Check Status Distribution (donut) β a selected check's result distribution (Ok / Warning / Critical / Unknown).
- Check Status History (chart) β time-series of a selected check's result history across the scope.
Tables (Table)
- All Devices β devices with name, OS, last-seen, and health.
- Recent Cases β recent cases with title, status, priority, customer, and date.
- Certificate Expiry Table β certificates due to expire, grouped by days remaining.
- Disk Space Table β devices ordered by least free disk space.
- Top Manufacturers β devices grouped by hardware manufacturer.
- Check Results Table β per-device results for a selected check (status, value, last evaluated).
- Incident Timeline β chronological list of incidents within the scope.
- Backup Status β backup job runs with target, status, and last success.
- Local Users β local accounts present on devices in the scope.
- Vulnerabilities β vulnerability findings surfaced by the Lywand integration.
- Monitoring Summary β monitoring check state across devices.
- Top Installed Software β most-installed software titles across the scope's devices.
- Hardware Inventory β one row per device with a configurable set of hardware fields, grouped into System, Identity, CPU, Memory, Storage, and Network.
- Patch History β installed updates per device, with KB number and install date.
- Pending Patches β updates still outstanding per device.
Info cards (Info)
- Device Summary β server-resolved roll-up of devices in scope (totals + breakdown).
- Customer Breakdown β server-resolved customer roll-up (names + counts), filtered by the report's customer and site scope.
- Gauge (Static) β single gauge with a configurable value range and severity thresholds. Author-provided value β does not query live data and is not scope-aware.
Checks (Checks)
- Check Detail β detail card for a single check (current state, last result, configuration summary).
- Check History (per device) β per-device result history for a single check, one entry per device with its recent trend. Can be narrowed to specific devices or statuses.
- Check Status Timeline β timeline of a single check's state transitions across the scope.
Layout (Layout)
Structural widgets β no live data, and not scope-aware.
- Heading β section heading text.
- Paragraph β body paragraph text.
- Callout β coloured callout box with one of the six background colours.
- Bullet List β bullet list with marker style
Dot,Check, orDash. - Divider β horizontal rule.
- Spacer β vertical whitespace.
- Page Break β forces a page break at this point in the PDF.
- Traffic Lights β author-curated grid of status cells (
Ok/Warning/Critical/Unknown).
Scope semantics
When a report is generated, the request payload carries customerId? and siteId? β both optional, and a siteId is only meaningful when paired with a customerId. The renderer narrows every scope-aware widget's data query to that customer (and optional site).
Widgets that are not scope-aware (the Gauge and all Layout widgets) ignore the scope β their content is author-provided and renders the same regardless of customerId / siteId.
Scope is not stored on the template. It is a generate-time parameter β the same template can produce a tenant-wide report, a per-customer report, or a per-site report depending on what is passed to the generate call.
Built-in vs custom templates
Both types share the same schema and editor experience. The differences are behavioural:
- Created by β built-in ships with octoja; custom is created by you.
- name β built-in is an i18n key (localized on display); custom is the literal user string.
- slug / iconName β set on built-ins (slug drives the PDF filename, iconName the card icon);
nullon custom (filename slugified from name, generic template icon). - Edit β built-ins are read-only; clone first to customize. Custom templates are editable.
- Delete β built-ins are protected server-side; custom templates are deletable.
- Duplicate β allowed for both, and always produces a new custom template.
Permission
reports.manage β creating, editing, deleting, and renaming custom templates. Generating reports and viewing the template list do not require it.
Granted via groups in Administration β Groups.
PDF filename
The generated PDF's filename is set by the content-disposition header on the response:
- Built-in template:
<slug>-<yyyy-mm-dd>.pdf(e.g.executive-snapshot-2026-04-20.pdf). - Custom template:
<slugified-name>-<yyyy-mm-dd>.pdf(e.g.quarterly-customer-review-2026-04-20.pdf).
The date is the date of generation. The report's data window is a separate setting: the optional rangeStart / rangeEnd reporting period on the generate call (the Period selector in the UI, with All time, Current month, Last month, and Custom presets). Time-windowed widgets honour it; point-in-time widgets such as the inventory tables always reflect the current state.
PDF language
The PDF locale follows the Accept-Language request header. octoja always sets this to the user's current UI language at the moment Generate is clicked. To produce a German PDF from an English UI, switch the language picker first and then click Generate β the next click produces a German PDF.
Scheduling
Reports can be delivered automatically on a recurring basis. A schedule bundles one or more report templates with a cron expression and a set of receivers; when the schedule fires, octoja generates each template as a PDF and emails it to the receivers. The reports page has a Scheduling entry that opens this management area.
- cron β a standard 5-field cron expression, evaluated in UTC. It is validated on save; an invalid expression returns
400 Bad Request. - receivers β one or more entries, each pairing a
customerId(required), an optionalsiteId(only meaningful with a customer), and a list of recipientemails. Each receiver defines the report scope for the PDFs it gets β the same customer/site narrowing described under Scope semantics. - enabled β a disabled schedule is retained but never fires; the next run time is only computed while it is enabled.
- subject β optional custom subject line for the delivery email; leave it empty for the default.
Creating, updating, and deleting schedules β as well as running one immediately β require reports.manage. Listing and viewing schedules require only reports.view.
Related articles
- Create a report template β end-to-end walkthrough.