Skip to main content
Disputes (chargebacks) occur when a cardholder challenges a charge with their bank. Flex automatically syncs disputes the moment they are filed and exposes a full API for listing, retrieving, submitting evidence, and closing disputes.

Table of Contents


Overview

When a dispute is opened, Flex:
  1. Receives the charge.dispute.created event.
  2. Creates a Dispute record linked to your payment_intent_id and charge_id.
  3. Forwards a charge.dispute.created event to your registered webhook endpoint.
You have until evidence_details.due_by to respond. Submitting evidence with submit: true sends it immediately and increments submission_count. You may re-submit with updated evidence before the deadline. Alternatively, POST /v1/disputes/:id/close concedes the dispute immediately.

Authentication

All requests require a bearer token (API key).
Your API key is scoped to your partner account. Disputes for other partners are never visible regardless of the ID used — they return 404.

The Dispute Object

Field Reference

evidence_details Fields

balance_transactions Fields (per item)

payment_method_details.card Fields


Dispute Status Lifecycle

Attempting to submit evidence or close a dispute in a non-actionable status returns 422.

Dispute Reason Codes


Endpoints

List Disputes

Returns disputes for your account in reverse chronological order (newest first). Query Parameters
Note: balance_transactions and payment_method_details are not populated in list responses. Use GET /v1/disputes/:id to get the full dispute.
Example — list all disputes
Response
Example — filter by payment intent
Example — paginate forward

Get Dispute

Retrieves a single dispute by its Flex ID. This is the only endpoint that populates balance_transactions and payment_method_details. Path Parameters Example
Response
Errors

Update Evidence

Saves evidence for a dispute. Set submit: true to submit evidence immediately. Set submit: false (or omit it) to save a draft without submitting. The dispute must be in needs_response or warning_needs_response status. Path Parameters Request Body

Evidence Fields

All fields are optional. Include only what is relevant to your dispute reason. Text fields File fields — use a Flex File ID (ffile_... from POST /v1/files) Files must be uploaded with purpose dispute_evidence before use. See Uploading Evidence Files. Example — save a draft (no submission)
Example — submit evidence
Response Returns the updated Dispute object with refreshed evidence_details.submission_count.
Errors

Close Dispute

Accepts the dispute and concedes the funds. Use this when you do not intend to contest the dispute. This action is irreversible. The dispute must be in needs_response or warning_needs_response status. Path Parameters Request Body No body required. Example
Response Returns the updated Dispute object. status will be lost.
Errors

Uploading Evidence Files

Before referencing a file in an evidence submission, upload it using the Files API with purpose dispute_evidence.
Response
Use the returned file_id (ffile_...) in evidence file fields. Attempting to use a file with a different purpose (e.g. identity_document) will return a 422 with a clear error message indicating which field is invalid and what purpose was found vs expected.

Webhook Events

Configure a webhook endpoint in your Flex dashboard to receive dispute lifecycle events.

charge.dispute.created

Fired when a dispute is opened against one of your charges.
Recommended action: Alert your team and begin gathering evidence.

charge.dispute.updated

Fired when a dispute’s status, evidence, or deadline changes (including when you submit evidence via the API). Recommended action: Refresh your local dispute record.

charge.dispute.closed

Fired when a dispute is resolved — either won, lost, or warning_closed. Recommended action: Update your records; if lost, the funds have been debited.

charge.dispute.funds_withdrawn

Fired when funds are withdrawn from your balance to cover the disputed amount. A balance transaction is added to the dispute.

charge.dispute.funds_reinstated

Fired when a previously disputed amount is returned to your balance (dispute won). All webhook payloads include a flex-signature header for verification. See the Webhooks documentation for signature verification details.

Error Reference

All errors follow a standard format:
Or for field-level validation errors:

End-to-End Testing Guide

Prerequisites

  • Flex API key (test mode)
  • Test card numbers (see below)
  • A registered webhook endpoint to receive events

Step 1 — Trigger a dispute

Create a checkout session and complete payment using an auto-dispute test card: Use 4111 1111 1111 1111 as a valid non-disputing card for comparison. After completing payment:
  • The charge is automatically disputed (test mode only)
  • Flex receives the charge.dispute.created event
  • Your webhook endpoint receives the charge.dispute.created event

Step 2 — Inspect the dispute

Find the new dispute. Then fetch the full object:
Verify:
  • status: "needs_response"
  • evidence_details.due_by is a future timestamp
  • evidence_details.submission_count: 0
  • balance_transactions contains one debit entry

Step 3 — Submit evidence

Verify:
  • Response evidence_details.submission_count: 1
  • Response status changes to "under_review"

Step 4 — Close a second dispute

Create another charge with the auto-dispute card. Then:
Verify:
  • Response status: "lost"

Step 5 — Verify multi-tenant isolation

Using a different partner’s API key, attempt to access the dispute IDs from Steps 2–4. All should return 404.

Step 6 — Test error cases

Invalid status transition: Try POST /v1/disputes/fdsp_.../close on a dispute that is already lost or under_review. Expected: 422 with message "Cannot close dispute in '...' status". File with wrong purpose: Upload a file with purpose=identity_document, then reference it in an evidence field. Expected: 422 with message indicating which field has the wrong file purpose. Non-existent dispute:
Expected: 404.