Developers › After the payment
Disputes
Verified 6 November 2026Explain this to your team →
How a dispute reaches you
Disputes are handled by hand. A chargeback arrives here as an email from the bank with a case reference, and somebody at Secure Processing reads it and records it. It is worth knowing because it decides the timings below.
When that happens you get a dispute.created webhook, and an email with the deadline in the subject line goes to your account's owner, who cannot turn it off, and by default to everyone else on your team who can answer disputes. The dispute also appears in your dashboard under Disputes, and the payment it came from has disputed: true.
POST /v1/disputes. A chargeback is something the card network asserted; a business declaring one about its own payment would be moving its own money into reserve and back out again.An inquiry is not a chargeback
Sometimes the cardholder’s bank asks a question before taking anything — a retrieval request. Those arrive with a status beginning warning_, and no money is held. Answer it well and it may never become a chargeback.
If the network escalates it anyway, the same dispute moves from warning_needs_response to needs_response, the money is held at that moment, and you get a dispute.funds_withdrawn event. It is never a second dispute.
| Status | What it means |
|---|---|
| warning_needs_response | An inquiry. Nothing has been taken. Answer it. |
| warning_under_review | Your answer to an inquiry is with the bank. |
| warning_closed | The inquiry ended. No money moved at any point. |
| needs_response | A chargeback. The amount is out of your balance and evidence is due. |
| under_review | Your evidence is with us and on its way to the bank. |
| won | The bank found for you. The held amount is back in your balance. |
| lost | The bank found for the cardholder. The money stays gone. |
What happens to the money
Opening a chargeback moves the disputed amount out of your available balance and into a reserve. Winning moves it back; losing writes it off. Every step is a balance transaction you can see, and the ids are on the dispute object.
| When | What moves | On your statement |
|---|---|---|
| The dispute is opened | The disputed amount leaves your available balance | a dispute line, negative |
| You win | The same amount comes back | a dispute_reversal line, positive |
| You lose | Nothing further — it left at the start | no extra line, by design |
| A handling fee is charged | The fee leaves your available balance | a dispute line: amount 0, fee positive (what we charged, as on a charge), net negative |
The amount in the ledger is in Belize dollars at the rate the payment was taken at, which is why the dispute object carries both amount (the payment's currency) and settlement_amount (BZD).
Answering it
Evidence uses Stripe’s field names, so a library or a habit you already have will fit. Fields merge — sending the shipping section does not erase the receipt you sent yesterday — and sending null clears one.
curl https://api.secureprocessing.app/v1/disputes/dp_4fH7jK9mN2pQ5rT8vX1zA3bC \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"evidence": {
"shipping_carrier": "DHL",
"shipping_tracking_number": "CP123456789BZ",
"product_description": "One dive mask, collected in store"
}
}'The file fields — receipt, shipping_documentation, customer_communication and the rest — take a file_ id. Uploading a file is session-only, so attach documents from the dashboard: they are often invoices naming a customer or a signed delivery note, and an API key is a long-lived credential in an environment variable.
When you are ready, send it. You can do this in the same call:
curl https://api.secureprocessing.app/v1/disputes/dp_4fH7jK9mN2pQ5rT8vX1zA3bC \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{ "submit": true }'The deadline
evidence_details.due_by comes from the cardholder’s bank and cannot be extended. A dispute with no answer is lost by default, so this is the one field on the object worth alerting on.
We email the owner, and by default everyone else on your team who can answer disputes, three days before the deadline and again the day before. We stop there: a third email on the morning it expires would arrive too late to act on. After the deadline the reminders stop and a person here chases the bank instead.
Accepting one
If you are not going to contest a dispute, say so and we will stop asking:
curl -X POST https://api.secureprocessing.app/v1/disputes/dp_4fH7jK9mN2pQ5rT8vX1zA3bC/close \
-H "Authorization: Bearer sk_test_..."The method is called close because that is what Stripe calls it, and it means the same thing: you accept the loss. It moves no money on its own and it does not mark the dispute lost — the network has not decided yet, and we will not debit you ahead of them. A chargeback becomes under_review, an inquiry warning_under_review, and no further evidence is accepted.
You can accept only while the dispute is waiting for your response. Once you have submitted evidence the case is already with the bank, and accepting answers 400 and changes nothing. If you decide to concede after submitting, email support with the dispute id and we will tell the bank.
Events
| Event | When |
|---|---|
| dispute.created | A chargeback or an inquiry was raised. The deadline is in evidence_details. |
| dispute.funds_withdrawn | The amount left your available balance. An inquiry does not fire this. |
| dispute.updated | Evidence saved or submitted, you accepted, or an inquiry escalated. |
| dispute.funds_reinstated | You won and the money is back. |
| dispute.closed | The bank answered. status is won, lost, or warning_closed. |
Fees
A lost chargeback may carry a handling fee, charged to your available balance as its own balance transaction. It is not automatic and it is not a percentage: somebody decides it, it is on the dispute as dispute_fee, and the reason is in outcome_note. There is never a fee on a dispute you won.