Duration.

Guides

Import and reconcile

Duration reads a CSV of account activity, brings every row onto your ledger, and then asks you what each one is. Rows you already have are recognised and skipped. Everything else waits, plainly marked, until you decide where it goes.

There are two steps, and only the first one is about the file.

Set up

Choose the export, tell us which account it belongs to, and map its columns — date, amount, description, and a reference if your bank provides a stable one.

Underneath the mapping you will see the first few rows read back the way we read them: the dates normalised, the amounts signed, the descriptions as they will appear. This is the check worth making. A column mapped to the wrong field is the one mistake an import can make that is tedious to unpick, and it is obvious the moment you see a date where an amount should be. Anything we cannot read at all is listed by line and reason, and skipped.

If you have imported this source before, we recognise its layout and fill the account and the columns in for you, with a note saying why.

File them

Press import and the rows land. Income rests in ready-to-allocate; spending parks in Uncategorised. Both are holding positions, and a row sitting in one is a row that still wants a decision from you.

That is the part worth being explicit about: a row is on your ledger from the moment it arrives, and it is not filed until you say so. The money is real — your balances are immediately correct against your bank — but nothing has been claimed about what any of it was for. Those are two different things, and only the second one is a judgement.

Just imported and want it all back? Undo this import removes the rows from that file that are still waiting. Anything you have already filed stays, because that was a decision, and we will not quietly unmake one.

Deciding, a row at a time

Each waiting row carries one picker, and everything you can say about that row is in it.

Reconcile comes first, because it answers what a row is before anything answers where it goes:

  • Settles a transfer you accepted. You told us a move was coming; this is it arriving. Choosing this records the real transfer and closes the expectation.
  • Same as a transfer already recorded. The other side of a move already on your ledger, showing up on this account’s statement. Choosing this reconciles the two rather than recording a second one.
  • Already recorded on another date. The same charge, exported twice — see below.

Suggestions comes next, and is built from your own history. It offers the bucket this merchant usually goes in, and — where you have made the same call enough times — the disposition it usually gets, such as usually a transfer to a particular account. Nothing here is applied on your behalf without a confirming press; where the history is strong the bucket arrives pre-filled, and a suggested transfer never does, because saying a row is a transfer changes what it is rather than where it sits.

Then the ordinary choices: any bucket, a transfer to another account, or exclude from budgeting for a row that is a real fact on your statement but not a budgeted expense. A row can also be split across several buckets, which is the one thing a picker cannot express.

Work down the list, then confirm the lot in one press. The confirming act is that press, over rows you have looked at — not a checkbox per row, and not a screen you clicked past on the way in.

How matching works

Matching is done on the money, not the words. When a row is imported we record a fixed key for that statement line — built from the account, date, amount and the bank’s text at the moment of import — and every later import is compared against that stored key.

Because the key is captured once and never recomputed, re-importing the same file changes nothing, and importing an overlapping date range adds only the genuinely new rows. Two identical transactions on the same day stay two transactions: the comparison counts occurrences rather than collapsing them.

Rename a row without breaking the match

A useful consequence: you can rewrite an imported transaction’s description afterwards — turning a cryptic payee string into something you will recognise — and it will still reconcile. The next import of that statement line compares against the key captured at import, not the text you edited, so an annotated row never returns as a duplicate. Clean up your descriptions freely. See correct mistakes for the other edits that keep an imported row matched.

When the same charge arrives twice

The awkward case, and a common one on cards: a purchase is exported once while it is pending and again, days later, once it settles — at a different date, sometimes a slightly different amount. The two rows are not identical, so they do not match, and both would otherwise land.

We spot this and offer it on the later row as already recorded on the earlier date. Choosing it keeps the transaction you already have, drops the duplicate, and remembers the discarded statement line so that re-importing the file does not offer it again. Your filing on the surviving row is untouched.

If you would rather not hold a pending charge at all until it settles, Delete the row instead. It leaves your balances at once, and you can restore it from Activity. A deleted row’s statement line is not remembered, so the settled charge imports as normal when it arrives — and, by the same token, re-importing a file that still lists the pending line brings that line back.

Where the waiting rows live

The import page shows what the file you just brought in is waiting on. But the backlog is not a property of that page, and you should not have to go there to find it.

Activity carries the same list, behind a Needs a decision filter, with a count beside it in the navigation. It narrows like any other filter — combine it with a search, a date range or an account — and it is where the backlog will find you on an ordinary day, rather than the other way round.

Clearing the exceptions

The statement-level check is the backstop beneath all of this: your computed balance for an account, set against the balance the statement reports.

For a cash account the difference should be zero. Anything else means a row is missing or counted twice. In practice it is one of a handful of things:

  • A row that never imported — outside the date range of the export, or unreadable and skipped. Check the skipped lines named at the setup step, then re-import the fuller range; the rows you already have will be recognised, so nothing doubles.
  • A charge counted twice because it was exported pending and again settled. Resolve it on the later row as described above.
  • A hand-entered transaction the import then added again under a different description. Correct one of them; the import’s key is per statement line, so removing the hand-entered copy is usually the cleaner fix.

For an invested account the residual is not an error. The gap between what you put in and what the account is worth is market movement, and it is attributed rather than corrected. That is a different job with a different shape — see drift, and closing it.

A last word on order: reconcile before you allocate, not after. Allocating against a balance you have not yet squared with your bank means doing the arithmetic twice.

Last reviewed: October 2026.