Note: this is mostly vibe-coded, but was reviewed and works for me. Use at your own risk.
Sync transactions between two YNAB budgets with automatic currency conversion.
- You have a destination YNAB budget where you manage most of your finances
- You have a source budget in a different currency with fewer transactions
- You want to sync transactions from the source budget to your destination one, converting amounts while preserving payees and categories
Requires Python 3.10+.
# Using uv
uv run ynab-multi-budget-fx.py
# Or install dependencies manually
pip install ynab rich questionary httpx
python ynab-multi-budget-fx.pyOn first run, you'll be prompted for:
- YNAB API Key - Get one from YNAB Developer Settings
- Destination budget - Target budget (receives synced transactions)
- Source budget - Budget to sync transactions from
- Cutoff date - Only sync transactions since this date
Configuration is cached in ~/.local/share/ynab-multi-budget-fx/config.json.
All data is stored in ~/.local/share/ynab-multi-budget-fx/:
config.json- Budget IDs, API key, cutoff date, adjustment categoryrates_cache.json- Cached FX rates (keyed bybase:target:date)currency_data.json- ISO 4217 currency symbols for memo formatting
-
Validation - Maps categories and accounts between budgets by name. Source budget must have a subset of the categories and accounts of the destination budget.
-
Transaction sync - Fetches transactions from the source budget since the cutoff date. For each new transaction:
- Converts the amount using daily FX rates
- Maps category and account IDs to the destination budget
- Appends FX info to memo (e.g.,
100.00€ @1.05or100.00 EUR @1.05) - Sets
import_idtoMB:<orig_tx_id>to track synced transactions
-
Transaction updates - Previously synced transactions are detected via
import_idand updated if the source transaction's amount or memo has changed. -
Balance adjustments - After syncing, compares account balances and offers to create adjustment transactions for any discrepancies (only for differences ≥1 in target currency).
- Transactions with payee
<IGNORE>are skipped - Split transactions are fully supported
- Synced transactions are created as unapproved for review
Uses the Exchange API for historical exchange rates.
- Rates are fetched in parallel and cached locally to avoid redundant API calls
- If a rate is unavailable for a specific date, automatically falls back to the previous day
- Multiple CDN endpoints are tried for reliability
ynab- Official YNAB API clientrich- Terminal formattingquestionary- Interactive promptshttpx- HTTP client for FX API