Reading PSP Settlement Files: Stripe vs Adyen
Field-level reference for Stripe and Adyen settlement files: the universal object model, balance_transaction vs pspReference, and which IDs to persist.
A PSP settlement file is a processor record, not a bank statement. Maps Stripe (balance_transaction/payout, pays net) and Adyen (pspReference/batch, gross + fee lines) into one object model — plus the IDs to persist so a PSP switch doesn't break recon.
A PSP settlement file is the processor’s record of what it processed and paid out. It is not a bank statement, and it is not proof the money arrived. Operators who treat the two as interchangeable build reconciliation on a foundation that breaks the first time a payout is reported but never lands.
This reference covers what the fields in a Stripe and an Adyen settlement file actually are, and how they map to a single underlying model. It sits beneath the PSP reconciliation failure runbook — the runbook owns the break types, the matching-ID chains end-to-end, and the escalation procedure. This article owns the field definitions and the mapping. Read this to understand what you are looking at; read the runbook when something does not match.
Direct answer
Every PSP settlement file, regardless of vendor, expresses the same object model: identifiers (a transaction-level ID, the processor’s own reference, a batch-or-payout grouping, a link back to the original payment, and a bank-level reference), money (gross → fees → net, plus refunds, chargebacks, reserves, and adjustments), and several distinct dates (when the transaction happened, when it settled into a batch, when the payout was instructed, and when funds are expected at the bank). A settlement file records the processor’s intent to pay; only the bank statement confirms the money landed.
Stripe and Adyen express that model differently. Stripe is balance_transaction- and payout-centric and pays net by default: each balance_transaction row carries amount, fee, and net, and the Payout reconciliation report links each row to its payout. Adyen is pspReference- and settlement-batch-centric and reports gross plus a separate fee breakdown: the Settlement Details Report carries gross debit/credit columns alongside Commission, Markup, Scheme Fees, and Interchange. The operator job is to persist a stable internal ledger that both PSPs map into, so reconciliation survives a PSP migration.
Why PSP settlement files are not bank statements
A settlement file answers one question: what does the processor say it processed and intends to pay you? It is generated by the PSP, on the PSP’s schedule, from the PSP’s view of your transactions. It breaks down each transaction into gross, fees, and net, groups them into a payout or batch, and tells you when that payout is expected to reach your bank.
A bank statement answers a different question: what money actually moved in and out of your account? It is generated by your bank, independently, and it is the only record that confirms a payout actually arrived.
The gap between these two is where naive reconciliation breaks. If you match only your internal ledger against the PSP settlement file, you have a two-way match — it confirms your records agree with the processor’s records. It does not confirm the money arrived. A payout can be marked settled in the PSP file and never reach the bank because of a routing error, a beneficiary account issue, or a bank-side hold. The only way to catch that is to add the third leg: match the bank statement credit back to the payout using the bank-level reference. The full three-way match, the break taxonomy, and the escalation steps live in the PSP reconciliation failure runbook.
The practical consequence for reading settlement files: treat them as authoritative for what the processor did, and never as authoritative for what your bank received.
The universal settlement object model
Before mapping any specific PSP, fix the rail-agnostic model in your head. Every settlement file is some encoding of these three groups.
Identifiers — five distinct roles, often confused:
- Transaction-level ID — the processor’s identifier for a single transaction event (a charge, a refund, a fee). Stable within that PSP; meaningless across PSPs.
- Processor reference — the PSP’s own reference that ties together the lifecycle of one payment (authorization, capture, refund, dispute). Sometimes the same as the transaction-level ID, sometimes a parent of it.
- Batch or payout grouping — the ID that groups many transactions into one bank credit. One payout typically equals one line on your bank statement.
- Original-payment link — for any refund, chargeback, or modification, the reference back to the original payment it adjusts. Without this you cannot net a refund against its sale.
- Bank reference — the value that appears on the bank statement so you can match the payout to the credit.
Money — the gross-to-net chain plus the adjustment types:
- Gross — the transaction amount before any fees.
- Fees — the processor’s deductions. May be a single line (net model) or an itemized breakdown (interchange, scheme fees, markup, commission).
- Net — what you actually receive for that transaction (gross minus fees).
- Refunds, chargebacks, reserves, adjustments — record types that move money outside the simple sale flow. Each needs its own row type and sign convention.
Dates — at least four, and conflating them is a leading cause of false breaks:
- Transaction / processing date — when the payment occurred.
- Settlement / batch date — when it was assigned to a settlement batch.
- Payout date — when the payout was instructed.
- Expected bank-credit date — when funds are expected to arrive.
Record type — the field that distinguishes a sale from a refund from a fee from a reserve movement. This is the single most important field for correct accounting, because the sign and the ledger account both depend on it.
The two PSPs below are just different encodings of this same model.
Stripe: balance transactions, payouts, and reporting IDs
Stripe’s settlement model is built on the balance_transaction object. Every event that moves money on your Stripe balance — a charge, a refund, a fee, an adjustment, a payout — is a balance_transaction. Its id uses the txn_ prefix. The core money fields are confirmed in the Balance Transactions API: amount, fee, and net (where net = amount - fee), plus currency, available_on, created, status, source, type, and reporting_category.
Two classification fields matter for reconciliation:
type— the granular event type. Documented values includecharge,refund,payment,payout,adjustment,stripe_fee,reserve_hold,reserve_release, and dispute-related types, among many others.reporting_category— Stripe’s recommended field for accounting grouping. Documented values includecharge,refund,fee,dispute,dispute_reversal,payout_reversal,partial_capture_reversal,platform_earning,connect_reserved_funds, andrisk_reserved_funds. Stripe explicitly recommendsreporting_categoryovertypefor accounting.
The source field links a balance_transaction back to the object that created it — a charge (ch_), a payout (po_), a refund (re_), and so on. This is Stripe’s original-payment link.
Payouts group balance transactions. A payout (po_ prefix) is the transfer of your available balance to your bank. To reconcile, use the Payout reconciliation report, whose itemized form carries the linking columns: balance_transaction_id, automatic_payout_id (the payout each row belongs to), automatic_payout_effective_at (the expected bank-arrival date), gross, fee, net, currency, reporting_category, and trace_id (the bank-level reference, used to locate the payout on your bank statement). The flow is: charge → its balance_transaction → automatic_payout_id → trace_id → bank credit.
The defining Stripe characteristic: Stripe pays net. The Stripe fee is deducted on the balance_transaction itself — there is no separate fee invoice in the default model. Your bank credit equals the sum of the net column for that payout.
Adyen: pspReference, settlement batches, and accounting IDs
Adyen’s settlement model is built on the pspReference — Adyen’s per-transaction reference, a 16-digit number assigned to each transaction. Your own reference travels alongside it as Merchant Reference. Modifications (refunds, captures, cancellations) carry their own Modification Reference and point back to the original payment.
The transaction-level settlement file is the Settlement Details Report. Its columns, confirmed in Adyen’s documentation, include (in documented order): Company Account, Merchant Account, Psp Reference, Merchant Reference, Payment Method, Creation Date, TimeZone, Type, Modification Reference, Gross Currency, Gross Debit (GC), Gross Credit (GC), Exchange Rate, Net Currency, Net Debit (NC), Net Credit (NC), Commission (NC), Markup (NC), Scheme Fees (NC), Interchange (NC), Payment Method Variant, Modification Merchant Reference, and Batch Number.
The Type column is Adyen’s record-type field. Documented values include Settled, Refunded, Chargeback, SecondChargeback, ChargebackReversed, Fee, MerchantPayout, InvoiceDeduction, ReserveAdjustment, DepositCorrection, and Balancetransfer, among others. The Batch Number groups rows into a settlement batch, and the batch’s MerchantPayout row corresponds to the bank credit.
The defining Adyen characteristic: Adyen reports gross plus a separate fee breakdown. Rather than a single net figure, the Settlement Details Report itemizes fees into Commission (NC), Markup (NC), Scheme Fees (NC), and Interchange (NC) alongside the gross debit/credit columns. Adyen defines these as: Interchange (paid to the issuer, set by the card network), Scheme Fees (set by the card scheme), Markup (the IC++ margin component), and Commission (fees due to Adyen). Note also that Adyen’s monthly Processing Invoice is trued up against settlement as an InvoiceDeduction line — the reconciliation runbook covers that mechanic; do not assume its detail here.
The booking date — the date the entry is posted to a batch for payout — is a distinct concept from Creation Date in Adyen’s model; confirm the exact column name your report version exposes for it (see Adyen docs for the exact booking-date column name).
Field comparison table
This maps the universal concepts to each PSP’s confirmed field names. Where a cell says “(see docs)”, the exact column was not pinned in the docs accessed and should be confirmed against the current vendor documentation rather than assumed.
| Concept (universal) | Stripe field | Adyen field | Notes |
|---|---|---|---|
| Transaction-level ID | balance_transaction id (txn_) | Psp Reference | Stripe: one row per money-moving event. Adyen: 16-digit per-transaction reference. |
| Processor reference / lifecycle | source (ch_ / py_ / re_) | Psp Reference + Modification Reference | Stripe source links the txn to its originating object; Adyen modifications carry their own reference. |
| Batch / payout ID | automatic_payout_id (po_) | Batch Number | Groups many transactions into one bank credit. |
| Original-payment link | source (on refund/dispute txn) | Modification Reference | Ties a refund or dispute back to the original payment. |
| Merchant / order reference | metadata (your reference) | Merchant Reference | Your own key. Stripe holds it in metadata; Adyen has a dedicated column. |
| Gross | amount / gross | Gross Debit (GC) / Gross Credit (GC) | Stripe: amount on the txn, gross column in the payout report. Adyen splits debit vs credit. |
| Fee / commission | fee | Commission (NC) + Markup (NC) + Scheme Fees (NC) + Interchange (NC) | Stripe: single fee figure. Adyen: itemized fee breakdown. |
| Net | net | Net Debit (NC) / Net Credit (NC) | Stripe pays net by default; Adyen reports gross and derives net via the fee columns. |
| Refund | reporting_category = refund | Type = Refunded | Posts to the current batch, not the original sale’s batch. |
| Chargeback / dispute | reporting_category = dispute | Type = Chargeback / SecondChargeback | Stripe debits dispute + fee at dispute creation; Adyen uses dedicated journal types. |
| Reserve / adjustment | reserve_hold / reserve_release (type); risk_reserved_funds (reporting_category) | Type = ReserveAdjustment / DepositCorrection | Held funds, not lost. Book to a reserved-balance account. |
| Transaction date | created | Creation Date | When the event occurred — not when it paid out. |
| Settlement / payout date | available_on / automatic_payout_effective_at | Batch Number context; booking date (see docs) | Stripe: available_on = funds available; effective_at = expected bank arrival. Adyen: confirm the booking-date column name. |
| Bank reference | trace_id | payout reference (see runbook / docs) | The value that appears on the bank statement for matching. |
| Record type | type / reporting_category | Type | The field that determines the sign and ledger account. |
Gross-to-net treatment
This is the single structural difference that causes the most systematic reconciliation noise between the two PSPs.
Stripe nets fees into the payout. Each balance_transaction carries amount, fee, and net — the fee is deducted at the transaction level, and the payout you receive is the sum of the net figures. There is no separate fee invoice in the default model. If your expected-fee model treats the Stripe payout as gross, every transaction will mismatch by exactly the fee. The correct expectation: bank credit = Σ net.
Adyen reports gross plus separate fee lines. The Settlement Details Report gives you the gross amount and itemizes the fee into Commission (NC), Markup (NC), Scheme Fees (NC), and Interchange (NC). Net per row is reported in Net Debit (NC) / Net Credit (NC). This is richer for fee analysis — you can decompose exactly what each component cost — but it means your ledger must sum the fee columns to arrive at the same net figure Stripe hands you directly. Adyen also trues up its monthly Processing Invoice as an InvoiceDeduction line in a later batch, so the per-transaction fees in the settlement file are not the whole fee story.
Why this matters for the ledger: if you store only net, you lose Adyen’s fee decomposition and you cannot validate Stripe’s fee against your rate card. Store gross, total fee, and net as three separate fields regardless of PSP — and for Adyen, keep the four fee components too, since that breakdown is the most operationally useful artifact in the file. For the broader picture of what those fee components mean, see reading your processing statement line by line.
Refunds, disputes, reserves, and adjustments
These four record types move money outside the simple sale flow, and each PSP encodes them differently.
Refunds. Stripe: a balance_transaction with reporting_category = refund, linked to the original charge via source. Adyen: a row with Type = Refunded, linked to the original payment via Modification Reference. In both, the refund posts to the current payout or batch — not the batch of the original sale. Match a refund to its original transaction by the link field, never by date.
Disputes / chargebacks. Stripe: reporting_category = dispute (and dispute_reversal if you win), with the dispute amount and fee debited at dispute creation, not at cycle close. Adyen: Type = Chargeback, with SecondChargeback and ChargebackReversed for the later stages. The dispute lifecycle KPIs sit in chargeback operations KPIs; for settlement reading, the point is to recognize the record type and net it correctly.
Reserves. Stripe: type = reserve_hold / reserve_release (reporting_category = risk_reserved_funds). Adyen: Type = ReserveAdjustment for rolling-reserve movements and DepositCorrection for deposit recalculations. A reserve hold reduces your payout but is not a loss — book it to a reserved-balance account with a release schedule. Zeroing reserve lines inflates reported income and hides the liability.
Adjustments. Stripe: type = adjustment. Adyen: a range of correction journal types. These are catch-all corrections; map each to a ledger account rather than discarding.
The sign convention is the trap. Adyen splits debit and credit into separate columns (Gross Debit (GC) vs Gross Credit (GC)); Stripe uses signed amounts on a single amount field (refunds and fees are negative). Normalize both into your ledger’s own sign convention at ingest, keyed off the record type.
Date and timing fields operators must separate
Conflating dates is one of the most common reconciliation mistakes, and it produces breaks that look like data errors but are really field-selection errors.
- Transaction / processing date — Stripe
created; AdyenCreation Date. When the payment happened. - Settlement / batch date — when the transaction was assigned to a settlement batch. Adyen groups by
Batch Number; confirm the exact booking-date column for your report version (see Adyen docs). - Payout date / availability — Stripe
available_on(funds available on your balance) andautomatic_payout_effective_at(expected bank arrival). Adyen: the batch’s payout instruction. - Expected bank-credit date — when the money should land. This is the date you reconcile against the bank statement, and it is almost never the transaction date.
Under any rolling-payout model, the transactions paying out today were captured days ago. Matching today’s bank credit to today’s transaction volume will never balance — reconcile by payout/batch ID, not by calendar day. The same date confusion distorts cash forecasting: if you forecast cash off the transaction date rather than the expected bank-credit date, you systematically overstate near-term available cash. The working-capital impact of that settlement lag is covered in the working-capital cost of payments.
Ledger design checklist
The following is PaymentBrief operator guidance, not a vendor-published schema. The goal is one internal canonical ledger that both PSPs map into, so neither PSP’s column names leak into your accounting logic.
- One canonical transaction record keyed by your own ID, with the PSP’s transaction-level ID (Stripe
balance_transaction, AdyenpspReference) stored as a foreign reference — never as the primary key. - Separate money fields: gross, total fee, and net as distinct columns. For Adyen, also store the four fee components (commission, markup, scheme fees, interchange) so the decomposition is not lost.
- A normalized record-type field mapping each PSP’s type vocabulary (Stripe
reporting_category, AdyenType) into your own enum: sale, refund, chargeback, reserve, fee, adjustment, payout. Sign convention is derived from this field at ingest. - An original-payment link on every refund, dispute, and adjustment, so netting is by reference, not by date.
- A payout/batch grouping field plus the bank reference (Stripe
trace_id, the Adyen payout reference), so the third-leg bank match is a stored join, not a manual search. - Distinct date columns: transaction date and expected bank-credit date at minimum, both stored, never overwritten by each other.
If your canonical schema holds these independently, a PSP switch is a remapping job — write a new ingest adapter — not a reconciliation rebuild.
What to persist at each stage
Also PaymentBrief operator guidance. Persist these in your own database as the payment progresses, so the mapping survives a PSP migration and so investigations never depend on the PSP’s search API.
- At authorization: your order reference, the PSP’s payment/processor reference, amount, currency, timestamp.
- At capture: the PSP transaction-level ID (Stripe
balance_transaction, AdyenpspReference) — this is the single highest-leverage field to store, because every later reconciliation step keys off it. - At refund: the refund’s own ID and its link back to the original payment (Stripe
source, AdyenModification Reference). - At dispute: the dispute ID, the original-payment link, and the debit amount and fee.
- At settlement: the payout/batch ID, the per-transaction net, and the fee breakdown.
- At payout: the bank-level reference (Stripe
trace_id, the Adyen payout reference) and the expected bank-credit date, so the bank statement match is ready before the credit arrives.
Common reconciliation mistakes
- Treating the settlement file as a bank statement. The file is the processor’s intent to pay; only the bank statement confirms receipt. Skipping the third leg hides missing-credit breaks.
- Matching on gross when the PSP paid net. Stripe pays net per
balance_transaction. If your expected-fee model expects a gross credit, every row mismatches by the fee. Establish the settlement model before reconciling. - Using the payout date as the transaction date. Under rolling payouts, the two are days apart. Reconcile by payout/batch ID, not calendar day, or every day will appear to break.
- Not persisting the processor reference at capture. If you do not store the Stripe
balance_transactionor AdyenpspReferencein your own ledger, every investigation depends on the PSP’s search API and on report exports — slow and fragile. - Assuming fee structure is identical across PSPs. Stripe gives you one fee figure; Adyen itemizes into commission, markup, scheme fees, and interchange, and trues up monthly via
InvoiceDeduction. A fee model built for one will misread the other. - Collapsing gross, fee, and net into a single net field. You lose the ability to validate fees and to decompose Adyen’s breakdown. Store all three.
Related references
- PSP reconciliation failure runbook — the break taxonomy, the full matching-ID chains, and escalation. This reference explains the fields; the runbook covers what breaks.
- AI-powered payment reconciliation — exception triage and the continuous-close pattern that sits on top of the matching layer.
- Reconciliation automation with LLMs — LLM architecture for exception categorization and fuzzy matching.
- The working-capital cost of payments — why separating the transaction date from the bank-credit date matters for cash forecasting.
- PSP vendor lock-in and hidden costs — the contract-level mechanics that make a stable internal mapping worth building before you need to switch.
Scope note
- Four layers, kept distinct: (a) the universal settlement object model — rail-agnostic concepts; (b) Stripe-specific reporting fields — verified against Stripe docs; (c) Adyen-specific reporting fields — verified against Adyen docs; (d) PaymentBrief operator guidance — the ledger-design and persistence checklists, which are this site’s recommendations, not vendor-published schemas.
- Stripe and Adyen only. Checkout.com and Worldpay are excluded because their settlement-report field documentation is partially login-gated and could not be verified to the field level here. Their settlement models are touched on in the reconciliation runbook; a field-level reference for them is a future expansion, not part of this article.
- Field names verified against official docs as of 13 June 2026 (the access date in the sources below). Vendor documentation changes — column sets and report versions are revised over time. Where an exact column could not be pinned (notably the Adyen booking-date column name and the exact bank-payout reference label), the concept is described and marked “(see docs)” rather than guessed. Confirm against the current vendor documentation before building ingest logic.
Sources & methodology (8)
Stripe balance_transaction object: id uses the txn_ prefix; carries amount, fee, net (net = amount - fee), currency, available_on, created, status, source, type, and reporting_category
Checked:
Stripe balance_transaction type values include charge, refund, payment, payout, adjustment, stripe_fee, reserve_hold, reserve_release, and dispute-related types; reporting_category is the accounting-grouping field
Checked:
Stripe reporting_category values include charge, refund, fee, dispute, dispute_reversal, payout_reversal, partial_capture_reversal, platform_earning, connect_reserved_funds, and risk_reserved_funds
Checked:
Stripe Payout reconciliation report columns include balance_transaction_id, automatic_payout_id, automatic_payout_effective_at, gross, fee, net, currency, reporting_category, and trace_id (the bank-level reference)
Checked:
Adyen Settlement Details Report columns include Company Account, Merchant Account, Psp Reference, Merchant Reference, Payment Method, Creation Date, TimeZone, Type, Modification Reference, Gross Currency, Gross Debit (GC), Gross Credit (GC), Net Currency, Net Debit (NC), Net Credit (NC), Commission (NC), Markup (NC), Scheme Fees (NC), Interchange (NC), and Batch Number
Checked:
Adyen Settlement Details Report Type column values include Settled, Refunded, Chargeback, SecondChargeback, ChargebackReversed, Fee, MerchantPayout, InvoiceDeduction, ReserveAdjustment, DepositCorrection, and Balancetransfer
Checked:
Adyen fee components defined: Interchange (paid to the issuer, set by the card network), Scheme Fees (set by the card scheme), Markup (the IC++ margin component), and Commission (fees due to Adyen)
Checked:
Adyen reporting splits settlement reconciliation into transaction-level (Settlement Details Report) and batch-level (Aggregate Settlement Details Report); the Payment Processing Invoice is trued up against settlement as an InvoiceDeduction
Checked:
Source types explained in our Methodology.