Sent each time a wallet dispute moves, whether you, the holder or Payment Labs moved it.
wallet-dispute-status-changed tells you that a wallet dispute moved. It fires for your own actions too, so one integration can follow every dispute without polling.
When it fires
| Trigger | status after |
|---|---|
| You pick up the dispute with Pick Up Wallet Dispute. | under-review |
| You ask the holder for more with Request Wallet Dispute Information. | needs-more-info |
The holder answers while the dispute is needs-more-info. | under-review |
| You accept with Accept Wallet Dispute. | accepted |
| You decline with Decline Wallet Dispute. | declined |
| The holder cancels the dispute. | withdrawn |
The holder does not answer before responseDueAt. | expired |
| The card issuer reverses the load first (a chargeback). | superseded-by-chargeback |
| Payment Labs takes the dispute over, decides it, or changes a decision. | under-review, accepted or declined |
When Payment Labs takes a dispute over or changes the outcome of an accepted one, the delivery can carry the same status as before. After a take-over, your own decisions on that dispute are refused with 409 DISPUTE_NOT_ADJUDICABLE.
Resolve Wallet Dispute does not change the status and does not fire this event.
What to do
data.status | Suggested action |
|---|---|
under-review | Continue your review. |
needs-more-info | Wait for the holder's answer, or for responseDueAt. |
accepted | Call Resolve Wallet Dispute to move the money, unless you already did. |
declined, withdrawn, expired, superseded-by-chargeback | Close the dispute in your system. Nothing else can change it. |
Payload
data is the dispute as Get Wallet Dispute returns it, without holderId and takenOver, read when the webhook is sent. Fields with no value are omitted. Amounts use the Money object.
| Field | Type | Description |
|---|---|---|
disputeId | string | Dispute ID, for example DS-01JD7C3E5G7J9L1N3Q5S7U9W1Y. |
walletId | string | ID of the wallet the dispute is about. |
status | string | Where the dispute stands. See Dispute statuses. |
reasonCode | string | Why the holder disputes the entry. See Reason codes. |
disputedAmount | Money | Amount the holder claims. Never more than what could still be claimed when the dispute was filed. |
subjectEntryId | string | ID of the wallet entry being disputed. |
subjectEntryType | string | Kind of entry disputed: deposit (a card load) or charge (a spend from the wallet). Absent on older disputes, which are all deposits. |
transactionId | string | ID of the checkout transaction that paid for the load. Set for deposit disputes only. |
holderStatement | string | The holder's own explanation. Always set when reasonCode is other. |
responseDueAt | string | Deadline for the holder to answer, in ISO 8601 UTC. Set while status is needs-more-info. |
outcome | string | What was agreed. Set when status is accepted. See Outcomes. |
agreedAmount | Money | Amount agreed, which can be less than disputedAmount. Set when status is accepted. |
declineReason | string | Why the dispute was declined. The holder sees this text. Set when status is declined. |
createdAt | string | When the holder filed the dispute, in ISO 8601 UTC. |
updatedAt | string | When the dispute last changed, in ISO 8601 UTC. |
Dispute statuses
| Status | Meaning |
|---|---|
open | Filed. Nobody has picked it up yet. |
under-review | Being reviewed, by you or by Payment Labs. |
needs-more-info | Waiting for the holder to answer, before responseDueAt. |
accepted | Final. Decided in the holder's favour, with an outcome and agreedAmount. |
declined | Final. Decided against the holder, with a declineReason. |
withdrawn | Final. The holder cancelled the dispute. |
expired | Final. The holder did not answer before responseDueAt. |
superseded-by-chargeback | Final. The card issuer reversed the payment first, so the dispute no longer applies. |
New statuses may be added. Treat a value you do not recognise as "in progress" and fetch the dispute.
Reason codes
| Code | Meaning |
|---|---|
unauthorized | The holder says they did not make the transaction. |
duplicate-charge | The holder says they were charged twice. |
incorrect-amount | The holder says the amount is wrong. |
not-credited | The holder paid for a load, but the wallet was never credited. |
other | Anything else. holderStatement explains it. |
Outcomes
| Outcome | Meaning |
|---|---|
card-refund | Refund the card that paid for the load. Deposits only. |
wallet-credit | Credit the wallet from your funds. Does not reverse the card. |
complete-credit | Credit the wallet with the load it never received. Deposits only. |
Accepting a dispute records the outcome only. Money moves when the dispute is resolved with Resolve Wallet Dispute.
Example
The full request body Payment Labs sends:
{
"payorId": "6f1c2a7e-4b8d-4e0f-9a3c-2d5b7e9f1a04",
"event": "wallet-dispute-status-changed",
"timestamp": "2026-04-12T09:03:18.020Z",
"data": {
"disputeId": "DS-01JD7C3E5G7J9L1N3Q5S7U9W1Y",
"walletId": "W-01JC2R4T6V8X0Z2B4D6F8H0K2M",
"status": "accepted",
"reasonCode": "incorrect-amount",
"disputedAmount": {
"value": 40,
"wholeValue": 4000,
"currency": "USD",
"formattedValue": "$40.00",
"digits": 2
},
"subjectEntryId": "WE-01JD7B1C3E5G7J9L1N3Q5S7U9W",
"subjectEntryType": "deposit",
"transactionId": "ST-01JD7A9B1D3F5H7K9M1P3R5T7V",
"holderStatement": "I loaded $60 but my card was charged $100.",
"createdAt": "2026-04-10T16:22:05.000Z",
"updatedAt": "2026-04-12T09:03:17.000Z",
"outcome": "card-refund",
"agreedAmount": {
"value": 40,
"wholeValue": 4000,
"currency": "USD",
"formattedValue": "$40.00",
"digits": 2
}
}
}