🌍 Converting Multi-Currency Expenses with Kvatch
If you've ever tracked your expenses while traveling, you know the pain: one receipt in USD, another in GBP, a hotel bill in EUR. To get the full picture, you need to convert everything into a single currency. Most people copy exchange rates into a spreadsheet by hand. But with Kvatch, we can federate data from a Google Sheet (our expenses) with a live exchange rate API — and instantly see all our costs in one currency.
🖼️ How It Works
A Google Sheet + Frankfurter API → Kvatch → Unified expenses table in EUR
📊 The Problem
Here's a simple Google Sheet of expenses across currencies:
| date | category | amount | currency |
|---|---|---|---|
| 2025-09-01 | Flights | 1200 | USD |
| 2025-09-02 | Hotel | 900 | GBP |
| 2025-09-03 | Meals | 300 | EUR |
We want to convert them all into EUR, using live exchange rates.
🔌 The Plan
Our Kvatch plan has three parts:
expenses– pulled from Google Sheets.fx_rates– pulled from the Frankfurter API, which gives free exchange rates (no API key required).expenses_converted– a federated SQL dataset that joins expenses with exchange rates.
Here's the full YAML:
name: currency_conversion_example
storage:
type: sqlite
data_store_path: currency_conversion_example.db
connectors:
- name: expenses_sheet
type: GOOGLESHEET
connection:
spreadsheet_id: "${EXPENSES_SHEET_ID}"
read_range: "expenses"
desc: "Expenses in various currencies"
- name: fx_api
type: API
connection:
url: "https://api.frankfurter.app/latest"
method: GET
query_params:
from: EUR
response_path: "$"
desc: "Live exchange rates (EUR base)"
datasets:
- name: expenses
connector_name: expenses_sheet
type: GOOGLESHEET
config:
header_row_no: 1
query: "expenses"
desc: "Sheet with columns: date, category, amount, currency"
- name: fx_rates
connector_name: fx_api
type: JSON
options:
normalize_nested_objects: true
normalized_key_field_name: currency
normalized_value_prefix: rate_
query: "rates"
dedupe_key:
- currency
desc: "Latest FX rates (EUR base)"
- name: expenses_converted
connector_name: federated
type: SQL
query: |
SELECT
e.date,
e.category,
e.amount,
e.currency,
CASE
WHEN TRIM(UPPER(e.currency)) = 'EUR' THEN 1.0
ELSE r.rate_value
END AS fx_rate,
ROUND(e.amount /
CASE WHEN TRIM(UPPER(e.currency)) = 'EUR' THEN 1.0 ELSE r.rate_value END, 2) AS amount_eur
FROM expenses e
LEFT JOIN fx_rates r
ON TRIM(UPPER(e.currency)) = TRIM(UPPER(r.currency))
children:
- dataset_name: expenses
- dataset_name: fx_rates
desc: "Expenses converted into EUR"
output:
dataset_name: expenses_converted
format: table
verbose: true▶️ Running the Query
With the plan saved as currency.yaml, we run:
kvatch query --plan currency.yaml
And we get:
| date | category | amount | currency | fx_rate | amount_eur |
|---|---|---|---|---|---|
| 2025-09-01 | Flights | 1200 | USD | 1.08 | 1111.11 |
| 2025-09-02 | Hotel | 900 | GBP | 0.85 | 1058.82 |
| 2025-09-03 | Meals | 300 | EUR | 1.00 | 300.00 |
💡 Insights
With one query, we:
- Pulled expenses from Google Sheets.
- Pulled live FX rates from an API.
- Federated them into a single dataset with all amounts in EUR.
No manual copying, no outdated exchange rates — just a clean, up-to-date view of spending.
🚀 Wrap-Up
This is a simple example, but the same pattern applies to bigger problems:
- Convert international sales into your reporting currency.
- Combine bank statements with live FX feeds.
- Roll up multi-country revenue into a global P&L.
With Kvatch, all it takes is a few lines of YAML and SQL.
👉 Next time, we'll look at enriching datasets with external APIs — like mapping customer IPs to locations or adding stock prices to your portfolio.
Kvatch-CLI is free and built for curious developers. Join the GitHub repo and start federating your data.
🎉 Kvatch CLI is Now Available!
No more waiting! Download Kvatch CLI today and start federating your data sources.
Ready to simplify your multi-currency expenses?
Download Kvatch CLI and start converting your travel expenses with live exchange rates in minutes.