New: the AI firewall watches every module and explains each incident in plain words. See how it works

The history API

Read latest values and time series of device telemetry over REST – parameters, resolutions, aggregates, limits, paging, errors and worked examples.

Two read endpoints give you device telemetry: latest for the current value of each key, and series for history. Both are behind the telemetry read permission and return only devices the caller may read. This page is the reference with examples; see REST API basics and Authentication for keys and paths.

Before you start

  • Create an API key with the permission to read telemetry (and to read devices, if you also list them). The Read-only preset is enough. Restrict the key’s allowed networks to your servers.
  • Find the device id (a UUID) on the device page or with GET /api/iot/devices.
  • Every path is under your organisation: https://<your host>/tenant/<tenantId>/api/....
  • Times are milliseconds since 1 January 1970, UTC.

Latest values

GET /tenant/{tenantId}/api/telemetry/latest?kind=iot_device&entityId={deviceId}&keys=temperature,humidity
ParameterRequiredMeaning
kindYesiot_device for device telemetry
entityIdYesThe device id
keysNoComma-separated keys, at most 50. Leave out for every key.
{
  "kind": "iot_device",
  "entityId": "6f1c…",
  "latest": {
    "temperature": { "ts": 1759572000000, "value": 21.5 },
    "humidity": { "ts": 1759572000000, "value": 40 }
  }
}

A key the device never sent is absent from latest.

Series

GET /tenant/{tenantId}/api/telemetry/series?kind=iot_device&entityId={deviceId}&keys=temperature&from=1759568400000&to=1759572000000&bucket=auto&agg=avg
ParameterRequiredValuesDefault
kindYesiot_device
entityIdYesThe device id
keysYesComma-separated, 1 to 50 keys, each following the key rules
fromYesStart, inclusive (epoch ms)
toYesEnd, exclusive (epoch ms); must be after from
bucketNoauto, raw, 1m, 1h, 1dauto
aggNoavg, min, max, last, sum, count, increaseavg
limitNoPoints per key, 1 to 10,00010,000
{
  "kind": "iot_device",
  "entityId": "6f1c…",
  "resolution": "1m",
  "agg": "avg",
  "series": {
    "temperature": [
      { "ts": 1759568400000, "value": 21.2 },
      { "ts": 1759568460000, "value": 21.4 }
    ]
  }
}
  • resolution is the resolution actually used. With bucket=auto it is raw for windows up to 24 hours, then 1m, 1h or 1d, whichever is finest under 10,000 buckets.
  • With a bucket, ts is the start of the bucket (UTC aligned) and value the aggregate. Buckets without readings are absent, not zero.
  • With raw, every stored value is returned as it was stored (numbers, text, booleans, JSON), one point per timestamp, oldest first; agg is ignored.
  • Points are sorted by time. A key with no data returns an empty list.

See Aggregates and rollups for what each agg returns.

Limits

LimitValue
Keys per request50
Points per key10,000 (limit)
Buckets in a window10,000 at the chosen resolution, else 400 range_too_large
Raw valuesOnly inside your raw retention (at most 90 days)
Minute bucketsOnly inside the minute retention (at most 31 days)
RequestsThe API rate limit; 429 with Retry-After when exceeded. See Errors and rate limits.

Errors

StatusBodyCause
400{ "message": "to must be after from" }to is not after from
400{ "message": "bad keys" }Empty keys, more than 50, or a key that breaks the key rules
400{ "message": "…", "code": "range_too_large" }Too many buckets for the window; use a coarser bucket
401 / 403No valid key, or the key lacks the permission
404{ "message": "Not found" }The device does not exist, or you may not read it (the same answer for both)
429Rate limit

Paging through raw values

A raw read returns at most 10,000 points per key, oldest first. To read more:

  1. Request bucket=raw&limit=10000 for your window.
  2. If a key returned 10,000 points, request again with from set to the last point’s ts + 1.
  3. Repeat until a key returns fewer than limit points.

For long periods, prefer 1m or 1h buckets: they hold the min, max, sum, count and last of every bucket in one value each.

Examples

Latest values with curl:

curl -s -H "Authorization: Bearer $HERMETRY_KEY" \
  "https://$HOST/tenant/$TENANT/api/telemetry/latest?kind=iot_device&entityId=$DEVICE&keys=level,pump_running"

Hourly maximum of a pressure over the last 7 days:

TO=$(date +%s000); FROM=$((TO - 7*24*3600*1000))
curl -s -H "Authorization: Bearer $HERMETRY_KEY" \
  "https://$HOST/tenant/$TENANT/api/telemetry/series?kind=iot_device&entityId=$DEVICE&keys=pressure&from=$FROM&to=$TO&bucket=1h&agg=max"

Energy used per hour (a kWh meter that only grows) over one day:

curl -s -H "Authorization: Bearer $HERMETRY_KEY" \
  "https://$HOST/tenant/$TENANT/api/telemetry/series?kind=iot_device&entityId=$DEVICE&keys=energy_kwh&from=1762642800000&to=1762729200000&bucket=1h&agg=increase"

Daily totals in your time zone

Day buckets are UTC days. For a local day, read hourly increase (or sum) and add the hours that belong to each local day:

// Node.js 18+: daily energy per local day (Europe/Istanbul) for the last 7 days
const tz = 'Europe/Istanbul';
const to = Date.now();
const from = to - 7 * 24 * 3600 * 1000;
const url = `https://${host}/tenant/${tenant}/api/telemetry/series?kind=iot_device&entityId=${device}`
  + `&keys=energy_kwh&from=${from}&to=${to}&bucket=1h&agg=increase`;
const res = await fetch(url, { headers: { Authorization: `Bearer ${key}` } });
const { series } = await res.json();
const days = {};
for (const p of series.energy_kwh) {
  const day = new Date(p.ts).toLocaleDateString('en-CA', { timeZone: tz }); // YYYY-MM-DD
  days[day] = (days[day] ?? 0) + p.value;
}
console.log(days);

The first hour of the window counts only what rose inside it, so start the window an hour before the first local day you need, and drop that hour. A zone with a half-hour offset needs 1m buckets, which reach back at most 31 days.

Other read routes

RouteDoes
GET /api/telemetry/kindsThe kinds of readings your organisation has (for example iot_device)
GET /api/iot/devices/{deviceId}/elementsThe keys of one device (declared in its profile or sent), at most 300, with labels and units

For writes, devices use MQTT or HTTP; the REST API has no telemetry write route. See Device HTTP API and Telemetry and attributes API.