# tounify API > Normalized European electricity tariff and day-ahead price data over a REST API. Four endpoints, > JSON, bearer auth. This file is written for LLM agents integrating against the API. - Base URL: `https://api.tounify.io` - Machine-readable spec: `/openapi/v2.json` (also `/openapi/v2.yaml`) — OpenAPI 3, generated from the live controllers, so it cannot drift from the API. Read it for the full parameter and response schemas; this file covers what the schema alone will not tell you. - Human reference: `https://api.tounify.io` (needs JavaScript) ## Getting a token Register at `https://cockpit.tounify.io/register`. A testing token is issued immediately — no credit card, no sales call. Copy it from the Token page. The testing token is capped on **breadth, not request count**: 20 different companies and 20 different tariffs over its lifetime, 5 newly explored scopes per day, and 7 days of validity (renewable). Asking again about something you already looked up is free and never counts again. So explore deliberately: list first, pick one, then price it. Send it on every `/v2` request: ``` Authorization: Bearer ``` ## Vocabulary - `{country}` — ISO 3166-1 alpha-2, case-insensitive. `DE` not `GER`, `GB` not `UK`. The accepted set is published as an enum on the `country` path parameter in the spec. - `{sector}` — `consumption` (energy the customer buys), `feedin` (energy they export), or `grid` (the network operator's charge). It is a **path segment**, not a query parameter. - Company ids and tariff ids are opaque short strings (`EWE`, `EWEM`). A tariff id is not a company id, and the two are not interchangeable anywhere. - A *version* is the day a tariff configuration took effect, formatted `YYYYMMDD`. ## Reaching a price takes three calls A tariff belongs to a company, so listing tariffs requires the company id in the path. ```bash # 1. Which suppliers exist? curl -H "Authorization: Bearer $TOKEN" \ https://api.tounify.io/v2/DE/consumption/companies # 2. Which tariffs does one of them offer? (company id in the path — this is the step most # integrations get wrong by omitting it) curl -H "Authorization: Bearer $TOKEN" \ https://api.tounify.io/v2/DE/consumption/EWE/tariffs # 3. What does that tariff cost? curl -H "Authorization: Bearer $TOKEN" \ "https://api.tounify.io/v2/DE/dayahead?consumption_tariff=EWEM&include=fees,vat" ``` A fourth endpoint lists the historic versions of a tariff: ``` GET /v2/{country}/{sector}/{tariff}/versions ``` ## Getting the price right This is where a technically valid call still returns the wrong number. - **The consumption tariff is usually the bare energy price.** In an unbundled market it does not contain the network charge. Pass `grid_tariff` as well, and `include=fees,vat`, to get what a customer actually pays. - **`include` takes `fees`, `vat`, or both**, comma-separated. Omitting them understates the price. - **`postal_code`** selects location-specific regulatory fees and grid areas. Without it, only country-wide fees apply in countries where fees vary by location. - **Check the `warnings` array on every response.** It is absent when nothing was dropped, and every code in it means the returned price is narrower than the one you asked for — `location_dependent_fees_omitted`, `grid_tariff_not_applicable`, `grid_tariff_ignored_for_all_in_tariff`, `fees_not_applicable`, `default_band_schedule_used`. Treat a populated array as a signal to widen the request, not as noise. - **Sum the components.** A price point carries `energy`, `grid`, `power`, `fees` and `vat` separately; the total is their sum. They are deliberately not pre-blended. - `resolution` is in **seconds**: `3600`, `1800` or `900`. `historic_days` caps at **3**. - Prices are per kWh, net of VAT unless `include=vat`, in the country's major currency. ## Before you authenticate ``` GET /public/country-stats ``` No token required. Returns, per country, how many companies and tariffs exist per sector, how many postal codes resolve to a grid operator, and whether regulatory fee data is available. A country the `country` enum accepts may still hold no data yet — this is how you tell. ## Errors - `400` — unknown country or sector, an id that does not exist, a tariff belonging to a different country than the path, `historic_days` above 3, or an unsupported `resolution`. - `401` — missing or malformed `Authorization` header. - `403` — no active subscription, or a testing token that has used up its company or tariff allowance. The body carries a `testingLimit` block naming what ran out. - `429` — daily allowance exhausted. The body and the `X-RateLimit-*` headers carry `resetAt`; read that rather than retrying on a fixed interval. - `500` — the price series could not be produced. Retrying an identical request returns the same result. There is deliberately **no 404**: an unknown id is a `400`. ## Versioning `/v2` is current. `/v1` is deprecated, still served for existing integrations, and should not be used for new work.