Guide/Exchange rate API on Stack Overflow

Exchange rate API on Stack Overflow: developer troubleshooting, answered

The FX-API errors developers hit on Stack Overflow, fixed: 401 auth, 429 rate limits, CORS from the browser, stale weekend rates, converting an amount, and pulling historical or time-series data.

ERexchangerate.dev·Jun 30, 2026·6 min read

When an integration breaks, developers paste the error into Stack Overflow. For an exchange rate API the questions are almost always the same: a rejected key, a rate-limit wall, a CORS error, or a rate that looks stale over the weekend. Here are direct fixes, using exchangerate.dev as the worked example. Every snippet is a real call against https://api.exchangerate.dev.

Key points
A 401 almost always means a missing Bearer prefix or a key with a stray newline from copy-paste.
Track X-RateLimit-Remaining before the limit. On a 429, read X-RateLimit-Scope and Retry-After.
Anonymous browser calls are allowed. Never put an account key in front-end JavaScript.
source and market_session on every response tell you exactly why a rate is not moving.

The base URL is https://api.exchangerate.dev. The first call works anonymously (capped per IP), so you can reproduce any of these before signing up for a free key.

401 Unauthorized — the key is rejected

The key goes in the Authorization header as a bearer token, and the word Bearer with a trailing space has to be present. Keys are prefixed exr_live_.

curl · authenticatedcopy
curl https://api.exchangerate.dev/v1/latest/USD \
  -H "Authorization: Bearer exr_live_YOUR_KEY"

The usual causes of a 401: the Bearer prefix is missing, the key picked up a stray newline or quote from a copy-paste, or the env var holding it is not loaded. Platforms that cannot set Authorization can send the key as an X-API-Key header instead.

429 Too Many Requests — handling rate limits

Successful metered responses carry X-RateLimit-Remaining. A 429 supplies Retry-After; respect that value instead of assuming every limit resets after 60 seconds. Read X-RateLimit-Scope to see whether you hit the minute limit, anonymous hourly cap, or monthly quota. The free tier is 12 requests a minute, Basic is 120, and Pro is 500.

CORS error — calling the API from the browser

CORS permits anonymous reads and the Authorization and X-API-Key headers. That does not make a keyed browser request private: anyone who opens devtools can copy exr_live_.... Anonymous calls are fine for evaluation. For an account-attributed production call, proxy through your backend and keep the key server-side.

javascript · your backend routecopy
// the key never reaches the browser
const r = await fetch("https://api.exchangerate.dev/v1/latest/USD", {
  headers: { Authorization: `Bearer ${process.env.EXCHANGERATE_API_KEY}` },
});
const data = await r.json();

How should I cache exchange rates safely?

Cache a complete successful observation: rate, source, market_session, and data_updated_at. For actively traded pairs, start with 60 seconds on the server. That cuts duplicate calls. It does not make a daily reference rate fresher, so keep the observation fields beside the number.

  • Batch currencies into one symbols request instead of caching one HTTP call per pair.
  • Cache successful 2xx responses. Do not store a 401, 429, or upstream error as though it were a rate.
  • On 429, use Retry-After and X-RateLimit-Scope; do not invent a fixed retry delay.
  • Keep account keys in server-side configuration, never in a public browser cache or bundle.

The rate looks stale or will not change on weekends

This is expected, and the response tells you why. Actively traded currencies reprice live (~60s on trading days); current coverage comes from the API rather than a fixed marketing count, and the rest use daily reference rates from the ECB and FRED. Over a weekend the interbank market is closed, so the live feed pauses and reference fixes carry their last published value. Two fields make this explicit:

Field valueWhat it meansWhen it moves
source: liveAggregated spot consensusIntraday (~60s), trading week
source: ecb_dailyOfficial reference fixOnce per business day
market_session: weekendInterbank market closedLive feed paused; reference carries Friday

How do I convert an amount, not just read a rate?

Use /v1/convert/{from}/{to}/{amount}. It returns the rate and the converted amount together, so you do not multiply by hand:

curl · convert 100 USD to EURcopy
curl https://api.exchangerate.dev/v1/convert/USD/EUR/100 \
  -H "Authorization: Bearer exr_live_YOUR_KEY"

How do I get historical or time-series data?

For a single past day, put the date in the path: GET /v1/{YYYY-MM-DD}/{base}, back to 1999-01-04. For a full series across a range in one call, use GET /v1/range with start_date and end_date; it uses keyset pagination, so follow the cursor rather than requesting huge ranges in one shot.

Migrating from another FX API and hitting errors?

Request parameters follow common FX API conventions (base currency plus a symbols filter), so most migrations are a base-URL swap with no code rewrite. Where responses differ, this API adds fields (source, market_session, notice) rather than removing them — check any response-parsing code for a fixed key-set assumption.

The shortest call that works

No key, no dependencies:

curl · no keycopy
curl https://api.exchangerate.dev/v1/latest/USD

You get back the rates plus source and market_session so you know how fresh each one is. A free key raises the limit to 10,000 calls a month and takes a minute.

Indicative, not for settlement
Rates are published for reference, analytics, and display. They are not a dealing quote and should not be used to settle a trade. Displaying them in a product you ship requires the Basic or Pro plan; Free is for internal use.
ER
exchangerate.dev
Integration guides for developers.

Keep reading

GuideExchange rate API on Reddit: the developer questionsRead ComparisonFree exchange rate APIs comparedRead
More ComparisonsFixer vs exchangerate.devOpen Exchange Rates vs exchangerate.devCurrencylayer vs exchangerate.devCurrencylayer vs ExchangeRate-API
LearnReading source and market_session in your pipelineIndicative vs executable FX rates: what a rates API actually gives youECB reference rates, explained
Live RatesEUR/USDGBP/USDUSD/JPY