The Platform Refund Ledger

Chapter 9 · Reconciliation as a practice

The Platform Refund Ledger · 5 min read

This chapter answers one question: how does a Connect platform close a month — from payouts to balance transactions to the books — so that refund leakage cannot hide between systems?

Reconciliation is not a report you generate; it is a set of identities that must hold. When they hold, a leak of the kind this book describes is structurally impossible to miss for long. When nobody defined them, every number is negotiable.

The three artifacts

  1. Balance transactions — the ground truth (chapter 7). Pulled continuously or nightly; grouped by type and joined by source.
  2. Payouts — the bank-facing record. Each Payout object has an amount, status, and arrival_date, and corresponds to balance transactions whose funds became available into it. Failed or canceled payouts return via payout_failure / payout_cancel ledger lines rather than vanishing (docs.stripe.com/reports/balance-transaction-types).
  3. The books — where your accounting system believes everything happened.

The month-close is proving artifact 3 equals artifacts 1 and 2, line by line, with the type-to-account mapping made explicit.

Template T1 — the payout register

One row per payout in the month:

payout_idarrival_datestatusamountLedger sum matchBook ref
po_81412026-08-04paid12,481.90JE-2211
po_81572026-08-11paid9,930.44JE-2287
po_81722026-08-18failed0.00✓ (funds returned)JE-2305

"Ledger sum match" means: the balance transactions that fed this payout sum exactly to its amount. That check is the whole game — a payout your bank received that no set of transactions explains is the definition of unexplained money, in either direction.

Template T2 — the type-to-account map

Decide once, in writing, which book account each ledger type posts to. Ambiguity here is where refund losses hide — a refund posted against revenue nets to invisibility; posted to its own account it becomes a trend someone owns.

Balance transaction typePosts to
chargeClearing — Stripe
stripe_feePayment processing expense
application_feePlatform fee revenue
application_fee_refundPlatform fee revenue (contra)
refundRefunds (contra-revenue, own account)
transferSeller payable — clearing
transfer_refundSeller payable — clearing (contra)
adjustment (dispute source)Chargeback expense
reserve_transaction / connect_collection_transferConnected-account reserve
topupBank transfer in
payout / payout_cancel / payout_failureBank: Stripe clearing

Template T3 — the month-close checklist

StepEvidence when done
Pull full-month balance transactions; group by type; total eachType totals sheet
Sum charge − refund − stripe_fee ± adjustments per currency; agree to payout totals plus change in available balanceIdentity holds to zero
Match every payout row to its transaction set (T1)Register complete
Post per T2; verify refund and fee-refund contra accounts carry real balancesJournal entries
Split closing Stripe balance into platform cash versus pending seller shareBalance decomposition memo
Scan for orphan adjustment, reserve_transaction, connect_collection_transfer lines; each mapped to a causeAnomaly list empty or explained

The identity in step two deserves its own sentence: charges minus refunds minus Stripe fees, plus or minus dispute adjustments, must equal payouts out plus the change in what Stripe still holds. If it does not, the difference is either a missing object class in your pull or money nobody can name — both worth stopping the close over.

Cutoff discipline: pending is not available

At close, your Stripe balance exists in two states (docs.stripe.com/api/balance/balance_retrieve): available — spendable now — and pending — settling on future dates carried by each transaction's available_on. Only available funds can pay out, so the books' "cash at Stripe" figure is the available balance, while pending is a receivable still inside Stripe.

Worked decomposition, continuing chapter 7's day: available closed at $156.84, entirely platform money — the day's seller shares had already transferred out line by line. Suppose instead the export also showed $240.00 pending: under the book's running 10% pricing, $216.00 of that belongs to sellers (90% of unsettled volume) and $24.00 is the fee portion — a split worth writing down monthly, because next month's payout promises are sitting in it.

Foreign exchange lines are their own lines

Multi-currency platforms will see currency_conversion and stripe_fx_fee entries in their ledger (docs.stripe.com/reports/balance-transaction-types). Book them explicitly. Folding conversion effects silently into revenue or refund accounts guarantees a month-end variance nobody can attribute — and when a cross-currency reversal executes months after its original transfer, the conversion delta is real economics to record, not noise.

What to check on your own platform

  1. Run Template T1 for last month; if any payout lacks a full transaction-set match, stop and resolve before anything else.
  2. Write down your T2 mapping if it exists only in someone's head; date and version it.
  3. Compute the step-two identity for the last three months and record the residuals — a persistent small residual is a mapping bug, a large one is a leak.
  4. Check that refund and application-fee-refund postings land in named contra accounts, not netted inside revenue.
  5. Decompose your closing Stripe balance into available-versus-pending and platform-versus-seller shares; confirm the seller-share figure agrees with what you would owe if you suspended all transfers tomorrow.

Sources: docs.stripe.com/reports/balance-transaction-types · docs.stripe.com/api/balance/balance_retrieve · docs.stripe.com/api/payouts/object