Oil price API: price breakdown
Price breakdownWhat a litre is made of (taxes, crude, refining, distribution) in each EU country, or the parts as published in Thailand, Jamaica, South Africa, Uruguay and New Zealand, and how crude changes reach it.
What it is for
What a litre of petrol 95 or diesel is made of in an EU country, in the latest week: taxes, the crude oil cost, the refining margin and the distribution margin, each in euros a litre and as a share of the price. Taxes and the price before taxes add up to the price; crude, refining and distribution add up to the price before taxes. All of it is worked out from stored prices.
With it come the weekly figures on how the price moves, for the whole record since 2005 and for the last three years: the share of the weekly movement from each part, the pass-through (cents at the pump for a cent of crude after 8 weeks), the weeks by which half and nine tenths of it has come through, and the same for rises and falls apart. Leave out country for the countries we hold; each part's history is a series, named in series, to read with Series values.
For Thailand, Jamaica, South Africa, Uruguay and New Zealand, which publish the parts of their own prices, the answer gives those parts as published (refinery or ex-plant price, taxes, funds and margins), with the price where we hold it, and how fast the published cost line follows crude, in days, weeks or months.
- Showing what a litre is made of
- How much of the price is tax
- Whether prices rise faster than they fall
- Charting margins over time with the series it names
price_breakdownParameters 2 in the query
| Name | Where and type | Required | What it does | Example |
|---|---|---|---|---|
country | query country | optional | Two letter code: an EU country such as de or fr, or a country that publishes its own build-up (th, jm, za, uy, nz); leave out for the list of countries. | de |
fuel | query string | optional | For an EU country gasoline_95 or diesel; for the others one of the fuels in the list; leave out for all. | diesel |
Try it runs against the live API with your key
No key yet? Get a free one; it is saved in this browser for every page.
The answer 200, application/json
| Field | Type | What it holds | Example |
|---|---|---|---|
country | string | Two letter country code | "DE" |
name | string | Our name for it | "Germany" |
fuel | string | Fuel code; see Fuels and units | "diesel" |
date | string | The day of the close | "2026-10-26" |
unit | string | litre, gallon or barrel | "litre" |
currency | string | Three letter currency code | "EUR" |
price | number | The price in currency per unit | 2.298 |
parts | object | Each part a litre: taxes, crude, refining, distribution, margin (refining and distribution together) and before_taxes | {"taxes":0.8587,"crude":0.6788,"refin... |
shares | object | Each part as a share of the price | {"taxes":0.374,"crude":0.295,"refinin... |
pass_through | object | The weekly figures, all and last_3_years: share_of_movement, pass_through, lag50_weeks, lag90_weeks, r2, rises and falls | {"all":{"weeks":1090,"from":"2005-01-... |
series | object | Series code, or the series we hold | {"price":"retail.de.diesel","taxes":"... |
Example answer real, from what we hold now; long lists cut to three
GET /v1/breakdown?country=de&fuel=diesel{ "data": { "country": "DE", "name": "Germany", "fuel": "diesel", "date": "2026-10-26", "unit": "litre", "currency": "EUR", "price": 2.298, "parts": { "taxes": 0.8587, "crude": 0.6788, "refining": 0.4767, "distribution": 0.2838, "margin": 0.7605, "before_taxes": 1.4393 }, "shares": { "taxes": 0.374, "crude": 0.295, "refining": 0.207, "distribution": 0.123, "margin": 0.331 }, "pass_through": { "all": { "weeks": 1090, "from": "2005-01-03", "to": "2026-10-26", "share_of_movement": { "taxes": 0.235, "crude_price": 0.281, "exchange_rate": 0.012, "margin": 0.471, "refining": 0.193, "distribution": 0.278, "unexplained": 0.001 }, "pass_through": 1.051, "lag50_weeks": 0, "lag90_weeks": 1, "r2": 0.362, "rises": { "pass_through": 1.025, "lag50_weeks": 0 }, "falls": { "pass_through": 1.019, "lag50_weeks": 0 } }, "last_3_years": { "weeks": 157, "from": "2023-10-30", "to": "2026-10-26", "share_of_movement": { "taxes": 0.306, "crude_price": 0.252, "exchange_rate": 0.014, "margin": 0.428, "refining": 0.202, "distribution": 0.226, "unexplained": 0 }, "pass_through": 0.678, "lag50_weeks": 0, "lag90_weeks": 0, "r2": 0.458, "rises": { "pass_through": 0.473, "lag50_weeks": 0 }, "falls": { "pass_through": 0.295, "lag50_weeks": 0 } } }, "series": { "price": "retail.de.diesel", "taxes": "tax.de.total.diesel", "before_taxes": "structure.de.before_tax.diesel", "crude": "structure.de.crude_cost.diesel", "refining": "structure.de.refining.diesel", "distribution": "structure.de.distribution.diesel", "margin": "structure.de.margin.diesel" } }, "meta": { "worked_out_at": "2026-10-30T02:20:43Z", "note": "Taxes and the price before taxes add up to the price; crude, refining and distribution add up to the price before taxes. Worked out from stored prices. Distribution is measured against a world product price, so its changes say more than its level." } }
Errors every error has the same shape
| HTTP | Code | When | What to do |
|---|---|---|---|
| 401 | unauthorized | No key, or not a valid one | Send your key in the X-API-Key header; your account page shows it. |
| 400 | bad_request | A value is wrong or a required one is missing | The message names the parameter and the form it takes. |
| 422 | unknown_parameter | A parameter this endpoint does not take | Take it out; the parameters this endpoint takes are listed above. |
| 429 | rate_limited | Too many calls this minute | Wait the seconds in the Retry-After header, then call again. |
| 429 | quota_exceeded | Today's calls are used up | Wait for the day to reset at midnight UTC, or move to a larger plan. |