GET Device Readings
Pull time-series measurements for a single device with GET /v5/devices/{device_id}/data — parameters, response schema, pagination, and code examples in five languages.
GET /v5/devices/{device_id}/data
Retrieves time-series measurements for a single device. Get the device_id from List Devices, then call this endpoint to pull the device's readings over a date range, timestamp range, or relative window.
Authentication
Authenticated with your API key in the X-API-Key header; the user is resolved from the key. Access requires an Administrator, Editor, or User role in the device's organization. See Authentication and Data access control in the Overview.
Explore the interactive v5 endpoint in the OpenAPI/Swagger reference.
Request
Path parameters
Parameter | Type | Required | Description |
| string | Yes | The unique identifier of the device. Example: |
Query Parameters
Parameter | Type | Default | Description |
| string |
| Order in which data is retrieved and displayed by date. One of |
| string (ISO 8601) | - | Start of the window as an ISO datetime string. A datetime without a timezone is treated as UTC. Example: |
| string (ISO 8601) | - | End of the window as an ISO datetime string. A datetime without a timezone is treated as UTC. Example: |
| integer | - | Start of the window as a Unix timestamp (seconds since 1970-01-01 UTC). Example: |
| integer | - | End of the window as a Unix timestamp (seconds since 1970-01-01 UTC). Example: |
| string | - | A relative time range measured back from the time of the request (server time, UTC). Written as |
| string |
| The units the data returns in. One of |
| string | - | The token needed to retrieve the next pagination set. See Pagination below. |
start_datetime / end_datetime), the timestamp pair (start_timestamp / end_timestamp), or a relative window. Combining them returns 422.window value must be a positive whole number followed by a single lowercase unit character. Any other form — decimals, negatives, zero, uppercase units, long unit names, whitespace, or a bare number — returns 422.Example requests
cURL
curl --request GET \
--url 'https://api.zentracloud.io/v5/devices/z6-00930/data?start_datetime=2026-05-29T00%3A00%3A00-00%3A00&end_datetime=2026-05-30T23%3A59%3A00-00%3A00&direction=descending&units=metric' \
--header 'Accept: */*' \
--header 'X-API-Key: YOUR_API_KEY'
curl --request GET \
--url 'https://api.zentracloud.io/v5/devices/z6-00930/data?window=24h&direction=descending&units=metric' \
--header 'Accept: */*' \
--header 'X-API-Key: YOUR_API_KEY'
JavaScript — Fetch
const url = 'https://api.zentracloud.io/v5/devices/z6-00930/data?start_datetime=2026-05-29T00%3A00%3A00-00%3A00&end_datetime=2026-05-30T23%3A59%3A00-00%3A00&direction=descending&units=metric';
const options = {
method: 'GET',
headers: { 'X-API-Key': 'YOUR_API_KEY', Accept: '*/*' }
};
try {
const response = await fetch(url, options);
const data = await response.json();
console.log(data);
} catch (error) {
console.error(error);
}
Python — Requests
import requests
url = "https://api.zentracloud.io/v5/devices/z6-00930/data"
querystring = {
"start_datetime": "2026-05-29T00:00:00-00:00",
"end_datetime": "2026-05-30T23:59:00-00:00",
"direction": "descending",
"units": "metric",
}
headers = {
"X-API-Key": "YOUR_API_KEY",
"Accept": "*/*",
}
response = requests.get(url, headers=headers, params=querystring)
print(response.json())
PHP — cURL
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.zentracloud.io/v5/devices/z6-00930/data?start_datetime=2026-05-29T00%3A00%3A00-00%3A00&end_datetime=2026-05-30T23%3A59%3A00-00%3A00&direction=descending&units=metric",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: */*",
"X-API-Key: YOUR_API_KEY",
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
R — httr
library(httr)
url <- "https://api.zentracloud.io/v5/devices/z6-00930/data"
queryString <- list(
start_datetime = "2026-05-29T00:00:00-00:00",
end_datetime = "2026-05-30T23:59:00-00:00",
direction = "descending",
units = "metric"
)
response <- VERB("GET", url, query = queryString,
add_headers('X-API-Key' = 'YOUR_API_KEY'),
accept("*/*"))
content(response, "text")
Response
A 200 OK returns the device's measurements for the requested window, with a next_token when more pages are available.
metadata
Describes the device the readings belong to.
Field | Type | Description |
| string | The unique identifier (serial) of the device. |
| string | The device's display name. Defaults to the |
| string | The folder path the device sits in, for example |
| string | The device's latitude and longitude, comma-separated. |
values []
Each item is a single measurement from one sensor port at one point in time. Ordering follows the direction parameter.
Field | Type | Description |
| integer | The sensor port the reading came from. |
| string | The measured quantity (e.g. |
| string | The unit of |
| string | The sensor that produced the reading (e.g. |
| number | The measured value. |
| integer | The reading time as a Unix timestamp (seconds since the epoch, UTC). |
| string | The reading time as a human-readable datetime with UTC offset. |
| integer | |
error_code is still returned — the sensor reported a problem rather than a value, so the row is present with the code attached rather than being dropped.pagination
Field | Type | Description |
| integer | The number of readings returned on this page. |
| string | null | The token to pass on the next request to fetch the following page, or |
| string (ISO 8601) | The start of the window covered by this page. |
| string (ISO 8601) | The end of the window covered by this page. |
| string | null | A ready-to-use URL that fetches the next page. Follow it exactly as given. |
Example response
{
"metadata": {
"device_id": "A4100123",
"device_name": "JersyField",
"location": "Upper East Field",
"coordinates": "40.6673487, -74.61492299999999"
},
"values": [
{
"port_num": 1,
"measurement": "Gust Speed",
"unit": "m/s",
"sensor_name": "ATMOS 41W",
"value": 0.53,
"timestamp": 1771401600,
"datetime": "2026-02-18 00:00:00-08:00",
"error_code": 0
},
{
"port_num": 1,
"measurement": "Gust Speed",
"unit": "m/s",
"sensor_name": "ATMOS 41W",
"value": 0.57,
"timestamp": 1771400700,
"datetime": "2026-02-17 23:45:00-08:00",
"error_code": 0
}
// ... additional readings omitted for brevity
],
"pagination": {
"num_readings":
97, "next_token":
"AErxaX_LHGoA",
"next_url": "https://api.zentracloud.io/v5/devices/A4100123/data?direction=descending&latest=false&units=metric&next_token=AErxaX_LHGoA",
"start_datetime": "2026-02-17T08:00:00Z",
"end_datetime": "2026-02-18T08:00:00Z" }
}Pagination
The simplest way to page is to follow next_url. It already carries the correct path, your choices such as units and direction, and the new token — so you do not have to rebuild the URL yourself. Keep following it until it comes back null.
next_url deliberately leaves out the time-window parameters (start_datetime, end_datetime, start_timestamp, end_timestamp, and window). The token already encodes the remaining window and the sort direction, so carrying the original time parameters forward would conflict with it. Because window resolves against the server clock at request time, this also means a paged window is fixed at the first request and does not shift as you follow next_url.
If you would rather build requests yourself, pass the returned next_token back as the next_token parameter.
When requesting data in descending order (newest first), the first page contains only the portion of the current month up to your requested end_datetime or end_timestamp. As a result, this initial page is often smaller than subsequent pages, which each contain a full calendar month of data.
Rate limiting
Rate limited per device, not per user. The budget belongs to the device and is shared by every client reading it, so another integration polling the same device can exhaust it. See Rate Limiting.
HTTP Status Codes
Status | Endpoint-specific cause |
| You lack an Administrator/Editor/User role in the device's organization. |
| Mixing |
See HTTP Status Codes for the full model, including 401 and 429.
Notes
- Carry the
device_idfrom List Devices into the path. - Timestamps are seconds since the Unix epoch (UTC).
How did we do?
GET List Devices