How to Normalize Chargeback Data Across Multiple Payment Processors

Contracargos?
Ya no es problema tuyo.
Recupera cuatro veces más Contracargos y prevención , hasta un 90 % de las entradas, gracias a IA y a una red global de 20 000 comercios.

En resumen:
- Translate each PSP dispute into one canonical record, and keep the raw payload and mapping version so any value can be traced back.
- Status vocabularies differ by PSP, and PayPal needs both status and outcome to express a win or loss, so map values through a versioned table.
- Stripe and Adyen send amounts in minor units while Braintree and PayPal send decimals, so convert by each currency's decimal places.
- Adyen's CHARGEBACK_REVERSED is provisional, not a win, because the issuer can still present a second chargeback.
- Store card network, received date and capture date so Visa VAMP and Mastercard ECP ratios can be rebuilt from your own data.
Every processor describes the same chargeback in its own words. An open chargeback that needs a reply is needs_response in Stripe, OPEN in Braintree and WAITING_FOR_SELLER_RESPONSE in PayPal.
Copy those models into a platform, and processor logic spreads into dashboards, automation, reporting and support. A canonical dispute model stops that spread. It is a core layer of chargeback management for payment platforms.
{{cta}}
What a canonical dispute record contains
Start with the fields every product team needs, whatever the PSP. Seven field groups cover most platform behavior.
Canonical dispute object: seven field groups
| Field group | What the platform needs |
|---|---|
| Identidad | Canonical dispute ID plus processor, processor account, source dispute and source transaction IDs. |
| Ownership | Platform tenant, merchant account and permitted viewers. |
| Financial | Disputed amount, currency, fee, provisional debit and recovered amount. |
| Lifecycle | Canonical stage and status, source status and transition timestamps. |
| Time | Source due date, internal due date, received time and last synchronized time. |
| Pruebas | Required artifacts, supplied artifacts, evidence ID, version and submission result. |
| Resultado | Won, lost, accepted, expired or withdrawn, with decision and settlement timestamps. |
Anything outside these groups goes into a source extension or the raw payload.
Why one dispute model matters as volume grows
Each new PSP adds its own status values, deadline formats and reason codes. Dispute volume is growing at the same time, so the cost of per-processor logic grows with it.
286M chargebacks projected worldwide in 2026 | $46.1B global chargeback cost forecast for 2029, up from $36.9B in 2026 | +37% growth in chargeback volume from 2025 to 2029 |
Source: Mastercard, What is the true cost of a chargeback for businesses?, research by Datos Insights, updated June 2026.
Separate canonical meaning from source representation
The canonical object answers questions that stay stable across PSPs. Who owns the case? Which transaction is disputed? What action is required, when is it due and how did it end?
Use two fields when meanings differ: a canonical field for shared behavior and a source field for fidelity. Keep both canonical status and source status. Map each source reason into a reason family, and keep the original chargeback reason codes from the network or processor.
Stripe already works this way inside one PSP. Each Stripe dispute carries a Stripe reason category and the card network's own code in network_reason_code.
How Stripe, Adyen, Braintree and PayPal describe the same dispute
Three fields cause most mapping errors: the response deadline, the amount and the reason code. The table shows where four PSPs put them, based on each provider's public API reference as of October 2026.
Where four PSPs put the deadline, amount and reason code
| PSP | Plazo para responder | Amount format | Reason code |
|---|---|---|---|
| Stripe | evidence_details.due_by, a Unix timestamp in seconds | amount as an integer in the currency's minor unit, plus a lowercase ISO currency code | reason (Stripe category) plus payment_method_details.card.network_reason_code |
| Adyen | defensePeriodEndsAt in additionalData, an ISO 8601 timestamp with a UTC offset | amount.value in minor units, plus amount.currency | chargebackReasonCode in additionalData |
| Braintree | reply_by_date, a time in UTC | amount_disputed as a decimal in major units, plus currency_iso_code | reason, plus the processor's reason_code and reason_description |
| PayPal | seller_response_due_date, an RFC 3339 date-time | dispute_amount.value as a decimal string in major units, plus currency_code | reason, read with dispute_life_cycle_stage |
Two traps follow. First, a USD 49.99 dispute arrives as 4999 from Stripe and Adyen but as 49.99 from Braintree and PayPal. Convert with each currency's decimal places, not a fixed divide by 100, because zero-decimal currencies such as JPY have no minor unit.
Second, deadlines arrive as epoch seconds, offset timestamps and UTC strings. Store one UTC instant for logic and keep the source value beside it for audit.
Map each PSP status to a canonical state
Status is where a lossy mapping does the most damage. Every value below comes from the PSP's own docs. Where a PSP has no direct equivalent, it is left out rather than forced into a match.
Canonical status mapping for Stripe, Adyen, Braintree and PayPal
| Canonical state | Documented source values | Mapping note |
|---|---|---|
| Inquiry, response needed | Stripe: warning_needs_response. Adyen: REQUEST_FOR_INFORMATION event. Braintree: kind RETRIEVAL. PayPal: stage INQUIRY. | Keep the source stage. A PayPal inquiry and a card-issuer retrieval request are different processes. |
| Chargeback, response needed | Stripe: needs_response. Adyen: NOTIFICATION_OF_CHARGEBACK event. Braintree: OPEN. PayPal: WAITING_FOR_SELLER_RESPONSE. | Drive alerts from the canonical due date, not from the status label. |
| Responded, awaiting decision | Stripe: under_review. Adyen: disputeStatus Responded. Braintree: DISPUTED. PayPal: UNDER_REVIEW. | Record the submission time and the evidence version that moved the case here. |
| Provisionally reversed | Adyen: CHARGEBACK_REVERSED with disputeStatus Pending. | Not a win yet. Adyen notes the issuer can still present a second chargeback, which ends as SECOND_CHARGEBACK with status Lost. |
| Ganó | Stripe: won. Adyen: disputeStatus Won. Braintree: WON. PayPal: RESOLVED with outcome RESOLVED_SELLER_FAVOUR. | PayPal needs two fields, status and outcome, to express one canonical state. |
| Perdido | Stripe: lost. Adyen: disputeStatus Lost. Braintree: LOST. PayPal: RESOLVED with outcome RESOLVED_BUYER_FAVOUR. | Stripe also sets lost when a merchant closes (accepts) a dispute, so keep a separate accepted flag. |
| Accepted or expired | Adyen: disputeStatus Accepted or Expired. Braintree: ACCEPTED, AUTO_ACCEPTED or EXPIRED. | Keep "chose not to fight" apart from "missed the deadline". Each needs a different follow-up. |
| Closed before chargeback | Stripe: warning_closed or prevented. | Stripe's monitoring documentation notes that unescalated inquiries do not count as disputes for network monitoring. |
Two rows need special care. Adyen's CHARGEBACK_REVERSED returns the funds but is not final, so mapping it to won will overstate recovery. And Stripe's lost covers both a decision and a merchant who accepted the dispute.
Normalize for network monitoring, not only for workflow
A model built only on PSP statuses cannot rebuild the ratios that Visa and Mastercard use to monitor merchants. The networks count by their own rules, and those rules ignore outcomes. Stripe's docs on the programs list the key gaps.
How Visa and Mastercard count disputes for monitoring
| Regla | Visa VAMP | Mastercard ECP |
|---|---|---|
| What counts | Disputes from TC15 reports plus fraud reports from TC40. A transaction in both reports counts twice. | Chargebacks, whether or not a refund, liability shift or win followed. |
| Ratio timing | Disputes and fraud against captured payments in the same calendar month. | This month's chargebacks against the previous month's transactions. |
| Excessive merchant threshold | 1.5% ratio and 1,500 count from April 2026 in the US, Canada, EU, AP and LAC. CEMEA: 2.2%, 150 count and USD 75,000. | ECM: 100 to 299 chargebacks and a 1.5% to 2.99% rate. HECM: 300+ chargebacks and 3%+. |
| Effect of the outcome | None. A won dispute still counts. | None. Winning does not remove the chargeback from the count. |
To support these counts, add a few fields to the canonical record: card network, the date the network received the dispute, the capture date of the original payment and an inquiry flag. Store fraud reports as their own event type.
Ratio reporting can then follow each network's rule instead of one PSP's dashboard. For full program rules, see the Visa Acquirer Monitoring Program (VAMP) guide. For ratio formulas, see the guide to chargeback data.
Model lifecycle as events and current state
A current-state record is easy for product reads, but it cannot explain how the case got there. Store an append-only event history next to the current dispute record. Each event should include source, event ID, event time, received time, payload version and mapping version.
This makes late or out-of-order dispute webhooks manageable. The projection can reject an older transition without losing the event. Support teams can rebuild the timeline when the platform and PSP disagree.
Use a mapping version and explicit unknown state
Mappings change as processors add reason codes and statuses. Tag every normalized event with the mapping version used. When the platform does not recognize a value, put it in an explicit unknown state and alert the owning team.
Silently converting an unknown value to a generic status can trigger the wrong automation. For example, a new terminal status read as actionable may cause the platform to generate or submit evidence after the case has closed.
Keep deadlines and money as first-class fields
Dates and amounts should not be buried in processor payloads. Store the source response deadline, the platform's internal deadline and the instant used for comparison. Keep dispute amount, fee, provisional debit and recovered amount as separate fields.
Teams need these splits to set priorities and for chargeback reconciliation. A won dispute can still carry fees, timing gaps or settlement adjustments, so the disputed amount rarely equals the cash recovered.
Test semantic equivalence, not only JSON shape
Contract tests should check more than required fields. Feed equivalent disputes from two processors into their adapters. Then confirm the canonical objects produce the same product behavior.
Next, test the exceptions: partial disputes, several disputes on one transaction, currency differences, evidence regeneration and late outcome changes. Keep fixtures built from production-like payloads with sensitive values removed. Re-run them when mappings or PSP API versions change.
Make normalization reversible
Five records that keep a mapping traceable
Normalization is only trustworthy when an operator can trace a canonical field back to the source that produced it. So the schema keeps meaning at several levels instead of flattening provider data into one lossy record.
The stable concept used by product logic, such as response deadline, dispute state or disputed amount.
A namespaced field for provider-specific meaning that has no safe cross-processor equivalent.
The unmodified payload or file row, its source timestamp and an immutable object reference.
Processor, API or file version, transformation version, processing time and validation result.
A controlled job that can reprocess historical raw events after a mapping fix without overwriting the prior interpretation.
Research basis: Pagos data harmonization and Hyperswitch guide to dispute lifecycle normalization.
The mapping version belongs on each case and event. It makes a provider schema change auditable, supports backfills and stops a corrected translation from silently rewriting historical reports.
{{cta}}
Implementation sequence
The build follows seven steps, from source schemas to monitoring. Teams still weighing an in-house build can compare options in build vs. buy chargeback management.
Seven build steps
Document identifiers, statuses, reasons, deadlines, amounts and event semantics for each PSP.
Choose the minimum shared fields needed by product, operations, finance and risk.
Keep raw payloads and source-specific fields outside the common core.
Map source values to canonical values with versioning and an explicit unknown path.
Store immutable events and derive the current dispute state.
Check that the same event from two PSPs leads to the same platform behavior.
Alert on new source codes, fields or invalid transitions.
Moving vendors mid-build? Export chargeback data before switching providers so the raw payloads behind your mappings survive the move.
Failure modes and controls
Common implementation risks and their controls
| Failure mode | Business consequence | Control |
|---|---|---|
| Lowest-common-denominator schema | Useful processor detail disappears. | Use a common core plus source extensions and raw payloads. |
| Mutable record with no event history | Late events overwrite context and cannot be audited. | Store append-only source and canonical events. |
| No mapping version | Historical behavior cannot be reproduced. | Record mapping version on every normalized event. |
| Amount without currency | Cross-border reporting and reconciliation become unsafe. | Model every monetary field as amount and currency. |
| Unknown values mapped to other | Automation continues with ambiguous meaning. | Quarantine unknown states and require a mapping decision. |
How Chargeflow Connect fits
Chargeflow documents a dispute state machine that unifies stages and statuses across every connected PSP. Stage covers inquiry, chargeback, pre-arbitration and arbitration. Status covers needs response, under review, won and lost.
Chargeflow Connect lets a platform read that one model across processors such as Stripe, Adyen, Braintree, PayPal and Checkout.com. The platform stores its own tenant and transaction IDs alongside it. Platforms can surface it through embedded chargeback management or call a chargeback API from their own interface.
With Evidence-as-a-Service, the platform sends dispute data over the API and Chargeflow returns a PDF evidence package, announced by webhook with a secure download link. Each new run raises file_version by one, so save that number in the case's evidence history. See how automated chargeback evidence generation works.
Dispute data normalization checklist
- Every dispute has one canonical ID plus the processor, account and source IDs it came from.
- Stage and status live in separate fields, and each PSP value maps through a versioned table.
- Amounts carry a currency and convert by that currency's decimal places.
- Deadlines are one UTC instant, with the original source value kept beside it.
- Unknown values pause automation until someone approves a mapping.
- Card network, received date and capture date are stored, so VAMP and ECP ratios can be rebuilt.
Related platform guides
- Native PSP Dispute Tools vs. Processor-Agnostic Chargeback Management
- Embedded, Co-Branded or API-Based Chargeback Management: Which Model Should a Platform Choose?
- How Payment Orchestration Platforms Can Add Chargeback Management Across Every PSP
- Multi-processor chargeback recovery: the merchant-side technical guide to case keys, webhooks and ledgers
- How to manage chargebacks across multiple payment processors
- Payment platform disputes, explained for PSPs, PayFacs and marketplaces
Preguntas frecuentes
What is a canonical data model for chargebacks?
A canonical data model for chargebacks is one shared schema that every processor's disputes are translated into. It fixes field names, units and state values for the platform. Each PSP adapter does the translation and keeps the original payload for audit.
Should a canonical schema include every PSP field?
No. A canonical dispute schema should hold the fields needed for shared product behavior. The remaining source fields belong in a versioned extension or the raw payload.
Should stage and status be one field?
No. Stage describes how far the dispute has escalated in the network process, such as inquiry or pre-arbitration. Status describes the action or outcome at that stage, such as needs response or won.
How should reason codes be normalized?
Map reason codes into stable reason families for analytics, and keep the original network or processor code. Evidence and operations teams need the exact code, because evidence rules differ by code.
How should late webhook events be handled?
Store every late dispute event, compare its source and received timestamps, and apply transition rules before updating the current-state record. An older event should never overwrite a newer state.
What should happen when a processor adds a new status?
A new processor status should land in an unmapped state. The integration should pause unsafe automation and wait for an explicit mapping release.
How do you centralize chargeback data from multiple processors?
To centralize chargeback data from multiple processors, pull disputes from each one through its API or webhooks and translate them into one canonical record. Store the raw payload and mapping version with it. Reporting, deadlines and evidence workflows then read one model instead of one integration per PSP.
Is there a 120-day limit for chargebacks?
Cardholders usually have 120 days to file a chargeback, and Visa and Mastercard allow up to 540 days in specific cases. That filing window differs from the merchant response deadline, which each PSP reports in its own field. See Chargeflow's guide to chargeback time limits.
Sources and further reading
- Chargeflow dispute state machine
- Chargeflow Connect integrations
- Chargeflow Evidence-as-a-Service overview
- Chargeflow platform webhook events
- Stripe API reference: the Dispute object
- Stripe API reference: close a dispute
- Stripe supported currencies and minor units
- Adyen dispute notifications
- Adyen currency codes and minor units
- Braintree dispute response reference
- PayPal Disputes API
- Mastercard: What is the true cost of a chargeback for businesses? (updated June 2026)
- Pagos data harmonization
- Hyperswitch: how payment orchestration normalizes the dispute lifecycle
Add Chargeback Management to Your Platform
Use a platform-first integration to offer chargeback automation across your merchant base.

Contracargos?
Ya no es problema tuyo.
Recupera cuatro veces más Contracargos y prevención , hasta un 90 % de las entradas, gracias a IA y a una red global de 20 000 comercios.













.png)


