> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dispute Webhooks

> The payload sent to your webhook endpoint when a dispute is created or updated. Handle each event to respond to disputes and reconcile your records.

<Info>
  As your [Merchant of Record](/features/mor-introduction), Dodo Payments manages the dispute and chargeback process with the card networks on your behalf. These webhooks keep your systems in sync as a dispute moves through its lifecycle so you can revoke access, gather evidence, and reconcile your records.
</Info>

## Dispute Webhook Events

A dispute emits an event at each stage of its lifecycle:

| Event | Fires when | What it usually means |
| - | - | - |
| `dispute.opened` | A cardholder opens a dispute on a payment | Funds are held; prepare to respond |
| `dispute.challenged` | Evidence has been submitted to contest the dispute | The dispute is being reviewed by the network |
| `dispute.accepted` | The dispute was accepted (not contested) | The funds are returned to the cardholder |
| `dispute.cancelled` | The dispute was withdrawn or cancelled | No further action needed |
| `dispute.expired` | The response window passed without resolution | Typically resolves against you |
| `dispute.won` | The dispute was resolved in your favor | Funds are retained |
| `dispute.lost` | The dispute was resolved in the cardholder's favor | Funds are returned to the cardholder |

<Note>
  Disputes auto-resolved through [Visa Rapid Dispute Resolution (RDR)](/features/transactions/disputes#visa-rapid-dispute-resolution-rdr) appear as `dispute.lost` with `is_resolved_by_rdr: true`. This is expected — the refund was issued automatically to prevent a formal chargeback.
</Note>

<Note>
  [Ethoca alerts](/features/transactions/disputes#ethoca-alerts) and [deflections](/features/transactions/disputes#deflections) never create a dispute, so they emit no `dispute.*` events. An Ethoca alert refund fires the standard `refund.succeeded` event, and any linked subscription cancellation fires the usual subscription event. A deflection fires no event.
</Note>

## Handling Dispute Events

When `dispute.opened` fires, the disputed amount is held immediately. Use the event to update your records and, if you intend to contest it, gather evidence in the dashboard.

```javascript Handling dispute events expandable theme={null}
app.post('/webhooks/dodo', async (req, res) => {
  // Verify the signature first. See /developer-resources/webhooks#verifying-signatures.
  // With express.raw(), req.body is a Buffer, so parse it after verification.
  const event = JSON.parse(req.body);

  switch (event.type) {
    case 'dispute.opened': {
      const dispute = event.data;
      // Record the dispute and consider revoking access while it is open
      await recordDispute(dispute.dispute_id, dispute.payment_id, dispute.amount);
      // Gather and submit evidence from the Dodo Payments dashboard (within 10 days)
      break;
    }
    case 'dispute.won': {
      // Funds retained — restore normal state in your records
      await markDisputeResolved(event.data.dispute_id, 'won');
      break;
    }
    case 'dispute.lost': {
      // Funds returned to the cardholder — reconcile and keep access revoked
      await markDisputeResolved(event.data.dispute_id, 'lost');
      break;
    }
  }

  res.json({ received: true });
});
```

<Tip>
  Always verify the webhook signature before processing — see the [Webhooks guide](/developer-resources/webhooks) for setup. The handler above omits verification for brevity.
</Tip>

<Warning>
  You have **10 days** to respond to a dispute after it is created. See [Dispute Response Best Practices](/features/transactions/disputes#dispute-response-best-practices) for the evidence to gather and how to format it.
</Warning>

## Dispute Status and Stage

The dispute object reports its progress through two fields:

| Field | Values |
| - | - |
| `dispute_status` | `dispute_opened`, `dispute_expired`, `dispute_accepted`, `dispute_cancelled`, `dispute_challenged`, `dispute_won`, `dispute_lost` |
| `dispute_stage` | `pre_dispute`, `dispute`, `pre_arbitration` |

## Related

<CardGroup cols={2}>
  <Card title="Managing Disputes" icon="gavel" href="/features/transactions/disputes">
    How to respond to disputes, submit evidence, and how RDR protects your dispute rate.
  </Card>

  <Card title="Handle Payment Failures" icon="screwdriver-wrench" href="/developer-resources/handle-payment-failures">
    Detect and recover failed payments before they become disputes.
  </Card>
</CardGroup>

## Webhook Payload Schema


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.