From a business event to double-entry posting: a flow and its prerequisites

A single flow for receipts, holds, settlement, refunds and unknown outcomes, with the prerequisites and observable results for a double-entry rollout.

The difficult part of double-entry is rarely adding one debit line and one credit line. It is deciding when a business event is certain enough to enter the ledger. Authorization, provider acceptance, merchant capture, bank arrival and a successful screen may be five different moments.

The simplified flow below separates business, ledger and reconciliation state. It is a system-design example, not an accounting policy for a country or a company.

Do not edit a balance from the event

A payment first enters an event layer with a stable business reference, order number, stage, account, original amount, currency, source and event time. Retain each notification’s delivery ID too, but it may change on retry and cannot replace the business reference. The service may mark an event received, pending or unknown; a callback must not directly become a new balance value.

The event layer preserves what happened externally and what evidence we received. The ledger layer turns events that meet the current stage’s recognition rules into vouchers and entries. The balance layer provides fast reads derived from posted entries or verifiable snapshots, without interpreting the event itself.

This identifies duplicate notifications, attaches a late success to the original business operation and keeps an unknown outcome pending reconciliation instead of forcing success or failure.

Validate eligibility and reserve funds

Validate the source and its mapping first: is the callback signature or other trusted-source proof valid, does the provider account map to the correct tenant and entity, and do the business reference, amount and currency match the request? Then check account status, precision, order direction and allowed state transitions. Cross-border and multi-currency operations also need quote, fee, limit and account-eligibility checks.

When initiating an authorization that reserves funds, check availability and write the hold in one controlled operation covering concurrent requests against a shared pool. A capture or success callback must consume the existing hold for the actual amount, without creating it again. Apply explicit rules to partial capture, excess capture and unused releases. A hold does not recognize revenue or prove settlement.

After sending an external request, a local failure or timeout must not automatically release the hold. Release it under the linked rule only after confirming that the external operation was not executed, failed or was canceled. Preserve a controlled hold while the outcome is unknown and continue querying; do not make those funds available to another operation prematurely.

Record a specific reasonCode, requestId and linked reference for validation failures. Distinguish a closed account, unsupported currency, insufficient capacity and a duplicate stage. Retain redacted decision and funds-change evidence for investigation.

Generate and commit a voucher

First ask which rights and obligations are already confirmed for this stage. A confirmed capture may debit a provider receivable and credit a merchant payable; bank arrival later settles that receivable in another voucher. Not every posting must wait for final settlement. However, an “accepted” notification alone does not prove that bank funds increased.

Generate a voucher from the event type and versioned account mapping. Enforce at least two entries with both debit and credit, equal totals within the same voucher, book, entity and currency, accounts and periods open to posting, and unique business-stage keys and voucher numbers. A failed check prevents the commit and creates a reasoned exception.

Validate trusted sources and business-stage idempotency, obtain enough evidence before generating and atomically committing a voucher, then reconcile and link adjustments
Evidence before posting. Swipe horizontally on a narrow screen. Open full image

Read the diagram as seven steps:

  1. Validate trusted sources, entity, fields and references. Record a reason and stop invalid events.
  2. Deduplicate by stable business reference and stage. Return the committed result for an identical request, reject conflicting payloads and let pending events continue with new evidence.
  3. Check the recognition evidence for this stage. If insufficient, remain unknown; use queries, trusted callbacks or reconciliation to obtain evidence and repeat this gate.
  4. Generate a voucher from the versioned mapping only when evidence is sufficient, without anticipating the next stage’s funds outcome.
  5. Check debits, credits, currency, entity, accounts, periods and uniqueness. Any failure makes the whole voucher ineffective.
  6. Commit the voucher, all entries, idempotency result and balance or hold changes used for funds decisions in one local transaction. Return a queryable postingId.
  7. Reconcile ledger records against external reports and bank statements. Review differences before creating linked adjustments, preserving original records.

“Atomic” describes the required result: concurrent requests must not see contradictory intermediate states, and a voucher must not be half-written. A transactional outbox can deliver cross-service notifications to idempotent consumers. The remote provider’s final outcome still converges through a state machine, queries and reconciliation.

Preserve unknown asynchronous outcomes

A provider may accept a request and call back later, or a request may time out after the provider charged. Record local responses, provider responses, ledger commits and external settlement separately; none automatically substitutes for another.

Preserve the event, evidence and controlled hold when the outcome is uncertain. Use supported queries, trusted callbacks, settlement reports and bank statements to converge, with an owner, retry schedule and escalation deadline. An old out-of-order state must not overwrite a newer confirmed state. Late evidence should advance the correct stage rather than post the original stage again.

Pending reconciliation is not permission to use a suspense account arbitrarily. If bank arrival is evidenced but ownership is unclear, an approved policy may debit bank and credit unidentified receipts. If even the movement of money is uncertain, retain the unresolved event without inventing a balanced voucher that claims arrival. Preserve earlier confirmed receivables and other entries.

Reconciliation matches internal events, entries, external references, fees and actual arrival. Record the type, amount, currency, time range and status of a difference, without erasing it through an unsupported manual balance change.

Refunds, reversals and repair

Refunds, authorization cancellations, hold expiry releases and settlement failures have their own business stages and link to the original transaction. Do not delete the original voucher or edit old entries to make the numbers appear correct.

Post a refund according to the obligations and location of funds at that time. After paying the merchant, a refund may require a merchant receivable or another agreed recovery relationship before recording the actual refund. It is not necessarily a whole reversal of the original receipt voucher. Check cumulative limits for partial refunds and express fee-return rules separately. For incorrect mappings, preserve the voucher and create an authorized reversal or adjustment with its reason, approver and references.

The same business reference, stage and necessary subevent reference should cause its funds change once. Different delivery IDs may describe the same operation; separate partial captures or refunds must not be merged just because the amounts match. A rule upgrade is not permission to repost an event.

Preconditions and expected results

Before rollout, prepare at least:

  • Account and entity boundaries: platform, customer, merchant, bank or clearing party.
  • An event dictionary and evidence thresholds for authorization, hold, capture, clearing, arrival, refund, reversal and fees.
  • Versioned account mappings for each stage, currency and fee condition.
  • Amount rules for precision, rounding, rate sources, fee payer and currency bridges.
  • Consistency controls for stable business identifiers, idempotency, concurrent holds, atomic commits, permissions and periods.
  • Cutover and operations: reconciled opening balances, transit and pending inventory, one authoritative writer, external reports, exception owners and escalation deadlines.

The expected result is an explainable state. A sampled transaction can be traced through its event, decision, hold, voucher, external outcome and reconciliation. Duplicate deliveries do not post twice; timeouts remain unknown; refunds and reversals link back; balances can be rebuilt per account and currency; reports separate pending funds from settled funds.

Acceptance scenarios include replay, concurrent requests against one pool, interrupted voucher writes, out-of-order callbacks and refunds after settlement. These are targets for a ledger implementation. This website presents knowledge documents and does not operate a funds ledger or execute these financial scenarios. If the prerequisites are missing, begin with read-only records and shadow reconciliation before expanding automatic posting.

Continue with why double-entry helps and debits and account design, or return to multi-currency ledgers and the actual cost of a rate.

Have a real use case in mind? Let’s talk.