How to backfill FX rates without look-ahead bias
When you reconstruct a historical EUR/USD series for analytics or backtesting, the rate you query must be the one that was knowable on each simulated date, not a value published later. Here is the pattern.
Use GET /v1/{date}/{base} to retrieve the rate as published on a specific past date, going back to 1999. The /v1/latest endpoint always returns today's value, so it has no place in a historical series. Check `is_forward_filled` on every row: when it is true, no rate was published that day and the prior value was carried forward.
/v1/{date}/{base} for historical work. Never use /v1/latest, which returns today's value regardless of date.is_forward_filled: true means no rate was published on that date (weekend or public holiday); the prior value is carried.What look-ahead bias means for FX data
Look-ahead bias occurs when your historical series contains a value that was not actually published on the date you are simulating. With FX rates this is easy to introduce accidentally: if you query /v1/latest/USD today and store the result against a past date, you are using today's rate in a historical slot. The data will appear self-consistent but it describes a world that did not exist on that date.
The fix is to query each date individually via the point-in-time path. The response reflects what was published that day, not a later revision.
The dated endpoint
Put the date in the path: GET /v1/{date}/{base}. The date must be ISO 8601 (YYYY-MM-DD) and the base is a three-letter currency code.
The response shape is the same as /v1/latest with one addition: is_forward_filled. When that field is true, no rate was published on the requested date and the API returned the most recent prior value.
Reading is_forward_filled
For reference-rate sources (ECB and Federal Reserve), rates are only published on business days. Requesting a Saturday, Sunday, or public holiday returns the last published value with is_forward_filled: true. The flag lets you treat those rows deliberately rather than silently treating a carried value as a freshly published one.
Python: looping dates to build a series
The example below requests USD rates for a week, printing each date's EUR rate and whether it was forward-filled. Throttle to stay within the 12-request-per-minute free-tier limit.
On June 14 (Saturday) and June 15 (Sunday) you will see forward_filled=True. Both are non-publication days for reference-rate sources.
Cross-checking with data_updated_at
The response also carries data_updated_at, the timestamp when the underlying rate was last written. On a forward-filled day this will point to the previous business day's publication time, giving you an additional signal about the age of the value you received.
A note on rate type
notice field on every response states this explicitly.