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

# Create, Submit, and Manage a Dispute

> Create, submit, and manage the disputes lifecycle in a private sandbox.

This guide navigates a simple dispute lifecycle in sandbox, while simulating the network state transitions to help you:

* Create a dispute by submitting an API request or by using the Marqeta Dashboard, upload supporting documents, and prepare it for chargeback submission to the card network.
* Submit a dispute for chargeback and manually transition card network states as they occur in a production environment.

You will also learn how Marqeta and network dispute states relate to each other as a dispute moves through its lifecycle.

<Note>This guide uses a minimal configuration Mastercard cleared transaction as an example.</Note>

# Prerequisites

Before you initiate the dispute process, ensure that you have the following in place:

* A cleared transaction
* A webhook handler

<Note>For more information about setting up a webhook handler, see [Set Up a Webhook Handler](/developer-guides/disputes-sandbox/disputes-webhook-handler).</Note>

# Dispute state flow

A Marqeta state is assigned when a dispute is first created, and a card network state is assigned when the dispute is submitted to the card network.
The states transition as a dispute progresses towards resolution.
The sandbox does not connect to the card networks.
However, in production, you will use the `DISPUTE` value in the `type` field for integrated network disputes, and `LEGACY_DISPUTE` for non-integrated cases.

In production, Marqeta handles all network-side state transitions once a chargeback is submitted.
This guide include steps to simulate the network-side state transitions to illustrate the transitions that occur automatically.

To simulate the network-side transitions, use the `LEGACY_DISPUTE` value in the `type` field of the request payload.
This allows you to manually transition the dispute through the card network states by simulating the process of submitting the disputes to card network to better understand the process.
See [Submit a Dispute](/developer-guides/disputes-sandbox/disputes-sandbox-submit-manage#submitting-a-dispute).

The following table outlines how Marqeta and network states relate to each other.

| Marqeta State                | Network State      |
| ---------------------------- | ------------------ |
| OPEN                         | -                  |
| OPEN\_WITH\_ACTION\_REQUIRED | -                  |
| READY                        | -                  |
| CHARGEBACK\_INITIATED        | `initiated`        |
| CHARGEBACK\_INITIATED        | `representment`    |
| CHARGEBACK\_INITIATED        | `prearbitration`   |
| CHARGEBACK\_INITIATED        | `arbitration`      |
| CLOSED                       | `case_won`         |
| CLOSED                       | `case_lost`        |
| CLOSED                       | `network_rejected` |

The following diagram illustrates the states a dispute transitions through during its lifecycle.

<Frame>
  <div className="not-prose" style={{overflowX: 'auto', minWidth: '600px'}}>
    ```mermaid theme={null}
    %%{init: {
    'state': { 'useMaxWidth': true },
    'themeVariables': {
        'nodeSpacing': 20,
        'rankSpacing': 20,
        'padding': 10
    }
    } }%%
    stateDiagram-v2
    direction TB

    state "OPEN" as OPEN
    state "OPEN_WITH_ACTION_REQUIRED" as ACTION
    state "READY" as READY

    state "CHARGEBACK_INITIATED" as CI {
        direction TB
        Initiated
        Representment
        Prearbitration
        Arbitration
    }

    state "CLOSED" as CLOSED {
        direction TB
        CW: Case Won
        CL: Case Lost
        NR: Network Rejected
    }

    %% Logic Flow
    [*] --> OPEN
    OPEN --> ACTION
    ACTION --> READY
    READY --> CI
    CI --> CLOSED
    CLOSED --> [*]
    ```
  </div>
</Frame>

# Create a dispute

To create a dispute, you must open a case, upload supporting documents, and transition it to the `READY` state.

For more information on creating a dispute, see [Creating a Dispute](/developer-guides/disputes-create).

## Opening the dispute case

To open a dispute case, send a `POST /cases` request with the following fields:

* `original_transaction_token`: The clearing transaction token.
* `dispute_amount`: The amount in dispute.
* `dispute_reason`: A reason code (for example, `NOT_AUTHORIZED_CARD_ABSENT` for fraud, or `CARDHOLDER_DISPUTE` for goods not received).

<Note>
  - The request payload for dispute creation differs depending on the network and dispute reason.
    The following sample request for a Mastercard cleared transaction is an example of a minimal configuration.
  - The `cardholder_contact_date` parameter is required for `REG_E` disputes, but it is not required for this example with minimal configuration.
  - The `dispute_reason` enum is different from `reason_code` on a transition which is a network-side identifier.
</Note>

### Sample request body

<Accordion title="Sample request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl --request POST \
        --url https://your-subdomain.marqeta.com/v3/cases \
        --header 'Content-Type: application/json' \
        --data '
        {
            "type": "LEGACY_DISPUTE",
            "dispute_details": {
                "original_transaction_token": "019ca0e2-a9e3-7f30-b120-957e44eb3408",
                "dispute_amount": 10,
                "dispute_reason": "NOT_AUTHORIZED_CARD_ABSENT",
                "cardholder_contact_date": "2023-07-18T22:24:46.251Z"
            },
            "memo": "A test legacy dispute case"
        }
        '
    ```

    ```javascript JavaScript theme={null}
        // transactionToken is the token of the cleared transaction
        const createDispute = async (transactionToken) => {
            const url = 'https://your-subdomain.marqeta.com/v3/cases';
            const payload = {
                type: "LEGACY_DISPUTE",
                dispute_details: {
                    original_transaction_token: transactionToken,
                    dispute_amount: 10,
                    dispute_reason: "NOT_AUTHORIZED_CARD_ABSENT",
                    cardholder_contact_date: "2023-07-18T22:24:46.251Z",
                },
                memo: "A test legacy dispute case"
            };

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING'
                },
                body: JSON.stringify(payload)
            });

            const data = await response.json();
            console.log('Dispute Case Created:', data);
        };
    ```

    ```python Python theme={null}
        import requests

        url = "https://api.marqeta.com/v3/cases"
        headers = {
            "Content-Type": "application/json",
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING"
        }

        payload = {
            "type": "LEGACY_DISPUTE",
            "dispute_details": {
                "original_transaction_token": "019ca0e2-a9e3-7f30-b120-957e44eb3408",
                "dispute_amount": 10,
                "dispute_reason": "NOT_AUTHORIZED_CARD_ABSENT",
                "cardholder_contact_date": "2023-07-18T22:24:46.251Z",
            },
            "memo": "A test legacy dispute case"
        }

        response = requests.post(url, headers=headers, json=payload)
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;

        public class CreateDispute {
            public static void main(String[] args) throws Exception {
                HttpClient client = HttpClient.newHttpClient();

                String jsonBody = """
                    {
                        "type": "LEGACY_DISPUTE",
                        "dispute_details": {
                            "original_transaction_token": "019ca0e2-a9e3-7f30-b120-957e44eb3408",
                            "dispute_amount": 10,
                            "dispute_reason": "NOT_AUTHORIZED_CARD_ABSENT",
                            "cardholder_contact_date": "2023-07-18T22:24:46.251Z"
                        },
                        "memo": "A test legacy dispute case"
                    }
                    """;

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://api.marqeta.com/v3/cases"))
                    .header("Content-Type", "application/json")
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println("Status: " + response.statusCode());
                System.out.println("Body: " + response.body());
            }
        }
    ```
  </CodeGroup>
</Accordion>

### Sample response body

<Accordion title="Sample response">
  <CodeGroup>
    ```json JSON theme={null}
    {
        "original_transaction_token": "019ca0e2-a9e3-7f30-b120-957e44eb3408",
        "original_transaction_type": "authorization.clearing",
        "dispute_amount": 10.00,
        "currency_code": "USD",
        "dispute_reason": "NOT_AUTHORIZED_CARD_ABSENT",
        "network": "MASTERCARD",
        "network_case_number": "",
        "card_token": "e25551b1-f47a-4310-a563-1a02cd09e0f7",
        "provisional_credit_granted": false,
        "acquirer_fee": 0.0000,
        "associated_transaction_selection_required": false
    }
    ```
  </CodeGroup>
</Accordion>

Upon creation, the dispute case is assigned the `OPEN` or `OPEN_WITH_ACTION_REQUIRED` Marqeta state.

## Uploading supporting documents

To upload supporting documents to defend the dispute claim, use `POST /cases/{token}/contents`.

You must upload supporting documents while the case is still in `OPEN`, `OPEN_WITH_ACTION_REQUIRED`, or `READY` states.
Once a dispute is submitted to the card network, you can no longer attach documents.

For this example in particular, Mastercard requires supporting documents for all dispute claims.

### Sample request body

You can upload supporting document file to the disputes API as a binary in an `application/json` in the `Content-Type` field, or as part of a `multipart/form-data`.
Examples for both modes follow below.

<Accordion title="Sample binary in body request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/contents" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Content-Type: application/json" \
            -H "Cache-Control: no-cache" \
            -d '{
                "document_category": "RECEIPT",
                "document_name": "receipt_2.pdf",
                "document_data": "<file_binary_code>"
            }'
    ```

    ```javascript JavaScript theme={null}
        const fs = require('fs');

        async function uploadDisputeEvidence(caseToken, filePath) {
            // Read file and convert to Base64
            const fileBuffer = fs.readFileSync(filePath);
            const base64Data = fileBuffer.toString('base64');

            const payload = {
                document_category: "RECEIPT",
                document_name: "receipt_2.pdf",
                document_data: base64Data
            };

            const response = await fetch(`https://your-subdomain.marqeta.com/v3/cases/${caseToken}/contents`, {
                method: 'POST',
                headers: {
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(payload)
            });

            const result = await response.json();
            console.log('Upload Status:', result);
        }
    ```

    ```python Python theme={null}
        import requests
        import base64

        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/contents"

        # Read and encode the file
        with open("receipt_2.pdf", "rb") as pdf_file:
            encoded_string = base64.b64encode(pdf_file.read()).decode('utf-8')

        payload = {
            "document_category": "RECEIPT",
            "document_name": "receipt_2.pdf",
            "document_data": encoded_string
        }

        headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Content-Type": "application/json"
        }

        response = requests.post(url, headers=headers, json=payload)
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;
        import java.nio.file.Files;
        import java.nio.file.Paths;
        import java.util.Base64;

        public class UploadEvidence {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                byte[] fileContent = Files.readAllBytes(Paths.get("receipt_2.pdf"));
                String encodedString = Base64.getEncoder().encodeToString(fileContent);

                // Simple JSON manual build (Use Jackson/Gson for production)
                String jsonBody = String.format("""
                    {
                        "document_category": "RECEIPT",
                        "document_name": "receipt_2.pdf",
                        "document_data": "%s"
                    }
                    """, encodedString);

                HttpClient client = HttpClient.newHttpClient();
                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/contents"))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println("Status: " + response.statusCode());
            }
        }
    ```
  </CodeGroup>
</Accordion>

<Accordion title="Sample multipart form request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/contents" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Cache-Control: no-cache" \
            -F 'body={
            "document_category": "AUTHORIZATION_RECORD",
            "document_name": "authorization_record.pdf"
            };type=application/json' \
            -F "file=@/path/to/your-file ;type=application/pdf"
    ```

    ```javascript JavaScript theme={null}
        const fs = require('fs');

        async function uploadMultipartEvidence(caseToken, filePath) {
            const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/contents`;

            const formData = new FormData();

            // Add the metadata part
            const metadata = JSON.stringify({
                document_category: "AUTHORIZATION_RECORD",
                document_name: "authorization_record.pdf"
            });
            formData.append('body', new Blob([metadata], { type: 'application/json' }));

    // Add the file part
            const fileStream = fs.createReadStream(filePath);
            formData.append('file', fileStream);

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                    'Cache-Control': 'no-cache'
                },
                body: formData
            });

            const data = await response.json();
            console.log(data);
        }
    ```

    ```python Python theme={null}
        import requests

        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/contents"

        headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Cache-Control": "no-cache"
        }

        # The 'files' dictionary mimics the -F flags
        files = {
            'body': (None, '{"document_category": "AUTHORIZATION_RECORD", "document_name": "authorization_record.pdf"}', 'application/json'),
            'file': ('authorization_record.pdf', open('/path/to/your-file', 'rb'), 'application/pdf')
        }

        response = requests.post(url, headers=headers, files=files)
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;
        import java.nio.file.Path;
        import java.util.UUID;

        public class MultipartUpload {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                HttpClient client = HttpClient.newHttpClient();

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/contents"))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    // Content-Type will be automatically set to multipart/form-data with a boundary
                    .POST(HttpRequest.BodyPublishers.ofString("... multipart data ..."))
                    .build();
            }
        }
    ```
  </CodeGroup>
</Accordion>

### Sample response body

<Accordion title="Sample response">
  <CodeGroup>
    ```json JSON theme={null}
    {
        "created_time": "2026-03-09T14:03:52Z",
        "last_modified_time": "2026-03-09T14:03:52Z",
        "token": "6fab0fc2-fef6-4949-be2b-d0d8175fba82",
        "document_category": "AUTHORIZATION_RECORD",
        "document_name": "receipt.pdf",
        "case_token": "<case_token>",
        "document_content_type": "application/pdf",
        "network_process_type": "SUBMITTED",
        "network_process_time": "2026-03-09T14:03:53Z"
    }
    ```
  </CodeGroup>
</Accordion>

The Marqeta state remains as `OPEN` or `OPEN_WITH_ACTION_REQUIRED`.

### Verifying the document upload

You can verify that your document was uploaded correctly by sending a request to the `GET /cases/{token}/contents` endpoint.

The response body includes only the list of uploaded documents.
However, if you want to download these files, include `download_link=true` as a query parameter to receive the link in the response body.

#### Sample request body

<CodeGroup>
  ```bash Curl theme={null}
  curl -X GET "https://your-subdomain.marqeta.com/v3/cases/<case_token>/contents/<document_token>?download_link=true" \
      -H "X-Marqeta-Program-Short-Code: your-program-code" \
      -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
      -H "Content-Type: application/json" \
      -H "Cache-Control: no-cache"
  ```

  ```javascript JavaScript theme={null}
  const getDocumentDownloadLink = async (caseToken, documentToken) => {
  const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/contents/${documentToken}?download_link=true`;

  const response = await fetch(url, {
      method: 'GET',
      headers: {
      'X-Marqeta-Program-Short-Code': 'your-program-code',
      'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
      'Content-Type': 'application/json',
      'Cache-Control': 'no-cache'
      }
  });
  const data = await response.json();
  console.log('Download Link:', data.download_link);
  };
  ```

  ```python Python theme={null}
      import requests
  case_token = "<case_token>"
      document_token = "<document_token>"
      url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/contents/{document_token}"
      params = {"download_link": "true"}
  headers = {
          "X-Marqeta-Program-Short-Code": "your-program-code",
          "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
          "Content-Type": "application/json",
          "Cache-Control": "no-cache"
      }
      response = requests.get(url, headers=headers, params=params)

      if response.status_code == 200:
          data = response.json()
          print(f"Temporary Download URL: {data.get('download_link')}")
      else:
          print(f"Error: {response.status_code}")
  ```

  ```java Java theme={null}
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;

  public class GetDocumentLink {
      public static void main(String[] args) throws Exception {
          String caseToken = "<case_token>";
          String documentToken = "<document_token>";

          String url = String.format(
              "https://your-subdomain.marqeta.com/v3/cases/%s/contents/%s?download_link=true",
              caseToken, documentToken
          );

          HttpClient client = HttpClient.newHttpClient();
          HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create(url))
              .header("X-Marqeta-Program-Short-Code", "your-program-code")
              .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
              .header("Content-Type", "application/json")
              .header("Cache-Control", "no-cache")
              .GET()
              .build();

          HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

          System.out.println("Response JSON: " + response.body());
      }
  }
  ```
</CodeGroup>

## Transitioning a dispute case

After you provide all the required case information and upload supporting documents, transition the case to the `READY` state by performing the `REVIEW` action.
Use `POST /cases/{token}/transitions` and set the `action` field value to `REVIEW`.

### Sample request body

<Accordion title="Sample request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/transitions" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Content-Type: application/json" \
            -d '{
                "action": "REVIEW",
                "reason_code": "05",
                "created_by": "Your Name"
            }'
    ```

    ```javascript JavaScript theme={null}
        const transitionDisputeCase = async (caseToken) => {
            const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/transitions`;

            const payload = {
                action: "REVIEW",
                reason_code: "05",
                created_by: "Your Name"
            };

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(payload)
            });

            const data = await response.json();
            console.log('Transition Result:', data);
        };
    ```

    ```python Python theme={null}
        import requests

        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/transitions"

        headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Content-Type": "application/json"
        }

    payload = {
            "action": "REVIEW",
            "reason_code": "05",
            "created_by": "Your Name"
        }

        response = requests.post(url, headers=headers, json=payload)
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;

        public class TransitionCase {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                HttpClient client = HttpClient.newHttpClient();

                String jsonBody = """
                    {
                        "action": "REVIEW",
                        "reason_code": "05",
                        "created_by": "Your Name"
                    }
                    """;

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/transitions"))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println("Status: " + response.statusCode());
                System.out.println("Body: " + response.body());
            }
        }
    ```
  </CodeGroup>
</Accordion>

### Sample response body

<Accordion title="Sample response">
  <CodeGroup>
    ```json JSON theme={null}
    {
        "case_token": "<case_token>",
        "token": "b70e779c-4c3a-48bf-861e-10486da57db8",
        "reason_code": "05",
        "reason_description": "Under Review",
        "created_by": "Your Name",
        "from_state": "OPEN",
        "state": "READY",
        "action": "REVIEW",
        "created_date": "2026-03-09T19:04:30Z"
    }
    ```
  </CodeGroup>
</Accordion>

The case transitions to `READY`, and it is now eligible for submission to the card network.

## Withdrawing a dispute voluntarily

You can withdraw a dispute while it is in the `OPEN`, `OPEN_WITH_ACTION_REQUIRED`, or `READY` state by sending a request to the `POST /cases/<case_token>/transitions` endpoint.
This moves the case to a `CLOSED` state.

<Warning>You will not be allowed to withdraw disputes once they have been submitted to the card network and assigned the `CHARGEBACK_INITIATED` state.</Warning>

### Sample request body

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/transitions" \
  -H "X-Marqeta-Program-Short-Code: your-program-code" \
  -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
  -H "Content-Type: application/json" \
  -d '{
      "action": "WITHDRAW_AND_CLOSE",
      "reason_code": "40",
      "created_by": "Your Name"
  }'
  ```

  ```javascript JavaScript theme={null}
  const withdrawDispute = async (caseToken) => {
      const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/transitions`;

      const payload = {
          action: "WITHDRAW_AND_CLOSE",
          reason_code: "40",
          created_by: "Your Name"
      };

      const response = await fetch(url, {
          method: 'POST',
          headers: {
          'X-Marqeta-Program-Short-Code': 'your-program-code',
          'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
          'Content-Type': 'application/json'
          },
          body: JSON.stringify(payload)
      });

      const data = await response.json();
      console.log('Case Status:', data.state);
  };
  ```

  ```python Python theme={null}
  import requests

  case_token = "<case_token>"
  url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/transitions"

  headers = {
      "X-Marqeta-Program-Short-Code": "your-program-code",
      "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
      "Content-Type": "application/json"
  }
  payload = {
      "action": "WITHDRAW_AND_CLOSE",
      "reason_code": "40",
      "created_by": "Your Name"
  }

  response = requests.post(url, headers=headers, json=payload)
  print(f"Status Code: {response.status_code}")
  print(response.json())
  ```

  ```java Java theme={null}
      import java.net.URI;
      import java.net.http.HttpClient;
      import java.net.http.HttpRequest;
      import java.net.http.HttpResponse;
  public class WithdrawDispute {
          public static void main(String[] args) throws Exception {
              String caseToken = "<case_token>";
              HttpClient client = HttpClient.newHttpClient();
  String jsonBody = """
                  {
                      "action": "WITHDRAW_AND_CLOSE",
                      "reason_code": "40",
                      "created_by": "Your Name"
                  }
                  """;
  HttpRequest request = HttpRequest.newBuilder()
                  .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/transitions"))
                  .header("X-Marqeta-Program-Short-Code", "your-program-code")
                  .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                  .header("Content-Type", "application/json")
                  .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                  .build();
              HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
              System.out.println("Dispute Final Status: " + response.body());
          }
      }
  ```
</CodeGroup>

# Submit a dispute

Once the dispute enters the `READY` state, you can submit it to the card network for processing.
Submitting the dispute formally initiates the chargeback with the card network.

<Warning>
  In production, Marqeta handles all network-side state transitions once a chargeback is submitted.
  To simulate the card transitions once the dispute is submitted, you will call the `/disputetransitions` endpoints.
  This endpoint is not used in the production environment.
  This guide includes the following steps only to illustrate the transitions that occur automatically.
</Warning>

## Submitting a dispute to the card network

After reviewing the dispute case in a `READY` state, Marqeta submits it to the card network and the case transitions to the `CHARGEBACK_INITIATED` network state.

You can simulate submitting a dispute using a `POST  /cases/<case_token>/transitions` request.
The chargeback can be initiated for a **provisional credit** or **no credit** flow.

The example below demonstrates a no-credit chargeback flow by sending `CHARGEBACK_NO_CREDIT` in the `action` field.

### Sample request body

<Accordion title="Sample request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/transitions" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Content-Type: application/json" \
            -d '{
                "action": "CHARGEBACK_NO_CREDIT",
                "reason_code": "29",
                "created_by": "Your Name"
            }'
    ```

    ```javascript JavaScript theme={null}
        const initiateChargebackNoCredit = async (caseToken) => {
            const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/transitions`;

            const payload = {
                action: "CHARGEBACK_NO_CREDIT",
                reason_code: "29",
                created_by: "Your Name"
            };

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(payload)
            });
    const data = await response.json();
            console.log('Chargeback Initiated:', data);
        };
    ```

    ```python Python theme={null}
        import requests

        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/transitions"

        headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Content-Type": "application/json"
        }

        payload = {
            "action": "CHARGEBACK_NO_CREDIT",
            "reason_code": "29",
            "created_by": "Your Name"
        }

        response = requests.post(url, headers=headers, json=payload)

        print(f"Status: {response.status_code}")
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;
    public class ChargebackNoCredit {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                HttpClient client = HttpClient.newHttpClient();
                String jsonBody = """
                    {
                        "action": "CHARGEBACK_NO_CREDIT",
                        "reason_code": "29",
                        "created_by": "Your Name"
                    }
                    """;

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/transitions"))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println("Result: " + response.body());
            }
        }
    ```
  </CodeGroup>
</Accordion>

### Sample response body

<Accordion title="Sample response">
  <CodeGroup>
    ```json JSON theme={null}
    {
        "case_token": "<case_token>",
        "token": "3518f614-1ea4-4913-9002-639e21ce0f93",
        "reason_code": "29",
        "reason_description": "Chargeback with no Credit",
        "created_by": "Your Name",
        "from_state": "READY",
        "state": "CHARGEBACK_INITIATED",
        "action": "CHARGEBACK_NO_CREDIT",
        "created_date": "2026-03-09T19:26:35Z"
    }
    ```
  </CodeGroup>
</Accordion>

Upon submission, the dispute case transitions to the `CHARGEBACK_INITIATED` Marqeta state and the `initiated` network state.

<Note>
  If the network rejects the submission, the dispute enters the `network.rejected` network state and the Marqeta state transitions to `CLOSED`.
  You can review the case and resubmit it with corrected details.
</Note>

When a dispute is submitted and enters a chargeback state, the Marqeta platform triggers specific webhooks.
The exact webhooks depend on whether the the action involves a **provisional credit** or **no credit** flow.
The `reason_code` used must match the action being performed.

Test your webhook handlers based on the selection you make from the following options.

If you select the `CHARGEBACK_CREDIT` action for provisional credit, the following webhook events are sent:

* `transactions.authorization.clearing.chargeback`
* `chargebacktransitions.initiated`
* `transactions.authorization.clearing.chargeback.provisional.credit.`

If you select the `CHARGEBACK_NO_CREDIT` action for no credit, the following webhook events are sent:

* `transactions.authorization.clearing.chargeback`
* `chargebacktransitions.initiated.`

<Note>
  There may be a delay between the time an action is taken and when the webhook is sent.
  This is true for all webhooks.
</Note>

### Dispute identifiers

Marqeta and the card network identify a dispute using different tokens, as described below:

* **Case creation**: When a case is created, you have the reason code, and your primary identifier is the transaction token. This is the identifier Marqeta uses to identify the dispute.

* **Chargeback initiation**: When a chargeback is initiated on the network, you receive both the transaction token and the chargeback token. The card network uses the chargeback token to identify the dispute.

### Recommended actions

To effectively track and manage chargebacks, Marqeta recommends that you:

* **Maintain a mapping**: Store the relationship between the reason code and the transaction token within your system.
* **Link the identifiers**: Once a chargeback is initiated, use the chargeback token to tie the network event back to the original transaction token.
* **Associate the reason code**: Ensure the reason code is associated with the chargeback token for future tracking.

<Note>
  - The chargeback token will be the identifier that is sent throughout the lifecycle of disputes in all subsequent webhooks.
  - There can be multiple disputes associated with a transaction. Hence, the chargeback token is the right identifier to map to a reason code.
</Note>

## Providing provisional credit

Granting provisional credit is required if your program is subject to specific regulations.
You are responsible for providing this credit if your program manages the ledger via Just-in-Time (JIT) funding.

For this example, which uses the `CHARGEBACK_NO_CREDIT` action, the system does not require provisional credit.
However, this section provides an example of requesting provisional credit below for reference.

### Sample request body

<CodeGroup>
  ```bash Send a POST request theme={null}
  curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/actions" \
  -H "X-Marqeta-Program-Short-Code: your-program-code" \
  -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
  -H "Content-Type: application/json" \
  -d '{
      "action_type": "GRANT_PROVISIONAL_CREDIT",
      "created_by": "Your Name"
  }'
  ```

  ```javascript JavaScript theme={null}
  const grantProvisionalCredit = async (caseToken) => {
      const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/actions`;

      const payload = {
          action_type: "GRANT_PROVISIONAL_CREDIT",
          created_by: "Your Name"
      };

      const response = await fetch(url, {
          method: 'POST',
          headers: {
          'X-Marqeta-Program-Short-Code': 'your-program-code',
          'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
          'Content-Type': 'application/json'
          },
          body: JSON.stringify(payload)
      });

      const data = await response.json();
      console.log('Provisional Credit Status:', data);
  };
  ```

  ```python Python theme={null}
      import requests
  case_token = "<case_token>"
      url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/actions"

      headers = {
          "X-Marqeta-Program-Short-Code": "your-program-code",
          "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
          "Content-Type": "application/json"
      }
  payload = {
          "action_type": "GRANT_PROVISIONAL_CREDIT",
          "created_by": "Your Name"
      }
  response = requests.post(url, headers=headers, json=payload)
  print(f"Status: {response.status_code}")
      print(response.json())
  ```

  ```java Java theme={null}
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpRequest.BodyPublishers;
  import java.net.http.HttpResponse;
  public class GrantCredit {
      public static void main(String[] args) throws Exception {
          String caseToken = "<case_token>";
          HttpClient client = HttpClient.newHttpClient();

          String jsonBody = """
              {
                  "action_type": "GRANT_PROVISIONAL_CREDIT",
                  "created_by": "Your Name"
              }
              """;
  HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/actions"))
              .header("X-Marqeta-Program-Short-Code", "your-program-code")
              .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
              .header("Content-Type", "application/json")
              .POST(BodyPublishers.ofString(jsonBody))
              .build();
          HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
          System.out.println("Response: " + response.body());
      }
  }
  ```
</CodeGroup>

## Simulating Merchant representment

In some cases, the acquiring bank may forward the dispute claim to the merchant.
A merchant may choose to accept the dispute or challenge it.
Marqeta might request additional documentation from the cardholder to resubmit the dispute.

After the representment is received from the merchant, card network reviews the information to determine if the cardholder or merchant wins the dispute.

In the sandbox, you can simulate merchant representment (the merchant's response to the dispute) using the `POST /cases/<case_token>/disputetransitions` endpoint.
Define the `amount` field within the `network_details.representment_details` object in the request body to simulate the representment.

### Sample request body

<Accordion title="Sample request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/disputetransitions" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Content-Type: application/json" \
            -d '{
                "action": "REPRESENTMENT_RECEIVED",
                "created_by": "Your Name",
                "network_details": {
                    "representment_details": {
                        "amount": 10
                    }
                }
            }'
    ```

    ```javascript JavaScript theme={null}
        const moveToRepresentment = async (caseToken) => {
            const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/disputetransitions`;

            const payload = {
                action: "REPRESENTMENT_RECEIVED",
                created_by: "Your Name",
                network_details: {
                    representment_details: {
                        amount: 10
                    }
                }
            };

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(payload)
            });

            const data = await response.json();
            console.log('Representment Logged:', data);
        };
    ```

    ```python Python theme={null}
        import requests
        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/disputetransitions"

        headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Content-Type": "application/json"
        }

        payload = {
            "action": "REPRESENTMENT_RECEIVED",
            "created_by": "Your Name",
            "network_details": {
                "representment_details": {
                    "amount": 10
                }
            }
        }

        response = requests.post(url, headers=headers, json=payload)
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;

        public class MoveToRepresentment {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                HttpClient client = HttpClient.newHttpClient();

                String jsonBody = """
                    {
                        "action": "REPRESENTMENT_RECEIVED",
                        "created_by": "Your Name",
                        "network_details": {
                            "representment_details": {
                                "amount": 10
                            }
                        }
                    }
                    """;

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/disputetransitions"))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();
                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println("Status Code: " + response.statusCode());
                System.out.println("Response: " + response.body());
            }
        }
    ```
  </CodeGroup>
</Accordion>

### Sample response body

<Accordion title="Sample response">
  <CodeGroup>
    ```json JSON theme={null}
    {
        "token": "50802d43-ffea-4280-8d01-41d8908a38a6",
        "created_time": "2026-03-10T13:59:07Z",
        "last_modified_time": "2026-03-10T13:59:07Z",
        "case_token": "<case_token>",
        "action": "REPRESENTMENT_RECEIVED",
        "created_by": "Your Name",
        "network_details": {
            "representment_details": {
            "amount": 10
            }
        }
    }
    ```
  </CodeGroup>
</Accordion>

This request transitions the network state to `representment` and Marqeta state remains as `CHARGEBACK_INITIATED`.
If the merchant challenges the chargeback, you receive an `authorization.clearing.representment` event.

### Representment in Visa

When a dispute goes through the Visa network, the representment state does not always apply.

Visa uses the following dispute flows depending on the reason code provided:

* **Collaboration**: For reason codes related to fraud and authorization.
  This flow can simplify the case management process and move it along faster.

  * **Collaboration flow**: Initiated → Representment → Prearbitration (decline or responded) → Arbitration.

* **Allocation**: For all other reason codes.
  The allocation flow skips the representment portion and moves directly into pre-arbitration.
  State transitions for each flow is as described:

  * **Allocation flow**: Initiated → Prearbitration (decline or responded) → Arbitration.

### Simulating prearbitration

If Marqeta chooses to challenge the merchant's representment, it moves the dispute to the `prearbitration` network state, which allows the involved parties to provide further evidence.
You can simulate this transition into prearbitration.

You can simulate the pre-arbitration action by the acquirer by passing `RESPOND_WITH_PREARB` in the `action` field.

### Sample request body

<Accordion title="Sample request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/disputetransitions" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Content-Type: application/json" \
            -d '{
                "action": "RESPOND_WITH_PREARB",
                "created_by": "Your Name",
                "network_details": {
                    "prearbitration_details": {
                        "amount": 10
                    }
                }
            }'
    ```

    ```javascript JavaScript theme={null}
        const respondWithPreArb = async (caseToken) => {
            const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/disputetransitions`;

            const payload = {
                action: "RESPOND_WITH_PREARB",
                created_by: "Your Name",
                network_details: {
                    prearbitration_details: {
                        amount: 10
                    }
                }
            };

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(payload)
            });

            const data = await response.json();
            console.log('Pre-Arbitration Initiated:', data);
        };
    ```

    ```python Python theme={null}
        import requests

        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/disputetransitions"

        headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Content-Type": "application/json"
        }

        payload = {
            "action": "RESPOND_WITH_PREARB",
            "created_by": "Your Name",
            "network_details": {
                "prearbitration_details": {
                    "amount": 10
                }
            }
        }

        response = requests.post(url, headers=headers, json=payload)
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;

    public class InitiatePreArb {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                HttpClient client = HttpClient.newHttpClient();

                String jsonBody = """
                    {
                        "action": "RESPOND_WITH_PREARB",
                        "created_by": "Your Name",
                        "network_details": {
                            "prearbitration_details": {
                                "amount": 10
                            }
                        }
                    }
                    """;

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/disputetransitions"))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println("Response Code: " + response.statusCode());
                System.out.println("Response Body: " + response.body());
            }
        }
    ```
  </CodeGroup>
</Accordion>

### Sample response body

<Accordion title="Sample response">
  <CodeGroup>
    ```json JSON theme={null}
    {
        "token": "38cf59c9-132b-4655-9cb4-ffc5493624fc",
        "created_time": "2026-03-10T15:22:10Z",
        "last_modified_time": "2026-03-10T15:22:10Z",
        "case_token": "<case_token>",
        "action": "RESPOND_WITH_PREARB",
        "created_by": "Frank Disputes",
        "network_details": {
            "prearbitration_details": {
                "amount": 10
            }
        }
    }
    ```
  </CodeGroup>
</Accordion>

This request transitions the network state to `prearbitration` and Marqeta state remains as `CHARGEBACK_INITIATED`.

Marqeta sends you the `chargebacktransitions.prearbitration` webhook.

## Responding to prearbitration

At this point, the merchant can submit further evidence for the case.
The specific requirements for the `prearbitration_response_details` object differ across the various card networks.

You can simulate the reponse to pre-arbitration action to the acquirer by passing `RESPOND_WITH_PREARB_RESPONSE` in the `action` field.

This example follows the Mastercard object, which requires only a list of associated document UUIDs in the `attached_contents` field in the `network_details.prearbitration_response_details` object.

<Warning>
  For testing purposes, pass an empty list in `attached_contents`.
  You can upload new documents and pass those UUIDs in the list.
</Warning>

### Sample request body

<Accordion title="Sample request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/disputetransitions" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Content-Type: application/json" \
            -d '{
                "action": "RESPOND_WITH_PREARB_RESPONSE",
                "created_by": "Your Name",
                "network_details": {
                    "prearbitration_response_details": {
                        "attached_contents": []
                    }
                }
            }'
    ```

    ```javascript JavaScript theme={null}
        const respondWithPreArbDetails = async (caseToken, documentTokens = []) => {
            const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/disputetransitions`;

            const payload = {
                action: "RESPOND_WITH_PREARB_RESPONSE",
                created_by: "Your Name",
                network_details: {
                    prearbitration_response_details: {
                        attached_contents: documentTokens // Array of document UUIDs
                    }
                }
            };

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(payload)
            });

            const data = await response.json();
            console.log('Pre-Arb Response Submitted:', data);
        };
    ```

    ```python Python theme={null}
        import requests

        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/disputetransitions"
    headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Content-Type": "application/json"
        }

        payload = {
            "action": "RESPOND_WITH_PREARB_RESPONSE",
            "created_by": "Your Name",
            "network_details": {
                "prearbitration_response_details": {
                    "attached_contents": [] # Add document UUIDs here
                }
            }
        }

        response = requests.post(url, headers=headers, json=payload)
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;

        public class PreArbResponse {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                HttpClient client = HttpClient.newHttpClient();

                String jsonBody = """
                    {
                        "action": "RESPOND_WITH_PREARB_RESPONSE",
                        "created_by": "Your Name",
                        "network_details": {
                            "prearbitration_response_details": {
                                "attached_contents": []
                            }
                        }
                    }
                    """;

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/disputetransitions"))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println("Status: " + response.statusCode());
                System.out.println("Response: " + response.body());
            }
        }
    ```
  </CodeGroup>
</Accordion>

### Sample response body

<Accordion title="Sample response">
  <CodeGroup>
    ```json JSON theme={null}
    {
        "token": "20d26d96-7df8-4280-87ba-4f319616211a",
        "created_time": "2026-03-10T15:40:26Z",
        "last_modified_time": "2026-03-10T15:40:26Z",
        "case_token": "<case_token>",
        "action": "RESPOND_WITH_PREARB_RESPONSE",
        "created_by": "Frank Disputes",
        "network_details": {
            "prearbitration_response_details": {
                "attached_contents": []
            }
        }
    }
    ```
  </CodeGroup>
</Accordion>

The network state remains as `prearbitration` and Marqeta state remains as `CHARGEBACK_INITIATED`.
The `chargebacktransitions.prearbitration.responded` webhook event sent.

## Moving to arbitration

Assume that the acquirer (merchant) does not agree with the pre-arbitration process.
You can simulate an arbitration request to proceed by passing `RESPOND_WITH_ARB` in the `action` field.

At this point, Marqeta transitions the dispute to the card network, who will provide the final and indisputable decision on the case.

### Sample request body

<Accordion title="Sample request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/disputetransitions" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Content-Type: application/json" \
            -d '{
                "action": "RESPOND_WITH_ARB",
                "created_by": "Your Name"
            }'
    ```

    ```javascript JavaScript theme={null}
        const escalateToArbitration = async (caseToken) => {
            const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/disputetransitions`;

            const payload = {
                action: "RESPOND_WITH_ARB",
                created_by: "Your Name"
            };

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(payload)
            });

            const data = await response.json();
            console.log('Arbitration Escalation Result:', data);
        };
    ```

    ```python Python theme={null}
        import requests

        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/disputetransitions"

        headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Content-Type": "application/json"
        }

        payload = {
            "action": "RESPOND_WITH_ARB",
            "created_by": "Your Name"
        }

        response = requests.post(url, headers=headers, json=payload)

        print(f"Status: {response.status_code}")
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;

        public class EscalateToArb {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                HttpClient client = HttpClient.newHttpClient();

                String jsonBody = """
                    {
                        "action": "RESPOND_WITH_ARB",
                        "created_by": "Your Name"
                    }
                    """;

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/disputetransitions"))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

                System.out.println("Status: " + response.statusCode());
                System.out.println("Body: " + response.body());
            }
        }
    ```
  </CodeGroup>
</Accordion>

### Sample response body

<Accordion title="Sample response">
  <CodeGroup>
    ```json JSON theme={null}
    {
        "token": "5b4a894f-8bc7-41b9-87bd-4ebe3225fd3e",
        "created_time": "2026-03-10T15:53:24Z",
        "last_modified_time": "2026-03-10T15:53:24Z",
        "case_token": "<case_token>",
        "action": "RESPOND_WITH_ARB",
        "created_by": "Your Name"
    }
    ```
  </CodeGroup>
</Accordion>

The network state remains as `arbitration` and the Marqeta state remains as `CHARGEBACK_INITIATED`.
Marqeta sends you the `chargebacktransitions.arbitration` webhook.

## Closing the case and notifying the cardholder

At this stage, the network has decided whether the case is won or lost.
In production, you must notify the cardholder of the outcome.

To simulate this transition, use one of the following actions:

* `CLOSE_WITH_CASE_WON`
* `CLOSE_WITH_NETWORK_REJECTED`

The example below demonstrates a `case.won` flow by sending `CLOSE_WITH_CASE_WON` in the `action` field.

### Sample request body

<Accordion title="Sample request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X POST "https://your-subdomain.marqeta.com/v3/cases/<case_token>/disputetransitions" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Content-Type: application/json" \
            -d '{
                "action": "CLOSE_WITH_CASE_WON",
                "created_by": "Your Name"
            }'
    ```

    ```javascript JavaScript theme={null}
        const closeCaseWon = async (caseToken) => {
            const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}/disputetransitions`;

            const payload = {
                action: "CLOSE_WITH_CASE_WON",
                created_by: "Your Name"
            };

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'X-Marqeta-Program-Short-Code': 'your-program-code',
                    'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(payload)
            });

            const data = await response.json();
            console.log('Case Closed - Won:', data);
        };
    ```

    ```python Python theme={null}
        import requests

        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}/disputetransitions"

        headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Content-Type": "application/json"
        }

        payload = {
            "action": "CLOSE_WITH_CASE_WON",
            "created_by": "Your Name"
        }

        response = requests.post(url, headers=headers, json=payload)

        print(f"Status: {response.status_code}")
        print(response.json())
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;

        public class CloseCaseWon {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                HttpClient client = HttpClient.newHttpClient();

                String jsonBody = """
                    {
                        "action": "CLOSE_WITH_CASE_WON",
                        "created_by": "Your Name"
                    }
                    """;

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken + "/disputetransitions"))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

                System.out.println("Result: " + response.body());
            }
        }
    ```
  </CodeGroup>
</Accordion>

### Sample response body

<Accordion title="Sample response">
  <CodeGroup>
    ```json JSON theme={null}
    {
        "token": "203a8a7d-944f-40a4-a160-25da40573f41",
        "created_time": "2026-03-10T16:02:10Z",
        "last_modified_time": "2026-03-10T16:02:10Z",
        "case_token": "<case_token>",
        "action": "CLOSE_WITH_CASE_WON",
        "created_by": "Frank Disputes"
    }
    ```
  </CodeGroup>
</Accordion>

Marqeta states transitions to `CLOSED` regardless of the decision and the network state transitions to `case.won` or `case.lost` automatically, based on this decision.

## Confirming the dispute status

Marqeta state for dispute is now `CLOSED`.
You can check the state of your Dispute with the following request.

### Sample request body

<Accordion title="Sample request">
  <CodeGroup>
    ```bash Curl theme={null}
        curl -X GET "https://your-subdomain.marqeta.com/v3/cases/<case_token>" \
            -H "X-Marqeta-Program-Short-Code: your-program-code" \
            -H "Authorization: Basic YOUR_BASE64_ENCODED_STRING" \
            -H "Content-Type: application/json"
    ```

    ```javascript JavaScript theme={null}
        const getCaseDetails = async (caseToken) => {
            const url = `https://your-subdomain.marqeta.com/v3/cases/${caseToken}`;

            try {
                const response = await fetch(url, {
                    method: 'GET',
                    headers: {
                        'X-Marqeta-Program-Short-Code': 'your-program-code',
                        'Authorization': 'Basic YOUR_BASE64_ENCODED_STRING',
                        'Content-Type': 'application/json'
                    }
                });

                const data = await response.json();
                console.log('Case Details:', data);
                console.log('Current State:', data.state);
            } catch (error) {
                console.error('Error fetching case:', error);
            }
        };
    ```

    ```python Python theme={null}
        import requests

        case_token = "<case_token>"
        url = f"https://your-subdomain.marqeta.com/v3/cases/{case_token}"

        headers = {
            "X-Marqeta-Program-Short-Code": "your-program-code",
            "Authorization": "Basic YOUR_BASE64_ENCODED_STRING",
            "Content-Type": "application/json"
        }

        response = requests.get(url, headers=headers)

        if response.status_code == 200:
            case_info = response.json()
            print(f"Case State: {case_info.get('state')}")
            print(case_info)
        else:
            print(f"Failed to retrieve case: {response.status_code}")
    ```

    ```java Java theme={null}
        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.HttpRequest;
        import java.net.http.HttpResponse;

        public class GetCase {
            public static void main(String[] args) throws Exception {
                String caseToken = "<case_token>";
                HttpClient client = HttpClient.newHttpClient();

                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://your-subdomain.marqeta.com/v3/cases/" + caseToken))
                    .header("X-Marqeta-Program-Short-Code", "your-program-code")
                    .header("Authorization", "Basic YOUR_BASE64_ENCODED_STRING")
                    .header("Content-Type", "application/json")
                    .GET()
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

                if (response.statusCode() == 200) {
                    System.out.println("Case Details: " + response.body());
                } else {
                    System.out.println("Error: " + response.statusCode());
                }
            }
        }
    ```
  </CodeGroup>
</Accordion>

***

# Next steps

After successfully navigating a basic dispute lifecycle, you can now begin tailoring your code to your specific use cases.

The payloads, responses, and actions you implement will vary significantly depending on the card networks and the regulations your program is subject to.


## Related topics

- [About Disputes](/docs/developer-guides/about-disputes.md)
- [Creating a Dispute](/docs/developer-guides/disputes-portal-create.md)
- [Disputes in the Marqeta Dashboard](/docs/developer-guides/disputes-dashboard.md)
- [Credit Account Disputes](/docs/core-api/credit-account-disputes.md)
- [Disputes Sandbox Overview](/docs/developer-guides/disputes-sandbox/disputes-sandbox-overview.md)
