Docs/Apio IoT Platform/Platform core

Historical Data and Export

Read timeseries older than the project's retention period, query any time range with a single request, and export data to Excel.

Retention period

Every project has a retention period, two years unless agreed otherwise with Apio. Values within the retention period are kept in the platform’s primary storage and are the fastest to read. Older values are moved to historical storage, where they remain available for queries.

The boundary is computed at the start of the day: with a two-year retention, on 2 October 2026 everything before 2 October 2024 at 00:00 is historical data.

Choosing the query endpoint

All three endpoints accept the same queries and pipelines described in Query Timeseries:

EndpointReadsUse it when
/telemetry/queryValues within the retention periodYou need recent data
/historical/queryHistorical values onlyYou need data older than the retention period
/unified/queryBothThe time range may cross the retention boundary, or you don’t want to care about it
GEThttps://api.apio.network/projects/{projectId}/unified/query?q=JSON_QUERY
POSThttps://api.apio.network/projects/{projectId}/unified/query
GEThttps://api.apio.network/projects/{projectId}/historical/query?q=JSON_QUERY

/unified/query splits the time range at the retention boundary, reads each part from the right storage and returns a single, continuous result. The response has the same format as /telemetry/query.

/historical/query responds with 400 Bad Request when timeFrom is within the retention period. When only timeTo is within the retention period, the result stops at the boundary.

Note

Historical and unified queries only accept the series form of the query. Use devices/{deviceId}/{property} instead of deviceId and name.

Apache Arrow results

For large results, the unified endpoint can return an Apache Arrow table instead of JSON arrays. This variant accepts a single query object, not an array:

POSThttps://api.apio.network/projects/{projectId}/unified/arrow/query
JSON
{
  "query": {
    "series": ["devices/meter-1/power"],
    "timeFrom": "2026-01-01T00:00:00.000Z",
    "timeTo": "2026-01-02T00:00:00.000Z"
  },
  "pipeline": [
    { "resample": { "interval": 900000, "operation": "avg", "from": "2026-01-01T00:00:00.000Z", "to": "2026-01-02T00:00:00.000Z" } }
  ]
}

The response is JSON, and data holds the bytes of the Arrow table in IPC format as an array of numbers. The table has a time column, in milliseconds since the Unix epoch, and one column per series:

JavaScript
import { tableFromIPC } from 'apache-arrow';

const res = await fetch(`https://api.apio.network/projects/${projectId}/unified/arrow/query`, {
  method: 'POST',
  headers: { Authorization: `apikey ${apiKey}`, 'Content-Type': 'application/json' },
  body: JSON.stringify(query),
});
const { data } = await res.json();
const table = tableFromIPC(Uint8Array.from(data));

for (const row of table) {
  console.log(new Date(row.time), row['devices/meter-1/power']);
}

A GET variant is also available, with the query passed in the q parameter.

Export to Excel

Values can be downloaded as an Excel file:

GEThttps://api.apio.network/projects/{projectId}/telemetry/export
ParameterRequiredDescription
deviceIdyesOne or more device ids
nameyesOne or more property names
timeFrom, timeTonoTime range. Defaults to the last hour
aggregationTypenoraw (default), quarter, hourly or daily
timezonenoTime zone used for the timestamps. Defaults to Europe/Rome
localenoLocale used to format the timestamps. Defaults to it-IT

To pass more than one device or property, repeat the parameter:

Shell
curl -G "https://api.apio.network/projects/$PROJECT_ID/telemetry/export" \
  -H "Authorization: apikey $APIO_API_KEY" \
  --data-urlencode "deviceId=meter-1" \
  --data-urlencode "name=activeEnergy" \
  --data-urlencode "name=activePower" \
  --data-urlencode "timeFrom=2026-09-01T00:00:00.000Z" \
  --data-urlencode "timeTo=2026-10-01T00:00:00.000Z" \
  --data-urlencode "aggregationType=hourly" \
  -o export.xlsx

The file contains one sheet per device, with a timestamp column and one column per property. Column headers use the property’s display name and unit of measurement from the device type.

With an aggregationType other than raw, the export contains the aggregated series of that period. Every exported property must declare an aggregation for that period in its device type.

Note

Exports read values within the retention period and cover at most about two years per request; longer ranges are rejected with 400 Bad Request.

Type to search guides and API endpoints.