HMRC Exchange Rate API: Official UK Monthly Customs Rates as JSON
HM Revenue & Customs publishes one official exchange rate table per calendar month, and that single rate is what UK customs declarations and VAT invoices must use for the entire month — no matter where the market goes in between. It is the clearest example of a rate you cannot get from a live FX feed: on 20 March the market rate and the rate you are legally required to apply are two different numbers. This guide shows how to pull HMRC's published table as JSON, via REST or the zero-dependency hmrc-exchange-rate npm package, with history back to 2021.
/api/v1/central-bank/hmrc/history?source=GBP&target=USD).What HMRC publishes
- ~140 currencies against sterling — every currency the Online Trade Tariff carries, quoted as units per £1.
- One table per calendar month, released roughly two weeks before the month it applies to, so next month's rate is knowable in advance.
- History back to January 2021 — queryable by date or as a series.
- A fixed number for the whole month — the rate never changes retroactively, which is exactly what makes it citable in an audit.
Why the monthly rate, not the market rate
A live mid-market feed answers "what is GBP/USD trading at right now?" — the right tool for a checkout or a dashboard. UK customs and VAT rules ask something else entirely: "which rate were you required to use for this entry?" For imports valued in a foreign currency, that is HMRC's published rate for the month of the declaration. Using the day's market rate instead produces a duty figure that will not reconcile, and the difference compounds across a month of entries.
Because the rate is fixed for a month, requesting any date inside that month returns the same official number. A lookup by invoice date or entry date therefore resolves to the rate you must apply, with no rounding decisions of your own.
Get the latest rates (REST)
curl "https://allratestoday.com/api/v1/central-bank/hmrc/latest" \
-H "Authorization: Bearer YOUR_API_KEY" The response is HMRC's current published table, with the start date of the month it applies to. The latest table is available on every plan, including the free tier (300 requests/month, no credit card).
The npm SDK
npm install hmrc-exchange-rate import { getRate, getLatestRates } from 'hmrc-exchange-rate';
// One pair at the official HMRC rate for the current month
const pair = await getRate('GBP', 'USD', { apiKey: 'art_live_...' });
console.log(pair.rate, pair.rate_date);
// The full published table
const table = await getLatestRates({ apiKey: 'art_live_...' });
console.log(table.rate_date, table.rates.length); Zero dependencies, TypeScript types included, and it runs anywhere fetch exists — Node 18+, Bun, Deno, and edge runtimes.
The rate for an invoice or entry date
import { getRatesForDate, getHistory } from 'hmrc-exchange-rate';
// Any date inside a month resolves to that month's official rate
const day = await getRatesForDate('2026-03-20', { apiKey: 'art_live_...' });
// Month-by-month series for one pair
const series = await getHistory(
{ source: 'GBP', target: 'USD', from: '2021-01-01' },
{ apiKey: 'art_live_...' }
); Historical dates and series need a paid plan; the latest table stays free.
Reconciling a month of entries
The practical pattern for a customs or VAT job is to fetch one table per month and cache it, rather than calling per invoice. A month's table is a few kilobytes and cannot change once published, so a single request covers every declaration in that month — a small quota goes a long way. Pull next month's table as soon as it appears, and your pricing and duty calculations are correct from the first of the month.
Published vs derived pairs
HMRC quotes everything against sterling. If you need a pair it does not print — say USD to EUR at HMRC's rates — the API computes it from the published table via GBP and flags the result derived: true with the method used. What HMRC printed and what was computed are never silently mixed, which is precisely the distinction an auditor will ask about.
HMRC and the wider official-rates picture
HMRC is a tax authority rather than a central bank, and its cadence reflects that: monthly certainty beats daily accuracy when the goal is a number everyone can agree on after the fact. The same API also covers the Bank of England's daily spot rates for the market view, and the US Treasury's quarterly reporting rates for the American equivalent of this problem.
FAQ
Does HMRC have an exchange rate API?
HMRC publishes its monthly rates as CSV and XML files on the Online Trade Tariff, and AllRatesToday serves the same published rates as clean JSON — around 140 currencies against sterling, with history back to 2021 — via REST or the hmrc-exchange-rate npm package. The latest table is free.
How often do HMRC exchange rates change?
Once a calendar month. HMRC publishes the table for the coming month roughly two weeks in advance, and that single rate applies for the whole month regardless of how the market moves. Every API response carries the start date of the month it applies to.
Which exchange rate should I use for a UK customs declaration?
The HMRC rate for the month the declaration falls in — not the market rate on the day. Requesting any date inside a month returns that month's official rate, so a lookup by invoice or entry date resolves to the rate you are required to apply.
Official HMRC rates, as JSON
The latest table is free — 300 requests/month, no credit card.
Get your free API key