History
Stored tag history is read in three ways: the historian module's own routes (this page), tag.replay over the socket, which asks the historian when it runs and the event backbone otherwise (see Live data over /sync), and the raw backbone window on Runtime and modules. Reports are saved definitions the dashboard runs against the historian. Background in History and replay and Historian.
Historian routes
All under /api/v1/modules/io.scadex.historian. As module routes, a GET needs viewer and PUT needs engineer. While the module is not running they answer 503 Module unavailable; while its store is still opening in the background they also answer 503, and history reads over the socket come from the backbone meanwhile.
| Method and path | Role | Purpose |
|---|---|---|
GET /api/v1/modules/io.scadex.historian/status | viewer | Position, lag, oldest and newest sample, size on disk, gaps |
GET /api/v1/modules/io.scadex.historian/points | viewer | Raw samples of one tag, oldest first, paged |
GET /api/v1/modules/io.scadex.historian/buckets | viewer | Aggregates per time bucket |
GET /api/v1/modules/io.scadex.historian/settings | viewer | {"retentionDays": 90} |
PUT /api/v1/modules/io.scadex.historian/settings | engineer | Change retention |
Times on these routes are Unix milliseconds.
Status
{
"running": true, "retentionDays": 90, "position": 904411, "streamHead": 904411, "lag": 0, "lastBatchAt": "…",
"approximateSamples": 12800411, "tags": 1480, "oldest": 1754900000000, "newest": 1762603200000, "sizeBytes": 734003200,
"gaps": [ { "from": 1760000000000, "to": 1760003600000, "missedMessages": 1200 } ],
"lastPrunedAt": "…", "lastPruneError": null
}
position is the stream position the store has committed; lag is how far behind the live stream it is. gaps are periods the module never received because they expired from the backbone before it caught up.
Raw samples
GET /api/v1/modules/io.scadex.historian/points?path=Plant.Line1.Temperature&start=&end=&limit=10000&cursor=
| Parameter | Meaning |
|---|---|
path | The tag's path (a deleted tag stays queryable by its last path until retention removes it; a renamed tag keeps its history) |
start, end | Unix milliseconds |
limit | 1 to 100000, default 10000 (400 outside the range) |
cursor | The previous page's nextCursor; an unparseable cursor is 400 |
Response:
{ "path": "Plant.Line1.Temperature", "tagId": 17, "start": 1762560000000, "end": 1762603200000,
"points": [ { "…": "one sample per entry: timestamp, value, quality" } ],
"truncated": true, "nextCursor": "…" }
truncated is true when the page filled before end; pass nextCursor back as cursor for the rest. nextCursor is null on the last page.
Buckets
GET /api/v1/modules/io.scadex.historian/buckets?path=&start=&end=&buckets=500
buckets is 1 to 10000, default 500. Each bucket aggregates the Good numeric values in its span:
{ "path": "…", "tagId": 17, "start": 1762560000000, "end": 1762603200000,
"buckets": [ { "startMs": 1762560000000, "endMs": 1762560086400, "count": 12, "badCount": 0, "min": 71.2, "max": 73.9, "avg": 72.4, "first": 71.5, "last": 73.1 } ] }
min, max, avg, first and last are null for a bucket with no good values; badCount counts the samples that were not good.
Retention
PUT /api/v1/modules/io.scadex.historian/settings body {"retentionDays": 90}. Shortening it prunes at once; otherwise pruning runs hourly. The data lives in <data>/modules/io.scadex.historian/history.db.
Reports
Saved report definitions, shared by everyone on the gateway, under /api/v1/reports. Running one is the dashboard asking the historian's bucket route for each tag; there is no server-side run route, and CSV export is done by the dashboard from the fetched buckets. Dashboard side: Reports.
| Method and path | Role | Purpose |
|---|---|---|
GET /api/v1/reports | viewer | Every report, by name |
GET /api/v1/reports/{id} | viewer | One report |
POST /api/v1/reports | engineer | Create |
PUT /api/v1/reports/{id} | engineer | Replace |
DELETE /api/v1/reports/{id} | engineer | Delete (204) |
ReportBody:
| Field | Type | Required | Meaning |
|---|---|---|---|
name | string | yes | Up to 80 characters |
description | string | no | Up to 500 characters |
tagPaths | string[] | yes | 1 to 20 paths, each up to 300 characters |
windowHours | integer | yes | 1 to 720 |
intervalMinutes | integer | yes | 1 to 1440 |
windowHours * 60 / intervalMinutes must not exceed 2000 rows (400). The response adds id, createdAt and updatedAt (ISO-8601). Unknown ids are 404.