Skip to content
django-nms

Bank statement reconciliation

Upload the statement. The rest posts itself.

django-nms reads CSV bank statements, matches transfers to customers in four steps and creates ledger entries. You only review the exceptions.

  • The vast majority of transfers post automatically
  • No virtual bank accounts billed monthly for every subscriber
  • Resilient to broken CSV files, format changes and mixed encodings
3 banks
Alior Bank, mBank (2025/26 and legacy format), Nest Bank
4 levels
of matching: invoice, identifier, name, history
1 screen
to review unmatched transfers
0
virtual accounts you have to open

Four levels of matching

Every transfer goes through a cascade of rules, from most certain to most general:

  1. Invoice number in the reference. A regular expression built dynamically from the prefixes of all active selling entities, longest first.
  2. Customer identifier (for example FN123456) in the reference. Every customer gets one automatically on creation.
  3. Sender name. First and last name matched in the counterparty field, two-token and single-token strategies.
  4. History. A sender assigned manually once is recognised next time by the same counterparty data.

If the invoice number was already used by another transfer, the system deliberately leaves the entry for a manual decision instead of guessing.

  • Fintech senders (Revolut, Wise) excluded from name and history matching
  • Duplicates blocked at file-row and ledger-entry level
  • Flag on every entry: matched automatically or manually

Review screen: only what needs a human

The transfer entries list has "matched / unmatched" and "balance created / not created" filters. Search by name, address, counterparty or account number. Assign the customer from an autocomplete, with the raw bank row next to it. Then one action: "Create balances".

  • Import runs in the background job queue, the panel never waits for parsing
  • Repair of rows split by commas inside counterparty names
  • Detection of UTF-8 with BOM, Windows-1250 and ISO-8859-2

Why this is cheaper than virtual accounts

Mass-payment services (a virtual account per customer) usually mean a monthly fee per account number plus posting fees. With hundreds or thousands of subscribers that is a fixed cost line you pay every month, whether or not the customer paid.

django-nms posts from your ordinary business account. The customer transfers as before, and the system recognises them by invoice number, identifier or name. No bank switch and no new account numbers on invoices.

If your bank is not on the list, adding a parser is usually a few dozen lines of code built on a field map. Ask for a quote.

Supported formats

Every format is tested against real files exported from online banking.

  • AL Available

    Alior Bank

    CSV, 12 columns, multi-line reference, automatic encoding detection. Covers the November 2025 format change.

  • MB Available

    mBank (2025/26 format)

    CSV, 5 columns, combined description parsed into name, reference and 26-digit account. Express Elixir handled.

  • MB Available

    mBank (legacy) / MultiBank

    CSV, 8 columns. Available for archived statements.

  • NE Available

    Nest Bank

    Comma CSV, Polish header, repair of rows split inside counterparty names, late-2025 variants.

  • PK Planned

    PKO BP, ING, Pekao, Santander

    Further CSV parsers. On the roadmap, ordered by customer requests.

  • MT Planned

    MT940 / CAMT

    Standard bank formats, which open the door to banks outside Poland. On the roadmap.

Reconciliation questions

What share of transfers matches automatically?

It depends on how customers fill in references. In practice the vast majority posts without manual work, and every manually assigned sender is remembered, so the share grows over time.

What if a customer pays two invoices with one transfer?

The entry lands on the customer balance as one payment. The balance is a ledger per payer, so an overpayment covers the next invoice.

Can statements be imported automatically, without uploading?

Today you start the import from the panel. Automatic retrieval (bank APIs, MT940 from a mailbox) is on the roadmap.

Bring your statement to the demo

We will import your CSV on a test environment and show how many transfers match right away.