Statement AI is live  ·  Reconciling Canadian PDFs to the cent

Guide

How we reconcile every credit-card statement to the cent

The 2¢ tolerance, what we check, and why your accountant cares. A look at how Balancely verifies every Canadian PDF statement balances before you download it.

The Balancely Team6 min read

Every credit-card statement makes a promise: an opening balance, a stack of transactions, and a closing balance that's supposed to equal the first plus the second. In practice, half the statements we look at don't add up the first time we parse them. The reasons are mundane — a fee buried under a heading we missed, a returned-purchase row counted twice, a foreign exchange rounding line — but the consequence is real: a workbook that doesn't reconcile is a workbook your accountant has to redo by hand.

So reconciliation is the first thing we built, and the thing we've rebuilt the most. Here's how it works today, why we set the tolerance at 2¢, and what the workbook does when something drifts.

The reconciliation equation

For every statement, we compute the same identity twice and compare. First, the headline check:

opening_balance + Σ(transaction.amount) ≈ closing_balance

Sign convention matters. Purchases, fees, and interest are positive (they increase what you owe); payments and returns are negative. We store every transaction with a signed amount in cents as a Decimal, never a float. Floating-point rounding in JavaScript will quietly cost you a penny on a 90-line statement, and a penny is the difference between “reconciled” and “please re-check.”

Then we run the same check per section. Most Canadian issuers group the statement into payments, purchases, fees & interest, and (sometimes) returns. The per-section sums have to match the stated subtotals on the printed page. This is what catches misclassified rows: if the purchases section sum is off by exactly the value of a fee row we accidentally tagged as a purchase, we know where to look.

Why 2¢, not zero

The honest answer is: because zero is a lie. There are at least three places a legitimate penny goes missing on a real statement:

  • Half-cent rounding on FX. Foreign-currency purchases are converted at a rate with four decimal places, then rounded to the nearest cent. Round-half-up vs. banker's rounding differs by issuer.
  • Fee-vs-purchase categorization. Some statements bundle the FX fee into the purchase amount; others list it as a separate line. Whichever convention the issuer used, the per-section subtotals reflect their choice, not ours.
  • Interest accrual roundoff. Daily interest is computed to many decimals, summed across the cycle, then rounded once. Our reconstruction sums each transaction as printed, so we can be off by a cent for the cycle.

Two cents covers all three with margin. We've looked at thousands of statements and the drift, when it exists, is almost always 0¢ or 1¢. A 3¢ gap means something is actually wrong — a missed line, a wrong sign, a duplicate — and the workbook should surface it loudly.

“If you tell me the answer is exactly right, I don't believe you. If you tell me it's within 2¢ and you can show me the per-section breakdown, I'll trust the whole file.” — an actual bookkeeper, on a discovery call.

What the workbook does with drift

Every Summary row has a Reconciled column. Inside the 2¢ tolerance, you get a green tick. Outside, an amber flag and a delta value showing the gap, signed. The All Transactions sheet conditional-formats the row on the suspect statement so you don't have to hunt for it.

We never silently “fix” a drift. If the statement doesn't reconcile, that's data your accountant needs to see, not data we should paper over. The workbook's job is to make the discrepancy obvious and easy to investigate; not to hide it under a cleaner-looking total.

The boring parts that matter

A few implementation details that prevent the most common bugs:

  • Amounts are stored as cents in a Decimal type, never number. Conversions happen once, at the parser boundary.
  • The reconciliation runs before the workbook is generated. If a job can't parse the opening or closing balance, the whole job is flagged for review rather than producing a workbook with mystery numbers.
  • Every statement carries a reconciliation_delta_cents field through the pipeline. The Summary sheet renders it; the API exposes it; the history page sorts by it.

None of this is glamorous, and it's not what we put on the landing page. But it's why bookkeepers tell us they trust the output. Reconciliation isn't a feature — it's the reason a parsed statement is worth anything at all.

Try Balancely on your next statement.

Two free conversions to start — no credit card required.