Introduction
exchangerate.dev is a REST API for indicative foreign exchange rates — live intraday on trading days for actively traded currencies, with source, market_session, and honest freshness on every response. Try the free exchange rate API anonymously, or start with a free key — no credit card required.
market_session and source fields tell you exactly what you are looking at on every call.Quickstart
Make your first data call without signup. Add a free key from the dashboard when you want account-attributed quota.
Authentication
You can evaluate data routes without a key. Pass your key in the Authorization: Bearer header for account-tier quotas and attribution. Anonymous access is limited to 12 requests/minute and 100 requests/hour per IP. Never embed an account key in public browser JavaScript; use anonymous access or a server-side proxy. Account quota resets at 00:00 UTC on the 1st.
Rate limits
Anonymous limits are per IP; account limits are per key and calendar month. On 429 the response includes Retry-After.
The source field
Every response carries a source that tells you the quality of the rate. This is not a vendor name — it is a freshness class.
live— updates on short intervals throughout the trading week, aggregated from market dataecb_daily— the European Central Bank's once-a-day reference rate, published each business day around 16:00 CETfred_daily— the US Federal Reserve's (FRED) once-a-day reference rate, used for currencies the ECB doesn't publish
When a response contains several currencies, the top-level source reflects the least fresh one in the set. Two things follow from that:
- A mixed basket can read
ecb_dailyeven though the majors in it are live. A per-currencysourcesmap tells you which is which — it's on every endpoint except/v1/range, whose rows each carry a singlesource. - Request only live currencies (e.g.
?symbols=EUR,GBP) andsourcereadslive.
Live rates are available on every tier, including Free.
The market_session field
The market_session field tells you whether the market is open and trading or in a reduced-liquidity period.
open— the interbank trading week is openweekend— Saturday/Sunday; interbank closed, last consensus carriedinterbank_closed— a known non-weekend market closure
Indicative rates
“Indicative” means the rate shows you where the market is — it is not a price anyone commits to trade at. Rates are built from aggregated market data and public reference rates, and can differ from an executable bank rate by roughly 5–15 basis points (a basis point is 0.01%).
Use them for display, analytics, and conversion estimates. Don't use them for settlement, regulated trading, or as a source of record — there is no SLA at v1. Responses built on ECB/FRED reference data say so in the notice field.
Derived crosses
Some pairs aren't quoted directly in the market, so we calculate them from two pairs that are — EUR/GBP, for example, is built from EUR/USD and GBP/USD. This is standard practice (called triangulation) and can add a small amount of extra spread. Derived rates are always flagged:
- Multi-currency responses list triangulated rates in
derived_symbols— filter on it client-side if you only want directly quoted rates. - Single-pair responses (
/v1/convert,/v1/rate) carry aderivedboolean instead. - When a pair isn't derived,
derivation_bps_maxis alwaysnull. When it is derived, that field usually carries the worst-case extra spread in basis points — but some triangulated pairs have no fixed ceiling and it readsnulltoo. Checkderived, notderivation_bps_max, to detect triangulation.
GET /v1/latest
Latest rates for all supported pairs, or a filtered subset via ?symbols=.
GET /v1/{YYYY-MM-DD}
Historical snapshot — returns the reference rate as published on that date. Dates back to 1999-01-04 (ECB series start; 1999-01-01 is accepted as a query date but has no fix — earlier holiday/weekend gaps return no data, never fabricated).
GET /v1/convert
Single or batch currency conversion. The POST form accepts multiple pairs in one call.
GET /v1/rate/{slug}
Single-pair quote by slug (e.g. eur-usd) — a flat, single-pair shape distinct from /v1/convert (which nests per-pair results under conversions[] and adds amount/converted). Slug is case-insensitive; malformed or unknown pairs return invalid_pair.
GET /v1/range
Daily time-series for a date window. JSON responses are capped at 366 rows/page with keyset pagination; pass format=csv or format=parquet to download the full window as a single file.
GET /v1/currencies
Full list of supported pairs with name, type, decimal precision, and derived flag.
GET /v1/account
Your org, active key, and current-month usage.
Python
No SDK required — a single requests call.
Node
No SDK required — built-in fetch.
MCP server
Use exchangerate.dev as a tool in any MCP-compatible AI agent. The dedicated MCP quickstart includes a one-command Claude Code setup, keyed Claude Desktop and Cursor config, and the complete tool table.