Dispute lifecycle
A dispute is opened when a cardholder or issuing bank challenges a paid card transaction. Recurrente links the dispute to the original invoice, debits the disputed amount from your Recurrente balance, asks for supporting documentation, and tracks the bank’s resolution.
Dispute webhooks are not unified intent.* events. They use their own event names: dispute.create and dispute.update.
Typical lifecycle
- The issuer reports the dispute. Recurrente receives the alert from the issuer or creates it from an issuer email when the transaction can be matched.
- The dispute is opened. The status is usually
needs_response. Recurrente debits the disputed amount from your balance, emails the account owner, and sends adispute.createwebhook. - You send documentation. Recurrente reviews the supporting documents and may move the dispute to
under_review. This sends adispute.updatewebhook. - The issuer reviews the case. The dispute stays in progress while the issuer decides. If no documentation arrives in time, Recurrente can mark the dispute
closed. - The dispute is resolved. Recurrente updates the status to
won,lost, or another final operational status. Awondispute credits the disputed amount back to your balance. Alostorcloseddispute leaves the original debit in place.
Not every dispute follows every step. For example, a dispute can be closed for no response, resolved directly by the issuer, or recorded as charge_refunded when the charge was refunded during handling.
Statuses
Webhook events
dispute.update can be sent for saved changes that are not status changes, so always read the status field instead of assuming every update means the lifecycle advanced.
Payload
Reasons
The reason field can be one of:
bank_cannot_process, check_returned, credit_not_processed, customer_initiated, debit_not_authorized, duplicate, fraudulent, general, incorrect_account_details, incorrect_amount, insufficient_funds, product_not_received, product_unacceptable, subscription_canceled, unrecognized.
Connected accounts
If the dispute belongs to a connected child account and your platform account has webhooks enabled, your platform can receive the same dispute events with these extra fields:
connected: trueindicates the event was generated by a connected account.account_idis the account that generated the event.
Handler pattern
Use the Svix svix-id header for delivery idempotency, and treat event.id as the dispute object’s ID.

