Wallet Disputes

Review the disputes your wallet holders open, talk to them, decide each case, and carry out the outcome.

A holder can dispute an entry on their wallet: a card load that went wrong, or a charge you made. You are the first to decide the case. This page walks through the lifecycle, from the holder filing a dispute to the money moving.

Before you start

How a dispute starts

The holder files a dispute from their wallet against one entry, with a reason (unauthorized, duplicate-charge, incorrect-amount, not-credited or other), the amount they claim, and an optional statement. A holder can only have one live dispute per entry, and only within the dispute window of your program. Disputes have IDs starting with DS-.

Payment Labs then sends wallet-dispute-opened. The webhook's data is the dispute as it is at delivery time.

Statuses

statusMeaningFinal?
openFiled, nobody is reviewing it yet.No
under-reviewYou picked it up.No
needs-more-infoYou asked the holder for information. They have 7 days to reply.No
acceptedYou agreed an outcome and amount. The money moves when you resolve it.Final decision
declinedYou declined it, with a reason the holder reads.Yes
withdrawnThe holder cancelled it.Yes
expiredThe holder did not reply to your request for information within 7 days.Yes
superseded-by-chargebackThe holder's bank took the money back through a card chargeback first.Yes
open ──pick up──► under-review ◄──holder replies── needs-more-info
  │                   │   └──request information──────────►│
  │                   │                                     └──no reply in 7 days──► expired
  └───────────────────┴──► accepted ──resolve──► money moves
                      └──► declined

Every status change sends wallet-dispute-status-changed.

Step 1: Find and read disputes

  • Search with Search Wallet Disputes. Filter on statusGroup to build a work queue: open (statuses open and needs-more-info), under-review, or resolved (every final status). You can also filter on disputeId, holderId, subjectEntryId, status and createdAt.
  • Read one with Get Wallet Dispute. Besides the dispute it returns holderId and takenOver.
  • Find the disputed entry with Search Wallet Entries, filtering entryId on the dispute's subjectEntryId.

Step 2: Pick it up

Pick Up Wallet Dispute moves an open (or needs-more-info) dispute to under-review, so the holder sees that someone is looking at it. It has no body.

Step 3: Talk to the holder

The dispute has one conversation that you and the holder both read.

{
  "body": "Please send the card statement that shows this load.",
  "attachments": [{ "mimeType": "application/pdf", "fileName": "load-receipt.pdf", "size": 48213 }]
}

The response is 201 with one upload per declared file. Send each file with a PUT to its uploadUrl, with the uploadHeaders exactly as given and Content-Type set to the file's mimeType. The file must be exactly the declared size. Upload and download links last one hour.

Your messages never change the status. To require an answer, use the next step.

  • Ask for information: Request Wallet Dispute Information moves an open or under-review dispute to needs-more-info and sets responseDueAt to 7 days from now. Send a message first that says what you need. When the holder replies, the dispute returns to under-review. If they do not, it becomes expired.

Every new message sends wallet-dispute-message-added, with the dispute and the new messageId.

Step 4: Decide

Before you accept, call Get Wallet Dispute Resolution Options. It lists the outcomes the disputed entry allows and the most each can pay:

Disputed entryOutcomes you can choose
One of your chargeswallet-credit
A card load that was credited to the walletcard-refund, wallet-credit
A card load that was never credited to the walletcomplete-credit, card-refund
OutcomeWhat resolving it does
card-refundRefunds the amount to the holder's card, out of the load.
wallet-creditCredits the amount to the holder's wallet from your funds. Needs a batch when you resolve.
complete-creditBooks the credit that the load never received.

Then either:

  • Accept: Accept Wallet Dispute with the outcome and the agreed amount, in minor units of the dispute's currency (1500 = $15.00), at least 1 and no more than the claim.

    { "outcome": "card-refund", "amount": 1500 }

    Accepting records your decision and moves the dispute to accepted. It does not move money. The outcome is checked only when you resolve, so choose it from the resolution options.

  • Decline: Decline Wallet Dispute with a reason (up to 2,000 characters) that the holder reads. The dispute moves to declined.

You can accept or decline from open, under-review or needs-more-info.

Step 5: Resolve

Resolve Wallet Dispute carries out the accepted outcome and moves the money.

{ "batchId": "B-01JDA1B2C3D4E5F6G7H8J9K0M1" }
  • batchId is required for wallet-credit (the credit is paid as a virtual payment in that batch) and ignored otherwise. Send an empty body for the other outcomes.
  • Retrying is safe: a card-refund or wallet-credit retry returns the same result and never moves money twice. A repeated complete-credit is refused with 409 DISPUTE_OUTCOME_NOT_PERMITTED, because the load is already credited.
  • If the load can no longer pay for the outcome, for example because the holder spent it, the call returns 409 DISPUTE_RESOLUTION_ESCALATED. The dispute stays accepted and Payment Labs takes it from there.

When Payment Labs takes over

Payment Labs can take over a live dispute. takenOver is then true on Get Wallet Dispute, and pick-up, request information, accept and decline return 409 DISPUTE_NOT_ADJUDICABLE. You can still read the dispute and its messages.

Errors and edge cases

ErrorOperationMeaning
404 NOT_FOUNDAllThe dispute does not exist or is not in your program.
409 DISPUTE_NOT_ADJUDICABLEPick up, request information, accept, declineThe dispute is in a status that does not allow this, or Payment Labs has taken it over.
400 VALIDATION_ERRORAcceptoutcome is unknown, or amount is not a whole number of at least 1.
400 DISPUTE_EXCEEDS_CLAIMAcceptamount is more than the holder claimed.
400 VALIDATION_ERRORDecline, messagereason or body is missing, blank, or over 2,000 characters; or an attachment is invalid, too large, or one too many.
409 DISPUTE_NOT_RESOLVABLEResolveThe dispute has not been accepted.
409 DISPUTE_OUTCOME_NOT_PERMITTEDResolveThe disputed entry cannot take the accepted outcome.
400 CREDIT_BATCH_REQUIRED, 400 CREDIT_BATCH_INVALIDResolveA wallet-credit needs a usable batch.
409 HOLDER_NOT_PAYABLEResolveA wallet-credit cannot be made until the holder finishes onboarding. Retry later.
409 CUSTOMER_FROZENResolveYour wallet program is frozen. Contact Payment Labs support.

Webhook payloads carry the dispute as it is when the webhook is delivered. If deliveries arrive late, trust the latest status, or read the dispute.

Next steps


What’s Next

Did this page help you?