Disputes
A dispute is a customer's formal objection to a payment, raised with their bank or payment provider rather than with you. The disputed amount can be taken back from you through a chargeback, while the case runs or when it closes. You can send evidence to contest the dispute, or accept it.
When a dispute arrives
- The customer raises the dispute with their bank or payment provider.
- Rootline registers a dispute against the original payment and notifies you.
- When the disputed amount is taken back, Rootline settles it against your available balance. It is reported as
chargeback_received.
If your available balance does not cover the disputed amount, it goes negative and later payments replenish it.
While the dispute is open, the payment cannot be refunded: refund requests are rejected asynchronously via the refund.schedule.failed webhook, and a refund that was already scheduled before the dispute arrived does not prevent the chargeback debit. See Refunds and disputes.
See the settlement report for the rows, and Introduction to reconciliation for what this means for your balance.
Deciding whether to defend
Accepting is a valid option. Accept when the claim is justified, or when the amount is small enough that gathering evidence costs more than the payment is worth. You do not need to do anything to accept.
Defend when you can address the claim the customer made. Start as soon as you are notified: defense windows are short, and a case can only be submitted once, so it needs to be complete when it goes out.
Defending a chargeback describes what evidence to send for each reason.
Dispute reasons
Every dispute has one reason. It tells you what the customer is claiming, which determines what evidence is worth sending. The reason code from the bank or payment provider is available alongside it.
| Reason | What the customer claims |
|---|---|
unauthorized_transaction | They did not make or approve the payment |
authorization_error | The payment was processed without a valid authorization |
billing_error | Duplicate charge, wrong amount, or a refund that never arrived |
item_not_received | The goods or service never arrived |
item_not_as_described | What arrived was defective or materially different from the offer |
subscription_canceled | They canceled before the billing date |
other | No usable reason was given |
After the decision
The customer's bank or payment provider reviews the evidence and decides. The outcome shows when the dispute closes: won, lost or accepted. While the case is open, the amount can come back as chargeback_returned and be taken again as chargeback_reaffirmed, so a return on its own is not the outcome.
Disputes on a platform
When a payment was split, the chargeback is split the same way. Each account carries the share it received: your client merchants carry their splits, and your platform account carries what it kept. Your settlement report shows which account carries each chargeback.
Rootline notifies you, the platform, and not your client merchant. That leaves three things with you:
- Deciding whether to defend. Your client merchant usually has the facts, but the decision and the deadline are yours.
- Collecting the evidence. You have the payment and checkout records, and your client merchant has proof of delivery, correspondence and their own terms. A complete defense usually needs both.
- Telling your client merchant. When they carry part of a chargeback, it shows in their balance and on their settlement report.
Rootline communicates with you rather than directly with your client merchants, so it helps to plan how you pass a dispute on to them.
Testing
You can run dispute scenarios against your own integration in the staging environment, so you can check your webhook handling and your reconciliation before a real dispute arrives.
Before you start, add the dispute events to your webhook endpoint in the dashboard, under Developer, then Webhooks: dispute.created, dispute.updated, dispute.closed and fraud_notification.received.
Rootline offers the following test scenarios, which you provide in the description field of the /payments request. The scenario runs when the payment is captured.
| Description value | Test scenario |
|---|---|
test_chargeback | A chargeback is raised and the dispute stays open. |
test_chargeback_won | A chargeback is raised, your defense succeeds, and the amount is returned. |
test_chargeback_lost | A chargeback is raised, the amount is returned, then the bank raises the case again and the chargeback stands. |
test_fraud_notification | A fraud notification on its own, with no dispute behind it. |
The description has to hold the scenario value on its own. If it contains anything else, the payment is processed as usual and no scenario runs.
All dispute webhooks of a test scenario arrive within a minute of the capture. In live mode, dispute.updated and dispute.closed arrive later than dispute.created, because they follow the chargeback through settlement.
One difference from a live dispute: reason.provider_reason_code returns the scenario value, because no bank or payment provider sent a code. reason.code still carries a real category, so you can branch on it exactly as you would in production.