Skip to main content

Endpoint

POST /api/v1/sites/{siteId}/timeseries
Query historical timeseries data for one or more points. Returns time-value pairs enriched with point metadata from the knowledge graph. For the latest value, use currentValue on the GraphQL Point type instead.
This endpoint uses timeseries IDs from the GraphQL API. First query your building’s points via the point query, then use the returned timeseriesId values to fetch historical data.

Path parameters

ParameterTypeDescription
siteIdstringSite ID

Request body

FieldTypeRequiredDefaultDescription
timeseriesIdsstring[]Yes-Array of timeseries UUIDs (1–200)
startstringNo"-1h"Start of time range. Accepts relative (-1h, -24h, -7d) or ISO-8601
endstringNo"now()"End of time range. Accepts relative, ISO-8601, or now()
windowstringNonullDownsampling window ("5m", "1h", "1d"). Omit for raw data
aggregatestringNo"mean"Aggregation: mean, min, max, sum, count, first, last
limitintegerNo1000Max records per series (1–10,000)

Response

FieldTypeDescription
queryobjectEcho of resolved query parameters
query.timezonestringIANA timezone of the site (e.g., Europe/London). All timestamps in data are in this timezone
seriesobject[]One entry per resolved point, enriched with metadata
series[].timeseriesIdstringTimeseries UUID
series[].namestringPoint display name
series[].typestringBrick class (e.g., Zone_Air_Temperature_Sensor)
series[].unitstringEngineering unit (e.g., degC)
series[].equipmentstringParent equipment name
series[].dataarrayTime-value pairs: t (ISO-8601 with UTC offset), v (number)
errorsobjectMap of unresolved timeseries IDs to error reasons

Pagination

REST list endpoints (e.g., /api/v1/sites/) support optional pagination via query parameters:
ParameterDefaultMaxDescription
limit-1000Number of items to return. Omit for all results.
offset0-Number of items to skip
When limit is provided, the response is wrapped in a paginated envelope:
{
  "count": 42,
  "next": "https://app.betacit.com/api/v1/sites/?limit=10&offset=10",
  "previous": null,
  "results": [ ... ]
}
Without limit, the response is a plain array.

Status codes

CodeDescription
200Success. Partial failures are reported in errors, not the status code
400Validation error (missing timeseriesIds, invalid aggregate, etc.)
401Not authenticated
403No access to this site
404Site not found
429Rate limit exceeded. Check the Retry-After header

Examples

cURL

curl -X POST https://app.betacit.com/api/v1/sites/your-site-id/timeseries \
  -H "Authorization: Bearer your-api-key-or-jwt-token" \
  -H "Content-Type: application/json" \
  -d '{
    "timeseriesIds": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "7c9e6679-7425-40de-944b-e07fc1f90ae7"
    ],
    "start": "-24h",
    "window": "5m",
    "aggregate": "mean"
  }'

Last 24 hours with 5-minute aggregation

Request
{
  "timeseriesIds": [
    "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "7c9e6679-7425-40de-944b-e07fc1f90ae7"
  ],
  "start": "-24h",
  "window": "5m",
  "aggregate": "mean"
}
Response
{
  "query": {
    "start": "-24h",
    "end": "now()",
    "timezone": "Europe/London",
    "window": "5m",
    "aggregate": "mean"
  },
  "series": [
    {
      "timeseriesId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "TW01-LBR-RPC-01/Space_Temp",
      "type": "Zone_Air_Temperature_Sensor",
      "unit": "degC",
      "equipment": "TW01-LBR-RPC-01",
      "data": [
        { "t": "2026-02-28T15:00:00+00:00", "v": 22.1 },
        { "t": "2026-02-28T15:05:00+00:00", "v": 22.3 },
        { "t": "2026-02-28T15:10:00+00:00", "v": 22.5 }
      ]
    },
    {
      "timeseriesId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "name": "TW01-LBR-RPC-01/Space_Temp_SP",
      "type": "Zone_Air_Temperature_Setpoint",
      "unit": "degC",
      "equipment": "TW01-LBR-RPC-01",
      "data": [
        { "t": "2026-02-28T15:00:00+00:00", "v": 22.0 },
        { "t": "2026-02-28T15:05:00+00:00", "v": 22.0 },
        { "t": "2026-02-28T15:10:00+00:00", "v": 22.0 }
      ]
    }
  ],
  "errors": {}
}

Peak temperatures over a week

Request
{
  "timeseriesIds": ["3fa85f64-5717-4562-b3fc-2c963f66afa6"],
  "start": "-7d",
  "window": "1h",
  "aggregate": "max",
  "limit": 168
}

Mixed valid and invalid IDs

When some timeseries IDs don’t resolve, the response includes both results and errors:
Request
{
  "timeseriesIds": [
    "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "00000000-0000-0000-0000-000000000000",
    "not-a-uuid"
  ]
}
Response
{
  "query": { "start": "-1h", "end": "now()", "timezone": "Europe/London" },
  "series": [
    {
      "timeseriesId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "TW01-LBR-RPC-01/Space_Temp",
      "type": "Zone_Air_Temperature_Sensor",
      "unit": "degC",
      "equipment": "TW01-LBR-RPC-01",
      "data": [{ "t": "2026-02-28T16:45:12+00:00", "v": 22.3 }]
    }
  ],
  "errors": {
    "00000000-0000-0000-0000-000000000000": "Point not found",
    "not-a-uuid": "Invalid timeseries ID format"
  }
}

Time format reference

Relative durations: -1h, -6h, -24h, -7d, -30d ISO-8601 timestamps: 2026-02-01T00:00:00Z Special values: now()

Timezone behaviour

Response timestamps are always in the site’s local timezone, declared in query.timezone. The UTC offset is embedded in every timestamp (e.g., +00:00 for London, +01:00 during BST), so you never need to convert manually. When an aggregation window is specified, all timestamps are snapped to the window boundary. For example, with window: "15m", timestamps align to :00, :15, :30, :45 in the site’s local time. Data is stored in UTC internally. The timezone conversion is applied on output only.

Aggregation windows

Use casewindowaggregate
Dashboard sparkline"5m""mean"
Hourly report"1h""mean"
Daily peak analysis"1d""max"
Energy totals"1h""sum"
Raw data exportomit-