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:

ParamDefaultMeaning
fromnow − 24 hRFC 3339, inclusive
tonowRFC 3339, exclusive
aggrawraw, 5m, 1h, 1d
fnmeanmean, min, max, count, last, p50, p95
limit5000Cap on returned points
formatjsonjson, 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.