Measurements API
Read with aggregations
Read measurements as a stream of (ts, value) pairs, optionally
aggregated. The endpoint is designed to back the dashboard's charts and
to be hit hard from the reports generator. Everyone else
should call it sparingly.
Endpoint
GET /v1/channels/chn_a1b2/measurements
Query parameters:
| Param | Default | Meaning |
|---|---|---|
from | now − 24 h | RFC 3339, inclusive |
to | now | RFC 3339, exclusive |
agg | raw | raw, 5m, 1h, 1d |
fn | mean | mean, min, max, count, last, p50, p95 |
limit | 5000 | Cap on returned points |
format | json | json, csv |
raw returns every stored measurement; 5m, 1h, 1d return rollups
from the corresponding continuous-aggregate (faster, lower precision).
For HACCP reports use 5m with fn=min and fn=max to get the
hourly envelope.
Response (JSON)
{
"channel_id": "chn_a1b2",
"agg": "5m",
"fn": "mean",
"data": [
[ "2026-05-17T08:00:00Z", 4.13 ],
[ "2026-05-17T08:05:00Z", 4.21 ],
...
],
"next_cursor": null,
"has_more": false
}
Pairs are sorted ascending by ts. Missing buckets (the sensor was
offline) are omitted, not filled with null. The dashboard renders the
gap as a break in the line.
Multiple channels in one call
GET /v1/measurements?channel_ids=chn_a1b2,chn_a1b3,chn_a1b4&agg=1h
Response is keyed by channel:
{
"data": {
"chn_a1b2": [ ["...Z", 4.13], ... ],
"chn_a1b3": [ ["...Z", 64.1], ... ],
"chn_a1b4": [ ["...Z", 92], ... ]
}
}
Up to 32 channel ids per request. The endpoint is rate-limited harder than the single-channel one.
CSV
?format=csv returns:
ts,value
2026-05-17T08:00:00Z,4.13
2026-05-17T08:05:00Z,4.21
Headers stable, separator is comma, decimal point is .. We do not
emit semicolon-separated CSV. Excel users on EU locales should open
with Data → From text rather than double-click.
Pagination
Use next_cursor if has_more is true. The cursor is opaque and
embeds (from, to, agg, last_ts). Pass it as ?cursor=... on the
next request; ignore from / to (the cursor carries them).
Gaps and no_data
A channel that has not reported in > 2 × cadence has a
state = no_data flag separate from the values endpoint. To find
gaps explicitly:
GET /v1/channels/chn_a1b2/gaps?from=…&to=…
Returns intervals where consecutive measurements are > 5 × cadence
apart. Useful for the report's "device offline" timeline.
Bulk export
For multi-day exports use the export endpoint, which streams CSV
without loading the whole result set into memory:
GET /v1/channels/chn_a1b2/export?from=…&to=…&format=csv
This bypasses the limit cap and the rate limiter (it has a separate,
slower budget of 1 export per 5 minutes). Returns up to 1 year of raw
data per call.