{"openapi":"3.0.0","paths":{"/v2/{country}/{sector}/companies":{"get":{"description":"Let your customer choose their own supplier for consuming or feeding in energy.","operationId":"listCompanies","parameters":[{"name":"country","required":true,"in":"path","description":"Two digit country code (ISO 3166-1 alpha-2), e.g. `DE` not `GER` and `GB` not `UK`. Case-insensitive. A code outside this list is a 400; a code inside it may still hold no data yet — GET /public/country-stats reports what each country currently carries.","schema":{"enum":["AT","BE","BG","CH","CY","CZ","DE","DK","EE","ES","FI","FR","GB","GR","HR","HU","IE","IT","LT","LU","LV","MC","MT","NL","NO","PL","PT","RO","SE","SI","SK"],"type":"string"}},{"name":"sector","required":true,"in":"path","description":"Which side of the meter to price: `consumption` (energy your customer buys), `feedin` (energy they export) or `grid` (the network operator's charge).","schema":{"enum":["consumption","feedin","grid"],"type":"string"}},{"name":"postal_code","required":false,"in":"query","description":"Customer postal code. For the grid sector it narrows the list to the operator serving that address, resolved via the postal→grid-operator map. Coverage varies by country — GET /public/country-stats reports the number of mapped postal codes per country. An address the map does not cover yet returns an empty list. The exception is a market whose grid price is set nationally rather than per distributor: there an uncovered address still returns the correct price, because it is identical whichever distributor serves it — only the operator name attached to it may be a regional guess rather than a mapped answer. Several markets work this way, and which ones changes as regulators reorganise, so treat a populated result for an unmapped address as normal rather than inferring the list. Ignored for the consumption and feed-in sectors, where suppliers operate nationwide.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CompanyDTO"}}}}},"400":{"description":"Unknown `country` (not a supported ISO 3166-1 alpha-2 code) or unknown `sector`. Also returned for an unknown or malformed query parameter. Note the public API never returns 404 — an unknown id is a 400.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicErrorDTO"},"example":{"statusCode":400,"message":"No tariff found for id ETID1"}}}},"401":{"description":"Missing `Authorization: Bearer <token>` header, a malformed header, or a token that is unknown, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicErrorDTO"},"example":{"statusCode":401,"message":"Missing or invalid Authorization header"}}}},"403":{"description":"The token is recognised but not entitled to this request: the subscription is not active, the requested country is not among the countries enabled for your token, the token is a testing token used on a `/v1` route (testing tokens can only access `/v2`), the testing token has expired (regenerate it on the cockpit Token page), or the testing token has already queried as many different energy companies or tariffs as it is allowed to. In that last case the body carries a `testingLimit` block naming which allowance ran out and which ids were refused; ids you have queried before stay available. That allowance is a total, not a daily one, so it does not reset — write to connect@tounify.io to have it raised.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicForbiddenErrorDTO"},"example":{"statusCode":403,"message":"Token is not entitled to this request"}}}},"429":{"description":"Request limit exceeded. The response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, and the body repeats the limit and the reset time. Also returned when a testing token has another request still in flight — a testing token may make one request at a time, so send them one after another rather than in parallel. Only testing tokens are subject to these limits — normal API-token integrations are not.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRateLimitErrorDTO"},"example":{"statusCode":429,"message":"Request limit exceeded","error":"Too Many Requests","rateLimit":{"limit":5,"remaining":0,"resetAt":"2026-08-07T00:00:00.000Z"}}}}}},"security":[{"bearer":[]}],"summary":"List energy companies","tags":["v2"]}},"/v2/{country}/{sector}/{company}/tariffs":{"get":{"description":"List the available tariffs of a company so your customer can select their tariff.","operationId":"listTariffs","parameters":[{"name":"country","required":true,"in":"path","description":"Two digit country code (ISO 3166-1 alpha-2), e.g. `DE` not `GER` and `GB` not `UK`. Case-insensitive. A code outside this list is a 400; a code inside it may still hold no data yet — GET /public/country-stats reports what each country currently carries.","schema":{"enum":["AT","BE","BG","CH","CY","CZ","DE","DK","EE","ES","FI","FR","GB","GR","HR","HU","IE","IT","LT","LU","LV","MC","MT","NL","NO","PL","PT","RO","SE","SI","SK"],"type":"string"}},{"name":"sector","required":true,"in":"path","description":"Which side of the meter to price: `consumption` (energy your customer buys), `feedin` (energy they export) or `grid` (the network operator's charge).","schema":{"enum":["consumption","feedin","grid"],"type":"string"}},{"name":"company","required":true,"in":"path","description":"ID of the company","schema":{"example":"CID1","type":"string"}},{"name":"type","required":false,"in":"query","description":"Narrow the list down to dynamic or static tariffs.","schema":{"enum":["dynamic","static"],"type":"string"}},{"name":"available","required":false,"in":"query","description":"Only return tariffs that are still offered by the supplier (available=true). Pass false to return only tariffs that are no longer offered.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PublicTariffDTO"}}}}},"400":{"description":"Unknown `country` or `sector`, or a `company` id that does not exist. Also returned for an unknown or malformed query parameter. Note the public API never returns 404 — an unknown id is a 400.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicErrorDTO"},"example":{"statusCode":400,"message":"No tariff found for id ETID1"}}}},"401":{"description":"Missing `Authorization: Bearer <token>` header, a malformed header, or a token that is unknown, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicErrorDTO"},"example":{"statusCode":401,"message":"Missing or invalid Authorization header"}}}},"403":{"description":"The token is recognised but not entitled to this request: the subscription is not active, the requested country is not among the countries enabled for your token, the token is a testing token used on a `/v1` route (testing tokens can only access `/v2`), the testing token has expired (regenerate it on the cockpit Token page), or the testing token has already queried as many different energy companies or tariffs as it is allowed to. In that last case the body carries a `testingLimit` block naming which allowance ran out and which ids were refused; ids you have queried before stay available. That allowance is a total, not a daily one, so it does not reset — write to connect@tounify.io to have it raised.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicForbiddenErrorDTO"},"example":{"statusCode":403,"message":"Token is not entitled to this request"}}}},"429":{"description":"Request limit exceeded. The response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, and the body repeats the limit and the reset time. Also returned when a testing token has another request still in flight — a testing token may make one request at a time, so send them one after another rather than in parallel. Only testing tokens are subject to these limits — normal API-token integrations are not.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRateLimitErrorDTO"},"example":{"statusCode":429,"message":"Request limit exceeded","error":"Too Many Requests","rateLimit":{"limit":5,"remaining":0,"resetAt":"2026-08-07T00:00:00.000Z"}}}}}},"security":[{"bearer":[]}],"summary":"List tariffs","tags":["v2"]}},"/v2/{country}/{sector}/{tariff}/versions":{"get":{"description":"List all the versions of a tariff. A version is the day a tariff configuration became effective. A tariff that is no longer offered still returns its versions here, matching GET /{country}/dayahead, which also keeps answering for an id you already use — so an existing integration is never cut off.","operationId":"listTariffVersions","parameters":[{"name":"country","required":true,"in":"path","description":"Two digit country code (ISO 3166-1 alpha-2), e.g. `DE` not `GER` and `GB` not `UK`. Case-insensitive. A code outside this list is a 400; a code inside it may still hold no data yet — GET /public/country-stats reports what each country currently carries.","schema":{"enum":["AT","BE","BG","CH","CY","CZ","DE","DK","EE","ES","FI","FR","GB","GR","HR","HU","IE","IT","LT","LU","LV","MC","MT","NL","NO","PL","PT","RO","SE","SI","SK"],"type":"string"}},{"name":"sector","required":true,"in":"path","description":"Which side of the meter to price: `consumption` (energy your customer buys), `feedin` (energy they export) or `grid` (the network operator's charge).","schema":{"enum":["consumption","feedin","grid"],"type":"string"}},{"name":"tariff","required":true,"in":"path","description":"ID of the tariff","schema":{"example":"TID1","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TariffVersionsDTO"}}}}},"400":{"description":"Unknown `country` or `sector`, or a `tariff` id that does not exist. Also returned for an unknown or malformed query parameter. Note the public API never returns 404 — an unknown id is a 400.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicErrorDTO"},"example":{"statusCode":400,"message":"No tariff found for id ETID1"}}}},"401":{"description":"Missing `Authorization: Bearer <token>` header, a malformed header, or a token that is unknown, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicErrorDTO"},"example":{"statusCode":401,"message":"Missing or invalid Authorization header"}}}},"403":{"description":"The token is recognised but not entitled to this request: the subscription is not active, the requested country is not among the countries enabled for your token, the token is a testing token used on a `/v1` route (testing tokens can only access `/v2`), the testing token has expired (regenerate it on the cockpit Token page), or the testing token has already queried as many different energy companies or tariffs as it is allowed to. In that last case the body carries a `testingLimit` block naming which allowance ran out and which ids were refused; ids you have queried before stay available. That allowance is a total, not a daily one, so it does not reset — write to connect@tounify.io to have it raised.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicForbiddenErrorDTO"},"example":{"statusCode":403,"message":"Token is not entitled to this request"}}}},"429":{"description":"Request limit exceeded. The response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, and the body repeats the limit and the reset time. Also returned when a testing token has another request still in flight — a testing token may make one request at a time, so send them one after another rather than in parallel. Only testing tokens are subject to these limits — normal API-token integrations are not.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRateLimitErrorDTO"},"example":{"statusCode":429,"message":"Request limit exceeded","error":"Too Many Requests","rateLimit":{"limit":5,"remaining":0,"resetAt":"2026-08-07T00:00:00.000Z"}}}}}},"security":[{"bearer":[]}],"summary":"List tariff versions","tags":["v2"]}},"/v2/{country}/dayahead":{"get":{"description":"Either one or both tariff IDs have to be supplied. If both are supplied, the price corresponds to the sum of both tariffs.","operationId":"getDayAheadPrices","parameters":[{"name":"country","required":true,"in":"path","description":"Two digit country code (ISO 3166-1 alpha-2), e.g. `DE` not `GER` and `GB` not `UK`. Case-insensitive. A code outside this list is a 400; a code inside it may still hold no data yet — GET /public/country-stats reports what each country currently carries.","schema":{"enum":["AT","BE","BG","CH","CY","CZ","DE","DK","EE","ES","FI","FR","GB","GR","HR","HU","IE","IT","LT","LU","LV","MC","MT","NL","NO","PL","PT","RO","SE","SI","SK"],"type":"string"}},{"name":"consumption_tariff","required":false,"in":"query","description":"ID of the consumption tariff. Provide a tariff ID (e.g. 'EWEM'), not a company code (e.g. 'EWE'). List a company's tariff IDs via the /{sector}/{companyId}/tariffs endpoint.","schema":{"maxLength":32,"example":"ETID1","type":"string"}},{"name":"feedin_tariff","required":false,"in":"query","description":"ID of the feed-in tariff. Provide a tariff ID (e.g. 'EWEM'), not a company code (e.g. 'EWE'). List a company's tariff IDs via the /{sector}/{companyId}/tariffs endpoint.","schema":{"maxLength":32,"example":"FTID1","type":"string"}},{"name":"grid_tariff","required":false,"in":"query","description":"ID of the grid tariff. Provide a tariff ID (e.g. 'EWEM'), not a company code (e.g. 'EWE'). List a company's tariff IDs via the /{sector}/{companyId}/tariffs endpoint.","schema":{"maxLength":32,"example":"GTID1","type":"string"}},{"name":"version","required":false,"in":"query","description":"A version is a date string in the YYYYMMDD format and represents the day an energy contract was signed. If set, the prices from the database entry closest in the past are used. If the version date is before the oldest entry, the prices of the oldest entry are used.","schema":{"example":"20230228","type":"string"}},{"name":"historic_days","required":false,"in":"query","description":"Number of historic days to include in the price info. Maximum is 3 days.","schema":{"example":2,"type":"number"}},{"name":"include","required":false,"in":"query","description":"Comma-separated list of extra price components to add on top of the market price. Supported values: 'fees' and 'vat'. 'fees' adds the country's regulatory/grid surcharges where they have been ingested; for a country with no fee data it adds nothing and the response carries warnings: ['fees_not_applicable']. GB is NOT such a country: the GB supplier price is held net of its network and policy costs, so omitting `include=fees` (or `postal_code`) understates a GB price by that whole layer and can even return a negative one — Octopus Zero Bills stores -0.0716 GBP/kWh, which only re-adds to its published 0.0 once both are passed. 'vat' adds the country's VAT on top of the summed components (consumption only) and works for any supported country. In an unbundled market the consumption tariff is the bare energy price, so pass `grid_tariff` as well — otherwise the response omits the grid component (warning ['grid_tariff_not_applicable'] when the country has no grid data) and understates the price.","schema":{"type":"array","items":{"type":"string","enum":["fees","vat"]}}},{"name":"resolution","required":false,"in":"query","description":"Price interval in seconds: 15min (900), 30min (1800) or 1h (3600). Resolutions are integer-ratio resampled: coarser requests average the finer prices, finer requests duplicate the coarser price. 1800 is used by UK Octopus Agile.","schema":{"enum":[3600,1800,900],"type":"number"}},{"name":"postal_code","required":false,"in":"query","description":"Customer postal code, resolved to the customer's grid area via the postal→grid-operator map (coverage varies by country — GET /public/country-stats reports the number of mapped postal codes per country). Relevant together with include=fees, where the resolved area selects the correct location-specific regulatory fees. Optional — when omitted in a country whose fees depend on location, only country-wide fees are applied and the response carries warnings: ['location_dependent_fees_omitted']. In a country whose grid tariff is set nationally, the grid charge is applied whether or not a postal code is supplied.","schema":{"maxLength":16,"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DayAheadV2DTO"}}}},"400":{"description":"Unknown `country`; no tariff id supplied; a tariff id that does not exist; a tariff that belongs to a different country than the path; `historic_days` above 3; or a `resolution` other than 3600, 1800 or 900. Also returned for an unknown or malformed query parameter. Note the public API never returns 404 — an unknown id is a 400.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicErrorDTO"},"example":{"statusCode":400,"message":"No tariff found for id ETID1"}}}},"401":{"description":"Missing `Authorization: Bearer <token>` header, a malformed header, or a token that is unknown, expired or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicErrorDTO"},"example":{"statusCode":401,"message":"Missing or invalid Authorization header"}}}},"403":{"description":"The token is recognised but not entitled to this request: the subscription is not active, the requested country is not among the countries enabled for your token, the token is a testing token used on a `/v1` route (testing tokens can only access `/v2`), the testing token has expired (regenerate it on the cockpit Token page), or the testing token has already queried as many different energy companies or tariffs as it is allowed to. In that last case the body carries a `testingLimit` block naming which allowance ran out and which ids were refused; ids you have queried before stay available. That allowance is a total, not a daily one, so it does not reset — write to connect@tounify.io to have it raised.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicForbiddenErrorDTO"},"example":{"statusCode":403,"message":"Token is not entitled to this request"}}}},"429":{"description":"Request limit exceeded. The response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, and the body repeats the limit and the reset time. Also returned when a testing token has another request still in flight — a testing token may make one request at a time, so send them one after another rather than in parallel. Only testing tokens are subject to these limits — normal API-token integrations are not.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRateLimitErrorDTO"},"example":{"statusCode":429,"message":"Request limit exceeded","error":"Too Many Requests","rateLimit":{"limit":5,"remaining":0,"resetAt":"2026-08-07T00:00:00.000Z"}}}}},"500":{"description":"The price series could not be produced: no prices are published for the requested tariff and period, the tariff prices by time-of-use bands whose switching times are not yet available for the requested location, or the requested tariffs could not be combined into one series. Retrying an identical request will usually return the same result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicErrorDTO"},"example":{"statusCode":500,"message":"No new prices available for ETID1"}}}}},"security":[{"bearer":[]}],"summary":"Get day-ahead prices","tags":["v2"]}},"/public/country-stats":{"get":{"description":"What each supported country currently carries: how many companies and tariffs exist per sector, how many postal codes resolve to a grid operator, and whether regulatory fees are available. **No token is required**, so this is the call to make first — it tells you whether the country you want is populated before you integrate against it.\n\nThe keys are ISO 3166-1 alpha-2 codes. They are a subset of what the `country` path parameter accepts: a country the parameter accepts but that appears nowhere here has no data at all yet, and one listed with zero companies is reachable but still empty.","operationId":"getCountryStats","parameters":[],"responses":{"200":{"description":"Coverage keyed by ISO 3166-1 alpha-2 country code.","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/CountryStatsDTO"},"example":{"AT":{"companies":{"consumption":144,"feedin":67,"grid":129,"total":145},"tariffs":{"consumption":821,"feedin":128,"grid":469},"postalCodes":2229,"hasFees":true,"feeCoverageComplete":true}}}}}}},"summary":"Coverage per country","tags":["public"]}}},"info":{"title":"tounify.io API","description":"__tounify__ automatically collects electricity tariff data from a large number of suppliers throughout Europe.\n\n**Getting started takes no sales call.** Register at https://cockpit.tounify.io/register and a\ntesting token is issued to you immediately — no credit card. It is meant for evaluation, so it is\ncapped on breadth rather than on request count: 20 different companies and 20 different tariffs over\nits lifetime, 5 newly explored scopes per day, and 7 days of validity, renewable from the Token page.\nAsking again about something you already looked up is free and never counts against either\nallowance. Write to connect@tounify.io only for a custom or volume plan.\n\nTo get the price info follow these steps:\n1. **List energy companies** – let your customer choose their own supplier for consuming or feeding in energy.\n2. **List energy tariffs** – use the selected company's ID to filter for available tariffs and let your customer select their tariff.\n3. **Get the day-ahead prices** on a daily basis using the consumption, feed-in and/or grid tariff selected by your customer.\n\n`GET /public/country-stats` needs no token at all and reports which countries currently carry\ncompanies, tariffs, postal-code coverage and regulatory fees — use it to check reachability before\nyou authenticate.","version":"2.0.0","contact":{"name":"tounify","url":"https://tounify.io","email":"connect@tounify.io"}},"tags":[{"name":"v2","description":"Current, stable version of the tounify API. Use these endpoints for new integrations."},{"name":"public","description":"Open endpoints that need no token. Use them to check reachability and coverage before you authenticate."}],"servers":[{"url":"https://api.tounify.io"}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"API token for your organisation. Register at https://cockpit.tounify.io/register to be issued a testing token immediately, then copy it from the Token page. Send it as `Authorization: Bearer <token>`."}},"schemas":{"CompanyDTO":{"type":"object","properties":{"id":{"type":"string","description":"Unique ID of the company","example":"CID1"},"name":{"type":"string","description":"Public name of the company","example":"Energy Supplier A"},"country":{"type":"string","description":"Two digit country code (ISO 3166-1 alpha-2)","example":"AT"},"url":{"type":"string","description":"Link to the company website","example":"https://www.energy-supplier.com"}},"required":["id","name","country"]},"PublicErrorDTO":{"type":"object","properties":{"statusCode":{"type":"number","description":"HTTP status code, repeated in the body","example":400},"message":{"type":"string","description":"Human-readable cause. Not a stable identifier — do not branch on its text.","example":"No tariff found for id ETID1"}},"required":["statusCode","message"]},"PublicTestingLimitDTO":{"type":"object","properties":{"kind":{"type":"string","description":"Which allowance ran out: 'companies' or 'tariffs'.","example":"tariffs"},"limit":{"type":"number","description":"How many different ones this testing token may query in total","example":5},"used":{"type":"number","description":"How many have been queried so far","example":5},"remaining":{"type":"number","description":"How many are still available","example":0},"blocked":{"description":"The ids in this request that are not covered yet. Drop them, or reuse ids you have already queried, and the request succeeds.","example":["ETID42"],"type":"array","items":{"type":"string"}}},"required":["kind","limit","used","remaining","blocked"]},"PublicForbiddenErrorDTO":{"type":"object","properties":{"statusCode":{"type":"number","description":"HTTP status code, repeated in the body","example":400},"message":{"type":"string","description":"Human-readable cause. Not a stable identifier — do not branch on its text.","example":"No tariff found for id ETID1"},"error":{"type":"string","description":"Status text","example":"Forbidden"},"testingLimit":{"description":"Present only when a testing token was refused for having exhausted its allowance of different companies or tariffs. Names which allowance ran out and which ids were refused. Absent on every other 403 — a token without an active subscription, for example.","allOf":[{"$ref":"#/components/schemas/PublicTestingLimitDTO"}]}},"required":["statusCode","message"]},"PublicTariffDTO":{"type":"object","properties":{"id":{"type":"string","maxLength":32,"description":"Unique ID of the tariff","example":"ETID1"},"companyid":{"type":"string","description":"Unique ID of the company that offers the tariff","example":"CID1"},"name":{"type":"string","description":"Public name of the tariff","example":"Tariff Name 1"},"link":{"type":"string","nullable":true,"description":"Link to the tariff information page","example":"https://www.energy-utility.com/tariff-name1"},"description":{"type":"string","nullable":true,"description":"Short description of the tariff","example":null},"type":{"nullable":true,"enum":["static","dynamic"],"type":"string","description":"'dynamic' means the price is derived from a market price; 'static' means the price changes follow a fixed scheme.","example":"dynamic"},"available":{"type":"boolean","description":"Whether the tariff is still offered by the supplier","example":true}},"required":["id","companyid","name","link","description","type","available"]},"PublicRateLimitDTO":{"type":"object","properties":{"limit":{"type":"number","description":"How many different things you may ask about per day on this endpoint","example":5},"remaining":{"type":"number","description":"How many more you may ask about before the window resets","example":0},"resetAt":{"type":"string","description":"ISO timestamp at which the window resets","example":"2026-08-07T00:00:00.000Z"}},"required":["limit","remaining","resetAt"]},"PublicRateLimitErrorDTO":{"type":"object","properties":{"statusCode":{"type":"number","description":"HTTP status code, repeated in the body","example":400},"message":{"type":"string","description":"Human-readable cause. Not a stable identifier — do not branch on its text.","example":"No tariff found for id ETID1"},"error":{"type":"string","description":"Status text","example":"Too Many Requests"},"rateLimit":{"description":"How much of the daily allowance is left and when it resets. Read `resetAt` rather than retrying on a fixed interval — the window is a calendar day, not a rolling timer.","allOf":[{"$ref":"#/components/schemas/PublicRateLimitDTO"}]}},"required":["statusCode","message","error","rateLimit"]},"TariffVersionsDTO":{"type":"object","properties":{"version":{"type":"string","description":"Date string in the YYYYMMDD format","example":"20230228"},"available":{"type":"boolean","description":"Whether the tariff is still offered by the supplier","example":true}},"required":["version","available"]},"ShortTariffInfoDTO":{"type":"object","properties":{"id":{"type":"string","description":"ID of the chosen tariff","example":"TID1"},"type":{"nullable":true,"enum":["static","dynamic"],"type":"string","description":"'dynamic' means the price is derived from a market price; 'static' means the price changes follow a fixed scheme.","example":"dynamic"},"available":{"type":"boolean","description":"Whether the tariff is still offered by the supplier","example":true},"price_basis":{"type":"string","enum":["bare","all_in"],"description":"How the stored supply price is held. 'bare' — the price is the supply component alone, and the `grid` and `fees` components of this response are added on top of it. `all_in` — the price is stored as captured, already containing the grid and levy share, so no `grid` component is returned and a `grid_tariff` passed in the request is ignored (see the `grid_tariff_ignored_for_all_in_tariff` warning). Omitted when the tariff carries no marker.","example":"bare"}},"required":["type","available"]},"DayAheadV2PricePointDTO":{"type":"object","properties":{"from_utc":{"type":"number","description":"Start time of the price value as UNIX timestamp","example":1605636000},"energy":{"type":"number","description":"Energy price per kWh","example":0.123},"grid":{"type":"number","description":"Grid price per kWh","example":0.123},"power":{"type":"number","description":"Power component of the grid fee per kW","example":0.123},"fees":{"type":"number","description":"Additional country specific fees","example":0.123},"vat":{"type":"number","description":"VAT amount of the complete price value stack","example":0.123}},"required":["from_utc"]},"DayAheadV2DTO":{"type":"object","properties":{"consumption_tariff":{"description":"Present if a consumption tariff was selected","allOf":[{"$ref":"#/components/schemas/ShortTariffInfoDTO"}]},"feedin_tariff":{"description":"Present if a feed-in tariff was selected","allOf":[{"$ref":"#/components/schemas/ShortTariffInfoDTO"}]},"grid_tariff":{"description":"Present if a grid tariff was selected","allOf":[{"$ref":"#/components/schemas/ShortTariffInfoDTO"}]},"currency":{"enum":["","EUR","CHF","DKK","SEK","CZK","HUF","NOK","PLN","RON","GBP"],"type":"string","description":"Currency of the price value in ISO 4217 format. The price is always per kWh.","example":"EUR"},"country":{"type":"string","description":"Two digit country code (ISO 3166-1 alpha-2)","example":"AT"},"resolution":{"type":"number","description":"Seconds between the pricing values","example":3600},"next":{"type":"number","description":"Recommended time to request new pricing information (UNIX timestamp)","example":1605639624},"consumption":{"description":"Present if a consumption tariff was selected. Sum the components to get the total price.","type":"array","items":{"$ref":"#/components/schemas/DayAheadV2PricePointDTO"}},"feedin":{"description":"Present if a feed-in tariff was selected. Sum the components to get the total price.","type":"array","items":{"$ref":"#/components/schemas/DayAheadV2PricePointDTO"}},"warnings":{"description":"Non-fatal advisories. Documented codes:\n  - 'location_dependent_fees_omitted' — fees were requested for a country with\n    location-scoped common_fee rows, but no postal_code was provided (or it\n    did not resolve), so only country-wide fees were applied.\n  - 'grid_tariff_not_applicable' — a grid_tariff was passed for a retail-bundled\n    country that has no separate grid charge (e.g. GB); it was ignored.\n  - 'grid_tariff_ignored_for_all_in_tariff' — a grid_tariff was passed alongside a\n    consumption tariff whose stored price is all-in (already contains its grid share);\n    adding the grid would double-count it, so it was ignored (fees are likewise not added).\n    The tariff's own `price_basis` field reports the same thing, and is present whether or\n    not fees were requested.\n  - 'fees_not_applicable' — include=fees was requested for a country with no\n    common_fee rows (e.g. GB, where all costs are bundled into the energy price).\n  - 'default_band_schedule_used' — the tariff prices by time-of-use bands whose switching\n    times belong to the grid operator, and no postal_code resolved one, so the country's\n    reference operator's clock was used. Pass a postal_code to bill on the customer's own.\n\nAbsent when nothing was omitted. Every code here means the returned price is narrower than\nthe one you asked for, so treat a populated array as a signal to widen the request rather\nthan as noise.","example":["location_dependent_fees_omitted"],"type":"array","items":{"type":"string"}}},"required":["currency","country","resolution","next"]},"CountryCompaniesStatsDTO":{"type":"object","properties":{"consumption":{"type":"number"},"feedin":{"type":"number"},"grid":{"type":"number"},"total":{"type":"number"}},"required":["consumption","feedin","grid","total"]},"CountryTariffsStatsDTO":{"type":"object","properties":{"consumption":{"type":"number"},"feedin":{"type":"number"},"grid":{"type":"number"}},"required":["consumption","feedin","grid"]},"CountryStatsDTO":{"type":"object","properties":{"postalCodes":{"type":"number","description":"Number of postal codes that resolve to a grid operator (postal-code → DSO coverage). 0 for countries without a postal-code mapping.","example":8100},"hasFees":{"type":"boolean","description":"Whether this country has regulatory fee/levy data (common_fee rows) that include=fees would add on top of the market and grid price. False for countries with no fee data, e.g. retail-bundled markets such as the UK (GB).","example":true},"feeCoverageComplete":{"type":"boolean","description":"Whether this country's regulatory fee layer is settled: either it has fee rows (hasFees), or research has established that the country levies no per-kWh fee at all. The two differ only where a market genuinely has nothing to charge — Monaco, whose sole statutory charge is VAT — so hasFees answers 'is there fee data?' while this answers 'do we know the fee answer?'. Use this for coverage reporting and hasFees to predict what include=fees will add.","example":true},"companies":{"$ref":"#/components/schemas/CountryCompaniesStatsDTO"},"tariffs":{"$ref":"#/components/schemas/CountryTariffsStatsDTO"}},"required":["postalCodes","hasFees","feeCoverageComplete","companies","tariffs"]}}}}