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
| Parameter | Required | Meaning |
|---|---|---|
kind | Yes | iot_device for device telemetry |
entityId | Yes | The device id |
keys | No | Comma-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
| Parameter | Required | Values | Default |
|---|---|---|---|
kind | Yes | iot_device | |
entityId | Yes | The device id | |
keys | Yes | Comma-separated, 1 to 50 keys, each following the key rules | |
from | Yes | Start, inclusive (epoch ms) | |
to | Yes | End, exclusive (epoch ms); must be after from | |
bucket | No | auto, raw, 1m, 1h, 1d | auto |
agg | No | avg, min, max, last, sum, count, increase | avg |
limit | No | Points per key, 1 to 10,000 | 10,000 |
{
"kind": "iot_device",
"entityId": "6f1c…",
"resolution": "1m",
"agg": "avg",
"series": {
"temperature": [
{ "ts": 1759568400000, "value": 21.2 },
{ "ts": 1759568460000, "value": 21.4 }
]
}
}
resolutionis the resolution actually used. Withbucket=autoit israwfor windows up to 24 hours, then1m,1hor1d, whichever is finest under 10,000 buckets.- With a bucket,
tsis the start of the bucket (UTC aligned) andvaluethe 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;aggis 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
| Limit | Value |
|---|---|
| Keys per request | 50 |
| Points per key | 10,000 (limit) |
| Buckets in a window | 10,000 at the chosen resolution, else 400 range_too_large |
| Raw values | Only inside your raw retention (at most 90 days) |
| Minute buckets | Only inside the minute retention (at most 31 days) |
| Requests | The API rate limit; 429 with Retry-After when exceeded. See Errors and rate limits. |
Errors
| Status | Body | Cause |
|---|---|---|
| 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 / 403 | No 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) |
| 429 | Rate limit |
Paging through raw values
A raw read returns at most 10,000 points per key, oldest first. To read more:
- Request
bucket=raw&limit=10000for your window. - If a key returned 10,000 points, request again with
fromset to the last point’sts+ 1. - Repeat until a key returns fewer than
limitpoints.
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
| Route | Does |
|---|---|
GET /api/telemetry/kinds | The kinds of readings your organisation has (for example iot_device) |
GET /api/iot/devices/{deviceId}/elements | The 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.

