Reconciliation only feels hard when the data model is missing a layer. Below is the full chain, each object's single responsibility, and the exceptions it is supposed to produce. If your current stack cannot name one of these objects, that is where your manual work is coming from.
1. Gift — the donor's intent
The gift records what the donor meant to do: amount, date of intent, fund or restriction, campaign or appeal, tribute, recurring plan or pledge linkage, and whether they elected to cover fees. It is the receipting object and the fundraising object. It is not a money-movement object.
- Exception produced: a gift with no fund when the campaign requires one.
- Exception produced: an offline gift dated inside a period that is already closed.
2. Transaction — what the processor actually did
One gift can produce several transactions over time (an initial charge, a retry, a partial refund). The transaction holds gross, fee and net, the processor reference, the method, and its own status lifecycle: authorised, captured, settled, refunded, disputed.
- Exception produced: captured but never settled after N days.
- Exception produced: a settled transaction with no matching gift.
3. Payout — the processor's batch
The payout is the object most stacks are missing. It groups transactions on the processor's schedule, carries batch-level fees and adjustments, and holds an expected arrival date and amount. Everything downstream depends on it existing.
- Exception produced: a payout containing a transaction from a closed period.
- Exception produced: payout net that does not equal the sum of its transaction nets plus adjustments.
4. Bank deposit — what your bank says
Imported from the bank feed or statement, with its own date and amount. Matching is deposit-to-payout, not deposit-to-gift, and it is usually one-to-one. Where it is not — a bank aggregating two payouts, or a payout split — the match is many-to-one and should be recorded as such rather than adjusted away.
- Exception produced: a deposit with no candidate payout.
- Exception produced: a payout that has not arrived by its expected date.
5. Allocation — restriction becomes ledger meaning
Allocation applies the gift's fund and restriction to the net amounts that actually settled. This is where restricted-fund balances become defensible: the balance is derived from settled, allocated money, not from the sum of gifts entered.
- Exception produced: a refunded gift whose allocation has not been reversed.
- Exception produced: a restricted balance spent below zero.
6. Journal mapping — the accounting boundary
Each object type maps to accounts: revenue by fund, processing fees as expense, receivables for pledges, a clearing account for money in transit between the payout and the deposit. That clearing account is the single most useful line in a nonprofit chart of accounts and the one most often missing.
- Exception produced: a fund with no revenue account mapping.
- Exception produced: a clearing balance that is non-zero after the deposit has matched.
7. Close batch — the period lock
The close batch freezes a period: no back-dating, no silent edits. Corrections after close become dated adjustments with an audit trail. This is what makes prior-period numbers repeatable, which is what an auditor is actually testing.
- Exception produced: an edit attempted against a closed period.
- Exception produced: an unresolved exception blocking close.
“A reconciliation is finished not when the numbers match, but when every difference is an object with a reason and an owner.”
How the month-end review reads once the model exists
- Open the period. Read the count of unresolved exceptions by type.
- Clear arrival exceptions first — they are usually timing, not error.
- Review unmatched deposits, which are usually offline gifts or non-gift income.
- Confirm the clearing account returns to zero.
- Close the batch. Anything later is a dated adjustment.
Honest status
Beneora implements this chain as its finance model, and the reconciliation and exception workspaces are built against it. It is in active build and has not yet run a live month-end for a production organisation.