CompareGuide

Migrate from ExchangeRate-API

Three changes: the URL, a header for the key and two field names

20 Oct 2026 · 3 min read

Most ExchangeRate-API v6 code needs three changes to use exchangerate.dev: update the URL, move the key from the path to an Authorization header and replace conversion_rates with rates. Responses still begin with "result": "success". Free includes 5,000 requests a month, and you can test the API without a key.

Matching endpoints

Five of ExchangeRate-API's six v6 endpoints have a match. Latest, pair, history and supported codes map directly. The request quota endpoint maps to /v1/account, which takes a dashboard session token instead of the API key. Enriched data has no equivalent. ExchangeRate-API puts the key in the URL; exchangerate.dev uses a bearer token, keeping the key out of URLs. The ExchangeRate-API details come from its public docs, checked on 19 Oct 2026.

ExchangeRate-API v6exchangerate.devNotes
GET /v6/KEY/latest/USDGET /v1/latest/USDSend the key in the Authorization header. Filter with ?symbols=EUR,GBP
GET /v6/KEY/pair/EUR/GBP/AMOUNTGET /v1/convert/EUR/GBP/AMOUNTBoth accept an optional amount. Returns rate and converted
GET /v6/KEY/history/USD/YEAR/MONTH/DAYGET /v1/YYYY-MM-DD/USDOne date in the path. Free: 30 days; Basic: 1 year; Plus: from 1999
GET /v6/KEY/codesGET /v1/currenciesEvery currency code with its name and decimals, no key needed
GET /v6/KEY/quotaGET /v1/accountQuota, plan and monthly reset. Needs a dashboard session token, not the API key
GET /v6/KEY/enriched/USD/JPYNo equivalentWe return the rate only, without the country, locale or flag details

Matching fields

The top-level response structure stays the same. The rates object has a different name, timestamps use ISO 8601 in UTC instead of Unix seconds, and each rate includes its source and whether it is stale.

ExchangeRate-APIexchangerate.devChange
resultresultUnchanged
base_codebaseNew name
conversion_ratesratesNew name
time_last_update_unix / _utcdata_updated_at (UTC ISO 8601)ISO 8601 in UTC; timestamp records when the response was served
time_next_update_unix / _utc–No fixed next update; live rates refresh during the trading day
target_code, conversion_rate, conversion_resultto, rate, convertedNew name
–source, sources, stale, market_sessionAdded: each rate's source, stale status and market state

Compare the requests

A typical migration changes one URL, one header and one field name. Use symbols to request only the currencies you need and keep the response small.

Original (ExchangeRate-API)
const res = await fetch("https://v6.exchangerate-api.com/v6/YOUR-API-KEY/latest/USD")const data = await res.json()const eur = data.conversion_rates.EUR
Updated (exchangerate.dev)
const res = await fetch("https://api.exchangerate.dev/v1/latest/USD?symbols=EUR", {  headers: { Authorization: `Bearer ${process.env.EXCHANGERATE_API_KEY}` },})const data = await res.json()const eur = data.rates.EUR
Python
import os, requestsres = requests.get(    "https://api.exchangerate.dev/v1/latest/USD",    params={"symbols": "EUR,GBP"},    headers={"Authorization": f"Bearer {os.environ['EXCHANGERATE_API_KEY']}"},    timeout=10,)data = res.json()rates = data["rates"]  # was data["conversion_rates"]
Shell
curl "https://api.exchangerate.dev/v1/convert/EUR/GBP/250" \  -H "Authorization: Bearer $EXCHANGERATE_API_KEY"

Matching errors

ExchangeRate-API returns "result": "error" with an error-type. exchangerate.dev returns "result": "error" with a code, a message and a matching HTTP status. Your code can handle errors using the status alone.

ExchangeRate-API error-typeexchangerate.devAction
unsupported-code400 unsupported_base or invalid_pairLook up the currency code in /v1/currencies
malformed-request400 invalid_request or bad_dateCheck the path, date format (YYYY-MM-DD) and amount
invalid-key401 invalid_api_keyVerify the key or rotate it in the dashboard
inactive-account–No equivalent; the key works after email confirmation at signup
quota-reached429 quota_exceededWait for Retry-After or choose a plan with more quota

Fixing the inactive-account error

According to ExchangeRate-API's docs, inactive-account means the account's email address hasn't been confirmed. Confirming it resolves the error there. With exchangerate.dev, you confirm your email once at signup, then the key in your dashboard is ready to use. The data endpoints also work without a key while you wait.

Try a call without a key

You can run this request before signing up. Keyless calls use Free plan data, with limits of 10 requests a minute and 100 an hour per IP address.

Shell
curl "https://api.exchangerate.dev/v1/latest/USD?symbols=EUR,GBP,JPY"

Request limits and history

Free includes 5,000 requests a month, 10 a minute, rates delayed by 15 minutes and 30 days of history. Older dates require Basic (one year) or Plus (from 1999). ExchangeRate-API's docs list historical data only on its Pro, Business and Volume plans.

Questions

How can I resolve ExchangeRate-API's inactive-account error?

Its docs say the account's email is unconfirmed, so confirm it. On exchangerate.dev, you confirm your email at signup and the key works immediately. The data endpoints also work without a key.

Can exchangerate.dev replace ExchangeRate-API without code changes?

Almost. Responses keep result: success. Change the URL, move the key from the path to a header and rename two fields: base_code to base and conversion_rates to rates.

Does exchangerate.dev offer historical rates like ExchangeRate-API?

Yes, through /v1/YYYY-MM-DD/USD. Free includes the last 30 days, Basic includes one year and Plus reaches back to 1999.

Can I test exchangerate.dev without signing up?

Yes. Call the data endpoints without a key at 10 requests a minute and 100 requests an hour per IP address.

Keep reading

Start your migration with a free key

Keep your code's structure, update the URL and header, and begin with the Free plan.

Get a free key