Energy Data · Quickstart

Quickstart

Fetch your first Dutch imbalance prices in under two minutes, with no API key.

There is no signup and no API key. Every endpoint below is public, and the only thing you need is a terminal.

Read the latest price

bash
curl https://api.tolven.eu/v0/series/imbalance-prices/latest

Each observation carries the value, the interval it applies to, and the publication_ts and revision it came from. You always know which revision you are looking at.

How fresh is latest

Imbalance settlement arrives in one batch per Dutch local day, not continuously. So the newest observation is normally between 1 and 25 hours old. It is youngest just after a batch lands and oldest just before the next one does. Plan around that shape rather than around a fixed interval. We poll far more often than upstream publishes, so our own delay is not what you are waiting on.

Measured 2026-08-16: upstream published at about 23:00 UTC on each of the previous 44 days. Before 2026-06-30 it published several hours later. The time also follows the Dutch local day rather than UTC, so expect it around 00:00 UTC while the Netherlands is on winter time. Treat that clock time as an observation of recent behaviour, not as a schedule, and build on the shape instead.

Read a window

bash
curl "https://api.tolven.eu/v0/series/imbalance-prices?from=2026-07-01T00:00:00Z&to=2026-07-02T00:00:00Z"

A window spans at most 31 days, one whole calendar month. The API rejects a wider window with 400 rather than truncating it silently, so a partial answer is never mistaken for a complete one. For longer spans, pull history in bulk.

Ask what was known at a point in time

TenneT restates imbalance settlement after the fact. If you backtest against today’s values, you are trading on information you could not have had. Your returns will look better than they were.

Revisions are rare here, which is what makes them dangerous. Between 2026-06-18 and 2026-08-15 we observed one revision in 11,120 observations. That one moved a settlement price from €500.00/MWh to €113.49/MWh, thirteen days after the interval had closed. A backtest run against live data used the wrong value for that period, and nothing flagged it.

Add as_of and you get the latest revision known at that instant, with anything published later hidden:

bash
curl "https://api.tolven.eu/v0/series/imbalance-prices?from=2026-07-01T00:00:00Z&to=2026-07-02T00:00:00Z&as_of=2026-07-02T00:00:00Z"

Same window, same series — but the values as they stood the moment the day closed, not as they were later restated.

One boundary to know about. Every series and bulk response carries revisions_observed_from: the instant the API started watching upstream. Points after it have true revision history. The API saw earlier points only retrospectively: their revision: 1 is the final settled value, not what was first published. Upstream serves no revision archive, so that earlier history cannot be reconstructed. The API rejects an as_of before the boundary with 400 rather than returning an empty result that would read as “nothing was known”. The gaps endpoint is live-only in v0, so it carries no boundary and takes no as_of.

Check for gaps before you trust a window

The API never interpolates gaps, so ask for them explicitly:

bash
curl "https://api.tolven.eu/v0/gaps/imbalance-prices?from=2026-01-01T00:00:00Z&to=2026-07-01T00:00:00Z"

You get interior gaps plus a coverage envelope: first_observed and last_observed per field. Absence outside the envelope is not a gap, so the API does not report it.

Pull history in bulk

For anything longer than a few days, skip JSON. The whole history is one object:

bash
curl -O https://api.tolven.eu/v0/bulk/imbalance-prices/full.parquet

That is every redistributable revision back to 2014-12-05 in a single request. Take it once, then stay current from the monthly partitions:

bash
curl https://api.tolven.eu/v0/bulk/imbalance-prices

Each month in the manifest carries its bounds, row count, byte size, ETag and an absolute URL. Frozen months keep stable URLs and ETags, so they cache indefinitely. Re-download only the months whose ETag moved, which is normally just the settlement tail.

python
import pandas as pd
df = pd.read_parquet("https://api.tolven.eu/v0/bulk/imbalance-prices/full.parquet")
# Every row carries publication_ts and revision, so point-in-time
# filtering is yours to do; no query engine required.
cutoff = pd.Timestamp("2026-08-01", tz="UTC")
known_at_cutoff = (
df[df["publication_ts"] <= cutoff]
.sort_values("revision")
.groupby(["field", "ts"], as_index=False)
.last()
)

Rate limits

The JSON endpoints allow 120 requests a minute per IP. Bulk downloads allow 60 a minute. Past a limit the API answers 429 with a Retry-After header; the limit resets within a minute. No workflow here needs many requests. The whole history is one download. Staying current after it costs one manifest read plus the months that moved. Higher limits do not exist yet. They would arrive with the paid tier. The energy-data page says how to ask for it.

Where to go next

MethodPathWhat it does
GET/v0/series/{dataset}Windowed reads, optionally as_of
GET/v0/series/{dataset}/latestMost recent observation per field
GET/v0/gaps/{dataset}Interior gaps plus a coverage envelope
GET/v0/bulk/{dataset}/full.parquetThe whole history in one Parquet
GET/v0/bulk/{dataset}Monthly Parquet manifest and downloads

Full parameters, response shapes and error codes live in the API reference. The running API generates it, so it cannot drift. Before you build on any of this in production, read attribution and licensing; it says what you may redistribute.