Reading many timeseries

Read the latest values of up to 2,000 timeseries in one call.

POST /timeseries/values returns the latest values of up to 2,000 timeseries over one shared time range, in one call. Use it when you need the same window from many entities, such as the schedules of every plant in a zone, instead of one values call per timeseries.

The timeseries are listed in a JSON body, so the list can be long. The call only reads: it is a POST because a request body has no length limit, where a URL does.

Request

Body fieldMeaning
seriesa list of {entity, name, provider}, 1 to 2,000 items: the same three things one values call names
start, endthe time range, shared by every series; both inclusive
cursorthe next of the previous page; send the rest of the body unchanged
curl -X POST "$API/timeseries/values" -H "X-API-Key: $KEY" -H "Content-Type: application/json" -d '{
  "start": "2026-11-03T12:00:00Z",
  "end": "2026-11-03T13:00:00Z",
  "series": [
    {"entity": "plant:18W000000000AI3J", "name": "production.per_unit.esios_p48_final_programme_injection", "provider": "esios"},
    {"entity": "plant:18W000000000F3DO", "name": "production.per_unit.esios_p48_final_programme_injection", "provider": "esios"},
    {"entity": "unit:18W000000000AI2L", "name": "production.per_unit.actual_generation_per_unit_a73.18w000000000ai2l", "provider": "entsoe"}
  ]
}'
P48 = "production.per_unit.esios_p48_final_programme_injection"
body = {
    "start": "2026-11-03T12:00:00Z",
    "end": "2026-11-03T13:00:00Z",
    "series": [
        {"entity": "plant:18W000000000AI3J", "name": P48, "provider": "esios"},
        {"entity": "plant:18W000000000F3DO", "name": P48, "provider": "esios"},
        {"entity": "unit:18W000000000AI2L",
         "name": "production.per_unit.actual_generation_per_unit_a73.18w000000000ai2l", "provider": "entsoe"},
    ],
}
blocks = []
while True:
    page = requests.post(f"{API}/timeseries/values", headers=HEADERS, json=body).json()
    blocks += page["series"]
    if not page["next"]:
        break
    body["cursor"] = page["next"]

for s in blocks:
    print(s["entity"], [p["value"] for p in s.get("points", [])])

The Python version prints:

plant:18W000000000AI3J [7.25, 7.25, 7.25, 7.0, 7.0]
plant:18W000000000F3DO [58.675, 56.7, 54.15, 51.375, 48.625]
unit:18W000000000AI2L []

Response

One block per series, in the order listed. A block is what the one-series values call returns for it (without as_of, which is on the page), so code that reads one reads the other.

{
  "start": "2026-11-03T12:00:00Z",
  "end": "2026-11-03T13:00:00Z",
  "as_of": "latest",
  "series": [
    {
      "entity": "plant:18W000000000AI3J",
      "name": "production.per_unit.esios_p48_final_programme_injection",
      "provider": "esios",
      "unit": "MWh",
      "resolution": null,
      "publication_time": "declared",
      "columns": ["value"],
      "points": [
        {"valid_time": "2026-11-03T12:00:00Z", "value": 7.25, "knowledge_time": "2026-11-03T13:55:20Z", "annotation": null},
        {"valid_time": "2026-11-03T12:15:00Z", "value": 7.25, "knowledge_time": "2026-11-03T13:55:20Z", "annotation": null},
        {"valid_time": "2026-11-03T12:30:00Z", "value": 7.25, "knowledge_time": "2026-11-03T13:55:20Z", "annotation": null},
        {"valid_time": "2026-11-03T12:45:00Z", "value": 7.0, "knowledge_time": "2026-11-03T13:55:20Z", "annotation": null},
        {"valid_time": "2026-11-03T13:00:00Z", "value": 7.0, "knowledge_time": "2026-11-03T13:55:20Z", "annotation": null}
      ]
    },
    {
      "entity": "plant:18W000000000F3DO",
      …
    },
    {
      "entity": "unit:18W000000000AI2L",
      "name": "production.per_unit.actual_generation_per_unit_a73.18w000000000ai2l",
      "provider": "entsoe",
      "unit": "MW",
      "resolution": "PT15M",
      …
      "points": []
    }
  ],
  "next": null
}

The A73 unit published nothing in that hour, so its points is empty; that is not an error. A series with several columns returns all of them, as values per point.

Errors per series

A series that cannot be read does not fail the call. Its block carries error instead of points, with the code and message the one-series call would have returned, and the rest of the list is still read:

{
  "entity": "plant:18W000000000AI3J",
  "name": "production.per_unit.esios_p48_programme",
  "provider": "esios",
  "error": {
    "code": "not_found",
    "message": "no timeseries 'production.per_unit.esios_p48_programme' on plant:18W000000000AI3J",
    "closest": ["production.per_unit.esios_p48_final_programme_injection"]
  }
}
codeWhen
not_foundthe entity, or the name on it, does not exist
bad_requestthe provider does not publish this timeseries (the error lists the ones that do), or the window holds more than 100,000 points at this series' resolution
platform_unavailablethe data platform did not answer for this series; ask for it again

The whole call is 400 only when the body itself is malformed: no series, more than 2,000, an item missing entity, name or provider, end before start, or a cursor this API did not issue for this list. It is 503 with Retry-After when the API is still loading its list of plants, units and portfolios (for a minute or two after it starts); send the same body again.

Paging

A page holds whole series, in the order listed, up to 200,000 points in total. When the next series would go over, the page stops and next is set: send the same body again with cursor set to it. A single series is still capped at 100,000 points, as in the one-series call, so a page always holds at least one series.

For example, 1,500 plant schedules over 120 days at quarter hours (about 11,500 points each) come back 17 series per page, in 89 calls instead of 1,500.

Limits

One call counts as one request against the rate limit, whatever the number of series. Without a key a call may list at most 5 series (Use without a key). Only the latest version is returned; for values as known at an earlier time (as_of), use the one-series values call.

On this page