An expense tool converts each receipt at the rate of the day it was dated. The date endpoint returns the daily reference rate for that day. When the day had no fixing, a weekend or a holiday, it returns the last published rate and says so in the response, so the report can show it.
Convert each receipt on its own date
Two receipts: 84.50 EUR dated Monday 12 October, and 41.20 EUR dated Saturday 10 October. The script asks for the rate on each date and prints the fields a report needs.
import json, urllib.requestfrom decimal import Decimaldef get(path): return json.load(urllib.request.urlopen(f"https://api.exchangerate.dev/v1/{path}"))expenses = [("2026-10-12", "EUR", Decimal("84.50")), ("2026-10-10", "EUR", Decimal("41.20"))]for date, ccy, amount in expenses: day = get(f"{date}?base={ccy}&symbols=USD") rate = Decimal(str(day["rates"]["USD"])) print(date, f"{amount} {ccy} x {rate} = {amount * rate:.2f} USD", "| forward-filled:", day["is_forward_filled"], "| rate dated", day["data_updated_at"][:10])2026-10-12 84.50 EUR x 1.1181 = 94.48 USD | forward-filled: False | rate dated 2026-10-122026-10-10 41.20 EUR x 1.1206 = 46.17 USD | forward-filled: True | rate dated 2026-10-09Weekends and holidays
Saturday 10 October has no fixing. The API returned the Friday rate, 1.1206, and set is_forward_filled to true. Friday is the last rate the market published before the receipt date, and most finance teams accept it. Show the flag in the report, so an auditor sees the date the rate really comes from.
Pick a policy and apply it everywhere
- Receipt date. Use the rate on the date printed on the receipt. This is the default above. For card spend, pass the settlement date instead.
- Report date. Use one rate for the whole report, such as the last day of the trip.
Whichever you choose, store the rate and the date it came from next to the converted amount. Approvers can then check a total without calling the API.
How far back you can go
Reports are often filed weeks late. The Free plan returns daily rates for the last 30 days. Basic ($19 a month) goes back a year, and Plus ($39 a month) covers history back to 1999. A request older than the window returns a plan_gated error with the earliest allowed date, so the failure is clear and the app can tell the user what to do.
Round after multiplying
Multiply the full receipt amount by the full rate, then round to the report currency's decimal places. Rounding the rate first moves a total by cents once an expense report holds a few hundred lines.
The daily reference rates are indicative. A tax authority may require its own rate. The official rates pages list the tables that tax offices publish and the guide on choosing an official rate covers when to switch.