Monitor Currency Rates for Freelance Invoicing
Get the daily FX rate behind every cross-border invoice as JSON, timestamp each bill with a named source, and stop losing margin to stale rates.

TL;DR — The Currency Rates Scraper returns the day's exchange rate with date, pair, and provider as JSON. Run it on invoice day, stamp the rate on the bill, and keep a defensible record for cross-border freelance work.
Why freelancers lose money on FX quietly
Cross-border invoices drift on exchange rates in two ways: the rate you assumed when quoting and the rate on the day you bill. With daily FX turnover above $7.5 trillion, a month between quote and invoice can move the real value of your fee by several percent — enough to notice, small enough to never investigate.
The fix is boring: bill at a documented rate. When a client asks why the USD figure moved, you point at the record — date, pair, provider — instead of shrugging.
How does this compare to the alternatives?
| Converter website | Bank rate sheet | Thirdwatch actor | |
|---|---|---|---|
| Cost | Free | Free but buried | Pay per result |
| Reliability | Manual copy-paste | Includes bank's markup | Named free sources |
| Setup time | Zero | Zero | Minutes |
| Maintenance | You re-check manually | You re-check manually | Scheduled runs |
The converter website is fine for one invoice. It breaks down when you bill monthly, in three currencies, and want a record you can hand to an accountant.
How to invoice at a documented rate in 4 steps
How do I get today's billing rate?
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("thirdwatch/currency-rates-scraper").call(
run_input={
"baseCurrencies": ["USD"],
"targetCurrencies": ["EUR", "INR"],
"amount": 3000,
"maxResults": 5,
}
)
rate_rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())Set amount to the invoice value and converted_amount comes back precomputed — the number you put on the bill.
How do I backdate a rate for a late invoice?
Use date with the original invoice date:
run = client.actor("thirdwatch/currency-rates-scraper").call(
run_input={
"baseCurrencies": ["USD"],
"targetCurrencies": ["EUR"],
"date": "2026-08-31",
"amount": 3000,
}
)You get the published fix for that day — the same number you would have used had you billed on time.
How do I store the audit trail?
Persist each record next to the invoice it priced:
import json, pathlib
store = pathlib.Path("fx_records.jsonl")
with store.open("a") as f:
for r in rate_rows:
f.write(json.dumps({"invoice": "INV-2041", **r}) + "\n")One JSONL line per invoice carries pair, rate, date, and provider — everything an accountant or a disputed payment needs.
How do I watch for rate swings between quote and payment?
Schedule a daily run and compare to the quote-day rate:
quoted = 0.92 # USD/EUR at quote time
now = next(r["rate"] for r in rate_rows if r["pair"] == "USD/EUR")
if abs(now - quoted) / quoted > 0.02:
print("Rate moved >2% since quote — flag the pending invoice")A two-percent band is a reasonable nudge threshold for service invoicing.
Sample output
{"base_currency": "USD", "quote_currency": "EUR", "pair": "USD/EUR",
"date": "2026-09-11", "rate": 0.9304, "inverse_rate": 1.0748,
"amount": 3000, "converted_amount": 2791.2,
"provider": "erapi", "provider_name": "ExchangeRate-API open access"}date and provider_name are the audit fields — they make the number defensible months later.
Common pitfalls
Free sources publish once daily, so a same-day rate is a fix, not a tick — fine for invoicing, wrong for trading. Weekend invoices resolve to the nearest published day; state the convention in your terms. Payment processors apply their own spread on top of the mid-market rate — your documented rate is the benchmark, not the received amount. The actor names the provider per record so your audit trail survives a source change.
Related use cases
Frequently asked questions
Which rate should an invoice use?
Use the published daily fix on the invoice date and record it. The actor returns the rate plus the date and provider per row, so the number on the invoice is reproducible later.
Can I convert an invoice amount directly?
Yes. Set the amount field to the invoice total and the record returns converted_amount alongside the rate — no second calculation step.
What if the client pays in a different currency than I bill?
Run both directions. Each record includes inverse_rate, so you can show the rate either way round on the invoice footnote.
Do I need a finance API subscription?
No. The actor reads free keyless exchange-rate sources. For invoicing and reporting — not intraday trading — daily published fixes are the right grain.
Related
100 free credits, no credit card.
About 30 real searches. Add the MCP to Claude or Cursor in two minutes.