Skip to content


Reading Data Structure

A reading is a parsed and human-readable unit of sensor data generated by a device, sent in a packet.

Packets can be accessed using the API, or pushed by a websocket.

In responses, a reading looks like this:

  "parser_id": "cee40cb2-f58c-4ca8-ae91-4ae76cba5119",
  "packet_id": "7ba0beee-1ea5-4a4b-b20c-75c2706c9710",
  "measured_at": "2017-08-02T09:11:04.910127Z",
  "location": null,
  "inserted_at": "2017-08-02T09:11:04.918087Z",
  "id": "07c04413-940b-4ee6-be99-da72a0321e25",
  "device_id": "43b5dca3-e7d9-4028-9309-c26ac0c08721",
  "data": {
    "foo": 96,
    "baz": 8,
    "bar": 35
Key Example Description
id 3e097a97-e504-4b4b-8182-ae148f2109f3 Unique reading ID (UUID4)
data {"foo": 96, "baz": 8, "bar": 35} JSON object that represents the parsed data
inserted_at 2017-07-31T12:15:18.289981Z When did the reading get inserted into the database
measured_at 2017-07-31T12:15:18.289981Z When did the measurement happen (may be provided by the device in the payload, infered from the receive time or simply be same as receive time)
parser_id cee40cb2-f58c-4ca8-ae91-4ae76cba5119 Reference to a parser which parsed the payload into the data
device_id 50e032fb-964f-440d-9b9a-47870667373c Reference to the device this reading belongs to
packet_id 50e032fb-964f-440d-9b9a-47870667373c Reference to the packet this reading belongs to
location {"location": {"type": "Point", "coordinates": [40.3684324046728, 42.221249216157474]}} GeoJSON point of the location where the reading was taken

List Readings

There are different ways to retrieve readings with the API:

  • by device ID GET /api/v1/devices/:id/readings
  • by device slug GET /api/v1/devices/:slug/readings
  • by selector, for example GET /api/v1/devices/by-eui/:eui/readings
  • by folder GET /api/v1/tags/:id_or_slug/readings

(parameters are denoted with a colon (:), which does not appear in the final API request)

Additionally, a streaming variant of all these endpoints is available, simply append /stream to any of these.

Query parameters

For all of the above endpoints, the available query parameters are the same:

Query Parameter Description
API Key or JWT
To go to the next page, pass the ID of the last reading from the result list here.
Read more about pagination
Field to sort the readings by
(default measured_at, inserted_at is also available)
asc or desc
Switch the sort direction
(default desc)
Integer 1-100
Control how many readings are loaded per page
(default 10)
when using streaming endpoints, the amount of readings is not limited by default
Only show readings measured before this date
Only show readings measured after this date
Expression that filters the readings.
The root schema of the filter is a reading.
simple filters use filters like inserted_before=2020

* = required parameter


  • /api/v1/devices/demo/readings?sort=inserted_at&retrieve_after=:uuid&auth=46cb688e2c0b468e26e914235d4b73ea

Paginating over readings by insertion date is possible by using the sort=inserted_at query parameter.

  • /api/v1/devices/by-eui/DEADAFFE00001111/readings?inserted_after=2020-11-11&auth=46cb688e2c0b468e26e914235d4b73ea

    Filtering for the inserted_at field can be useful if you need to synchronize readings with your applications database and the readings are dated back by the parser.

Notes on inserted_at vs. measured_at

Since the time of measurement may not be the time ELEMENT IoT will receive a packet and parse it to a reading, please take the following guidelines into account.

inserted_at is always the time a reading was stored by ELEMENT IoT into its database. measured_at is the time ELEMENT deems the reading to be measured at by the end-device.

There are different situations that will influence how measured_at and inserted_at differ or not:

  1. If the device is not signaling a measurement time that differs from the time the packet is send and there is no implicit rule on how to calculate a measurement time from the time of reception, then measured_at will be the time when ELEMENT receives and stores the measurement. Thus measured_at and inserted_at will be virtually the same - maybe differing be a few fractions of a second due to technical reasons.
  2. If the device is signaling a measured_at time, this one will be used and may be well adhead of inserted_at time.
  3. If a reparsing of packets is triggered any time later by a user, then inserted_at is the time the new readings is inserted_at (since reparsing means all readings of the affected device are deleted and new ones are created). Thus inserted_at may differ significantly from measured_at.

So if an external system is querying for readings using ELEMENTs API for a given timeframe at a given time, it may be that readings with a measured_at belonging into the timeframe are not yet inserted and thus cannot be included in the results yet, but will be at some later time. To really make sure that all readings are retreived considering above point, it may be best to either filter (using e.g. before and after parameters) on inserted_at or retrieve a timeframe for measured_at sufficently later (depending the timespan queryied devices take from measurement to transmission).

Reparsing will delete readings originating from the previous parsing. External systems should potentially no longer keep these readings. So a user triggering a reparse - it can't be triggered any other way - should consider this and take care of necessary steps in other systems.