Get official ECB exchange rates, live and back to 1999
The Currency & Exchange Rates API returns live and historical FX data as clean JSON.
6 active endpoints, on 1 and 2 credit tiers.
- POST/currency/v1/latest
- POST/currency/v1/convert
- POST/currency/v1/historical
- POST/currency/v1/timeseries
- POST/currency/v1/fluctuation
- POST/currency/v1/currencies
What Currency & FX endpoints does ReefAPI ship?
6 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.
Currency & FX API
3 of 6 endpoints, ready to run
Today's published reference rates for every supported currency, with the publication date and the base they are quoted against.
{ "ok": true, "meta": { "api": "currency", "endpoint": "latest", "mode": "live", "latency_ms": 1037, "record_count": 29, "cache_hit": false, "completeness_pct": 100 }, "data": { "base": "EUR", "date": "2026-08-28", "timestamp": 1787925600, "rates": { "USD": 1.1643, "JPY": 185.92, "CZK": 24.148, "DKK": 7.4748, "GBP": 0.8572, "HUF": 364.79, "PLN": 4.3365, "RON": 5.2584, "SEK": 11.0885, "CHF": 0.9364, "ISK": 140.8, "NOK": 10.8595, "TRY": 56.1718, "AUD": 1.6183, "BRL": 6.0126, "CAD": 1.613, "CNY": 7.8251, "HKD": 9.1276, "IDR": 20628.08, "ILS": 3.4612, "INR": 111.0585, "KRW": 1600.39, "MXN": 19.7327, "MYR": 4.6875, "NZD": 1.9585, "PHP": 72.482, "SGD": 1.4802, "THB": 38.37, "ZAR": 18.6309 }, "amount": 1, "source": "ECB" } }
How the Currency & FX API works
Currency & FX is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.
No OAuth app, no request signing, no per-site account. One key covers all 185 engines.
Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.
Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.
One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.
Convert a past invoice at the rate that applied on the day
Anything that has to survive an audit needs the rate for the date, not the rate for today, and it needs to say where the rate came from. Both come back on the same response.
{"from": "USD", "to": "EUR", "amount": 100, "date": "2020-03-02"}The result, the rate used, the date it was published and the source name. Store the rate and the date, not just the converted amount.
{"start": "2026-01-01", "end": "2026-03-31", "base": "EUR", "symbols": "USD"}The whole quarter in one call. Count the entries before you plot: publication days are not calendar days.
{"start": "2026-01-01", "end": "2026-03-31", "base": "EUR", "symbols": "USD,GBP,TRY"}Start rate, end rate, absolute change and percent change per currency, already computed.
One credit per call and no signup for the source. Everything is dated and attributed, which is what makes it usable in a report somebody else has to check.
curl -X POST https://api.reefapi.com/currency/v1/latest \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"base":"EUR"}'{
"ok": true,
"data": { … },
"meta": {
"api": "currency",
"endpoint": "latest",
"mode": "live",
"latency_ms": …,
"record_count": …
},
"error": null
}Which currency codes resolve, and which only work in the past
The rate source is the European Central Bank's daily reference fixing, so the currency list is the ECB's list — not a universal FX feed. Several codes in the enum are retired and resolve only for dates before they were discontinued. Anything outside the set is reported back to you rather than throwing.
| Group | Codes | When they resolve |
|---|---|---|
| Current ECB set | EUR · USD · JPY · GBP · CHF · AUD · CAD · CNY · HKD · NZD · SEK · NOK · DKK · CZK · HUF · PLN · RON · BGN · TRY · ISK · ILS · INR · IDR · KRW · MYR · PHP · SGD · THB · ZAR · MXN · BRL | any date the ECB published a fixing |
| Retired euro joiners | GRD · CYP · EEK · LTL · LVL · MTL · SIT · SKK | historical dates only — before that country adopted the euro |
| Discontinued | HRK · RUB · ROL · TRL | historical dates only — before the ECB stopped publishing them |
| Crypto, metals, anything else | BTC · ETH · XAU · … | never. A measured request for BTC came back in unavailable["BTC"] alongside the rates that did resolve — not an error, not a null rate. |
Three actions, three precisions, measured in one session: latest returned USD→TRY as 48.117319 (6 decimals), convert returned a rate of 48.06547568 (8 decimals), and timeseries returned EUR→USD as 1.1681 (4 decimals). Do not compare a value from one action against a value from another for equality, and do the rounding for display at the very end.
Which currencies, how far back, and what happens on a weekend
Measured on 2026-08-28 by walking the boundaries: the first day the source ever published, a weekend, a future date, a retired currency and a currency that was never in scope.
The reference set is 30 codes including the euro itself, covering the major European, American and Asian currencies plus Turkey, Israel, South Africa and Brazil. Every response names the source. There is no crypto, and the two ways it says so are different: convert rejects an unknown code outright with an INVALID_PARAM that lists every code it DOES accept, while latest and the symbols list keep the codes that resolved and put the rest in an unavailable array. The second behaviour is the useful one — one bad code in a list of twenty does not lose you the other nineteen. Note also that the parameter enum is slightly wider than the data: one code it accepts came back under unavailable rather than as a rate.
The first publication day returned real rates. A date before it, and any future date, both returned NOT_FOUND with a message naming all three reasons a date can miss. It does not invent a number and it does not return an empty success.
Asked for a Sunday, the response returned the previous Friday's rates — and set requested_date alongside the date it actually used, so the two are visibly different. That is the correct behaviour and it is auditable. Compare date against requested_date before you file the number.
A time series over a 27-day window returned 19 entries: no weekends, no bank holidays. The fluctuation endpoint silently moved its own start date to the first publication day and reported it as start_date. Do not divide by the number of days between your two dates.
With the euro as base the rates come back at four decimal places, exactly as published. Anything else is arithmetic, and the precision depends on which action you called: the same pair came back at six decimals from latest and at eight from convert, while a euro-based series stayed at four. Only the four-decimal euro figure is a quoted number; the rest are derived. That matters if somebody is going to reconcile your total against the source.
Two codes that were dropped from the reference set in recent years returned real rates for a 2021 date. Asked for today, the response returned an empty rates object with those codes listed under unavailable — an explicit answer rather than a silent omission.
What people build with Currency & FX
The jobs this data is most often used for.
endpoints
credits per call
Fintech and pricing tools call convert to show product prices in a user's local currency.
Finance dashboards use timeseries and fluctuation to chart and monitor rate movements.
Accounting workflows use historical to book transactions at the correct dated exchange rate.
What Currency & FX data costs
The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.
Full pricing →- 1,000 free credits on signup, no card
- One key, all 185 APIs, one credit pool
- Failed and blocked calls are never charged
- Credits roll over and never expire
Call it in two lines
Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.
curl -X POST https://api.reefapi.com/currency/v1/latest \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"base":"EUR"}'import requests
r = requests.post(
"https://api.reefapi.com/currency/v1/latest",
headers={"x-api-key": REEF_KEY},
json={
"base": "EUR"
},
)
print(r.json()["data"])Have a question? We got answers.
The questions people actually ask before wiring up Currency & FX.
Get a free key →I asked for a weekend date and got a different one back. Why?▾
Because the ECB does not publish on weekends or TARGET holidays, and inventing a rate for a day that had none would be worse than telling you. A measured conversion requested for 2026-08-23, a Sunday, returned date 2026-08-21 — the previous Friday's fixing — with requested_date 2026-08-23 echoed back so the substitution is visible. Always read date, not the value you sent. The same roll-back happens in fluctuation: a range starting 2026-08-01 reported start 2026-08-01 alongside start_date 2026-08-03, the first day with a published rate.
Why does my time series have gaps?▾
Missing days are simply absent from the rates object rather than present with null. A measured timeseries from 2026-08-20 to 2026-08-26 returned exactly five keys — 08-20, 08-21, 08-24, 08-25 and 08-26 — because the 22nd and 23rd were a weekend. If you are drawing a chart or joining against a calendar table, iterate the keys you got rather than the dates you asked for, and decide deliberately whether to carry the last value forward across the gap.
Are these live rates I can trade on?▾
No. They are the ECB's reference rates, published once per business day at 16:00 CET/CEST — the timestamp field is that publication instant as Unix seconds (measured 1787752800). Between publications the value does not move no matter how often you call. They are the right rates for accounting, invoicing, price normalization and reporting, and the wrong ones for anything that needs a live bid and ask. There is no spread here because there is no market quote.
The ECB publishes rates against the euro — how does base=USD work?▾
The set is re-expressed against the base you asked for. A measured call with base USD returned EUR 0.856971, GBP 0.733679 and TRY 48.117319, all derived from that day's euro fixings. The arithmetic is exact but it does pass through euro, so a USD→TRY figure and a EUR→TRY figure are consistent by construction rather than independently sourced. For accounting where a tiny difference matters, pick one base and stay on it rather than mixing.
What happens if I ask for a currency that is not covered?▾
It comes back in unavailable[] and everything else still resolves. A measured request for EUR, GBP, TRY and BTC returned rates for the first three and unavailable ["BTC"]. That is deliberate: one unrecognized symbol in a list of twenty should not fail the call. Check unavailable on every response — a symbol silently missing from rates is the single easiest way to end up computing with a zero.
How do I get the change between two dates without pulling every day?▾
fluctuation does it in one call. A measured EUR-based range from 2026-08-01 to 2026-08-26 returned, per currency, start_rate, end_rate, change and change_pct — TRY moved 54.8333 to 56.1481, a change of 1.3148 or 2.3978 percent. It also reports the actual start_date and end_date it used after rolling to published days. That is the cheap way to answer 'how much did our supplier currency move this month' without walking a series.
Can I convert an amount rather than reading a rate?▾
Yes — convert takes from, to and amount and returns the rate alongside result, which is simply amount times rate. A measured 100 USD to TRY at the 2026-08-21 fixing returned rate 48.06547568 and result 4806.547568. Note it returns the unrounded product: rounding to currency minor units is your decision, because the correct rule differs between invoicing, tax and accounting, and TRY, JPY and ISK do not all have two decimal places.
What is the Currency & FX API?▾
Currency & FX API is a ReefAPI endpoint group for exchange rates, conversion and historical rates. It returns live JSON through POST requests under /currency/v1.
Is the Currency & FX API free to try?▾
Yes. ReefAPI starts with 1,000 free credits, no card required. Currency & FX calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Currency & FX login or account?▾
No login to Currency & FX is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Currency & FX data?▾
The page example is captured from a live latest call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Currency & FX API use?▾
Currency & FX actions currently cost 1-2 credits per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call Currency & FX from an AI assistant or MCP client?▾
Yes. Connect ReefAPI once through MCP and your assistant can call currency actions with the same key, credit pool and JSON envelope used by normal REST requests.
Is the Currency & FX API a Currency & FX scraper?▾
It is the managed alternative to a DIY Currency & FX scraper. Instead of building and maintaining your own scraper — proxies, headless browsers, captcha and constant breakage — you call one ReefAPI endpoint and get the same exchange rates, conversion and historical rates back as clean JSON.
5 Finance & Data APIs on the same key
One key, one credit pool, one response envelope. If you are pulling Currency & FX, you are one call away from the rest of the category — no second contract, no second integration.
Need something this API does not do?
Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.
Try it on your own data before you pay anything
The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 184 APIs, and the same envelope everywhere.
Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-28.