Where Money Docs

How the numbers work

Currencies and exchange rates

Every transaction is stored in PLN. A row that arrived in another currency is converted at import, with the file's own amount kept beside the result.

This is the only part of the app that touches the network, and only on your click. See the one network call.

The conversion rule#

A foreign row is priced at the NBP table A mid rate of the last business day before its date — the Polish D-1 convention.

  • The last rate published before the date, so a Saturday purchase uses Friday's. The lookup reaches back at most 10 days: a holiday bridge is fine, a hole in the table does not silently reach into last month.
  • Rounded half away from zero, so a charge and its refund convert to exact opposites.
  • Rates are stored as integers, matching NBP's four decimals. Money is never a floating-point number.

What ends up on the row#

The converted PLN figure, and beside it exactly what the file said: the original amount and currency, the rate applied, and which business day it came from. ▸ Record in the dock shows all of it, so the account still reconciles against the bank's statement.

Fingerprints use the original amount, so conversion can neither create nor destroy a duplicate.

Which currency a row is in: the currency column if the template maps one, otherwise the account's currency. The review screen marks rows that fell back.

Importing is blocked until the rates are there#

A commit that would write a foreign row with no covering rate is refused — storing an unpriced row would leave it outside every PLN total.

The banner names exactly what is missing (EUR: 2026-03-22 … 2026-06-30) and fetches precisely that range, padded back for the D-1 lookup. Several missing currencies are fetched one after another in the same click. Afterwards the file re-stages itself and the rows pick up their conversions.

Only rows actually being written count — a duplicate or skipped row with an uncovered date doesn't hold up the rest.

The Rates tab#

Currencies. The tab offers the currencies your file gives a reason to hold rates for: the ones your accounts are in, the ones transactions were booked in, and the ones already fetched. Tick the ones to fetch — EUR and USD together is one click — or type any other three-letter code to add it.

Fetching. Pick the date range and press the button. Before you click it tells you what the range costs (8 requests to api.nbp.pl (4 per currency)), and it refuses a range too long for one currency or a batch too large overall. Currencies go one after another, spaced out, never at once. After any fetch there is a short cooldown shared by every button in the app.

If one currency fails part-way through a batch, the ones that already succeeded are kept, and the error names what stopped it.

Coverage. One row per currency: the span held, how many rates, the latest one, when it was last fetched. update fetches only from the day after the last rate held; Update all does that for every currency that has fallen behind. Rates you already hold are never re-fetched.

An empty result is a normal answer, not an error: NBP publishes nothing on weekends and holidays, and a currency outside table A is never published.

Waiting for conversion. Transactions imported before conversion existed appear here grouped by currency, with Convert to PLN. Rows whose dates the rate table can't cover are left untouched and reported, never half-converted.

Net-worth snapshots use a different rule#

A net-worth snapshot is priced at the rate published on its valuation date, or the most recent one before it if that day had none — not D-1.

The two rules differ because the situations do. A transaction was priced by your bank off the previously published table, since at the moment it happened today's table did not exist yet. A snapshot is typed days later about a date already past, where the table for that day exists and is the honest answer to "what was this worth on the 4th".

A snapshot's rate can also be overridden by hand, per month per currency, and the app records that you did. Unlike an import, a missing rate does not have to be fetched first — but the month cannot be saved until every currency in it has one, from the table or from you.

If you never leave PLN#

None of this applies, no rate is needed, and the app makes no network request at all.

Where Money is independent software, not connected to any bank, and its figures are not a substitute for your bank's own statements. Privacy, disclaimer & terms.