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

# Transaction Disputes

> Customers can dispute transactions on their card or account for many reasons, ranging from not recognizing the transaction to unauthorized activity.

## Overview

Customers can dispute transactions on their card or account for many reasons, ranging from not recognizing the transaction to unauthorized activity.

Disputing a transaction involves a series of actions between the parties involved, where supporting documentation is exchanged until a decision is reached on who is financially responsible. To begin the dispute process, open a dispute on a transaction through the Synctera Console or the Disputes API (described below). When the dispute is opened, a Dispute Case is automatically created. The Dispute and Dispute Case track the dispute details, lifecycle, and events during investigation. The Dispute Case and Dispute Lifecycle are described in this [article](/v2/docs/dispute-cases-fintechs).

Through both the Dispute Case in the Synctera Console and the Disputes API, you are guided through the dispute flow. Available actions depend on the payment rail of the original transaction. Once an action is created against a dispute, subsequent actions may become available as the case progresses.

Payment-rail–specific behavior differs. For example, card disputes are evaluated and filed with the card network by Synctera on your behalf after evidence is gathered. For card-specific steps, reason codes, and lifecycles, see [Card Transaction Disputes](/v2/docs/card-transaction-disputes). The walkthrough below uses an ACH dispute as the general API example.

## Webhook Events

To monitor transaction disputes, webhooks are triggered anytime one of the following events occurs:

| Webhook           | Description                           |
| ----------------- | ------------------------------------- |
| `DISPUTE.CREATED` | A new dispute has been created.       |
| `DISPUTE.UPDATED` | An existing dispute has been updated. |

To subscribe to the dispute webhooks refer to the [Webhooks Guide](/v2/docs/webhooks-guide).

## Disputing a Transaction

The following steps walk through disputing a transaction using the Disputes API. Examples use `payment_rail` = `ACH`.

Refer to the links below for payment-rail–specific details:

<CardGroup>
  <Card title="Card Transaction Disputes" href="/v2/docs/card-transaction-disputes" icon="angle-right" iconType="solid" horizontal={true} />
</CardGroup>

### 1. Create a Dispute

To create a dispute, use [`POST /v1/disputes`](/v2/reference/createdispute). ACH disputes support incoming ACH credit and debit transactions. The example below uses a personal account, so Regulation E and its applicable deadline fields appear in the response; those fields are omitted for business accounts.

<CodeGroup>
  ```bash Shell theme={"system"}
  curl \
  -X POST \
  $baseurl/v1/disputes \
  -H "Authorization: Bearer $apiKey" \
  --json '
  {
    "payment_rail": "ACH",
    "transaction_id": "{$transaction_id}",
    "disputed_amount": 500,
    "date_customer_reported": "2024-05-28T12:25:00.000Z",
    "memo": "Some details about the reason for creating the dispute."
  }
  '
  ```
</CodeGroup>

This will return a response with the created dispute.

<CodeGroup>
  ```json JSON theme={"system"}
  {
    "account_id": "bdec606d-e6ed-473d-b645-4e689f06a4d2",
    "applicable_regulation": "REGULATION_E",
    "creation_time": "2024-05-28T22:48:24.279984Z",
    "credit_status": "NONE",
    "currency": "USD",
    "customer_id": "9d9ba3c5-81b7-4f42-bbe5-6f5e3d9d71f6",
    "date_customer_reported": "2024-05-28T12:25:00Z",
    "decision": "ONGOING",
    "dispute_documents": [],
    "disputed_amount": 500,
    "id": "73688b78-8b16-4ca6-9d96-e7622799b01d",
    "last_updated_time": "2024-05-28T22:48:24.279984Z",
    "memo": "Some details about the reason for creating the dispute.",
    "network": "ACH",
    "payment_rail": "ACH",
    "status": "OPEN",
    "tenant": "asbght_iujkio",
    "timestamp_investigation_due": "2024-07-12T12:25:00Z",
    "timestamp_provisional_credit_due": "2024-06-11T12:25:00Z",
    "transaction_id": "10c6290e-d9bb-4e0f-a769-d38f25687ccc",
    "action_history": [],
    "available_actions": [
      {
        "action": "STOP_PAYMENT",
        "state": "CREATE"
      },
      {
        "action": "ACH_RETURN",
        "state": "CREATE"
      }
    ],
    "lifecycle_state": "PENDING_ACTION"
  }
  ```
</CodeGroup>

Note the returned `id` attribute and the list of `available_actions`.

### 2. Upload Supporting Documents

Supporting documents can be uploaded to any dispute (ACH or card) with [`POST /v1/disputes/{dispute_id}/documents`](/v2/reference/adddisputedocument). Uploaded files appear on the dispute under `dispute_documents` and can be referenced from actions via `supporting_doc_id` when applicable.

Optionally set `category` on upload:

| Category                    | Description                              |
| --------------------------- | ---------------------------------------- |
| `TRANSACTION_RECEIPT`       | Receipt for the disputed transaction     |
| `PRIOR_TRANSACTION_RECEIPT` | Receipt from a prior related transaction |
| `MERCHANT_CORRESPONDENCE`   | Correspondence with the merchant         |
| `COUNTERFEIT_EVIDENCE`      | Evidence that goods were counterfeit     |
| `REFUND_PROMISE`            | Evidence of a promised refund            |
| `OTHER`                     | Other supporting documentation           |

<CodeGroup>
  ```bash Shell theme={"system"}
  curl \
  -X POST \
  $baseurl/v1/disputes/{$dispute_id}/documents \
  -H "Authorization: Bearer $apiKey" \
  -F file=@file.pdf \
  -F category=OTHER
  ```
</CodeGroup>

This will return a response with the created document.

<CodeGroup>
  ```json JSON theme={"system"}
  {
    "creation_time": "2024-05-28T22:56:12.921781Z",
    "dispute_id": "73688b78-8b16-4ca6-9d96-e7622799b01d",
    "file_name": "file.pdf",
    "id": "dff07f15-417f-4998-9bcf-82881144f8d9",
    "category": "OTHER",
    "tenant": "asbght_iujkio"
  }
  ```
</CodeGroup>

Note the returned document `id` as it can be used in subsequent dispute actions via `supporting_doc_id`.

ACH supporting documents can be up to 14MB. For card disputes, files must be JPEG, PNG, or PDF, max 4.5MB each, and up to 10 documents per dispute. Some card reason codes also require a document with a specific `category` before the case can be filed — see [Card Transaction Disputes](/v2/docs/card-transaction-disputes#reason-code).

### 3. Create a Dispute Action

Select the action you wish to create from the list of `available_actions` on the dispute.

To create the action, use [`POST /v1/disputes/{dispute_id}/actions`](/v2/reference/createaction)

<CodeGroup>
  ```bash Shell theme={"system"}
  curl \
  -X POST \
  $baseurl/v1/disputes/{$dispute_id}/actions \
  -H "Authorization: Bearer $apiKey" \
  --json '
  {
    "payment_rail": "ACH",
    "action": "ACH_RETURN",
    "state": "CREATE",
    "reason_code": "UNAUTHORIZED_TRANSACTION",
    "return_code": "R10",
    "supporting_doc_id": "{$document_id}",
    "message": "Customer did not authorize this debit"
  }
  '
  ```
</CodeGroup>

This will return a response with the created action.

<CodeGroup>
  ```json JSON theme={"system"}
  {
    "action": "ACH_RETURN",
    "creation_time": "2024-05-28T22:58:30.396998Z",
    "id": "109ac96e-9572-4d43-9a01-772631d0e869",
    "message": "Customer did not authorize this debit",
    "payment_rail": "ACH",
    "reason_code": "UNAUTHORIZED_TRANSACTION",
    "return_code": "R10",
    "status": "SUBMITTED",
    "tenant": "asbght_iujkio"
  }
  ```
</CodeGroup>

`ACH_RETURN` requires a `reason_code` and corresponding ACH `return_code`. `R10` is valid for `UNAUTHORIZED_TRANSACTION`. After this action is created, the dispute moves to `ACH_AWAITING_APPROVAL` while it is reviewed. Uploaded documents remain listed on the dispute under `dispute_documents`. Although `supporting_doc_id` is stored from the request, current ACH action responses expose the document through `dispute_documents` rather than returning `supporting_doc_id` on the action.

### 4. Monitor for Dispute Updates

When the dispute is updated, a `DISPUTE.UPDATED` webhook is triggered. The webhook's `event_resource` contains the versioned dispute resource; the `v1` object has the same shape as a response from [`GET /v1/disputes/{dispute_id}`](/v2/reference/getdispute), including the updated `action_history`, `lifecycle_state`, and `available_actions`. Depending on the update, a final decision may be reached or further actions may be available.

If the dispute `decision` is still `ONGOING`, review the latest actions and any new supporting documents before continuing.

The decoded `v1` dispute object after Synctera requests more information is:

<CodeGroup>
  ```json JSON theme={"system"}
  {
    "account_id": "bdec606d-e6ed-473d-b645-4e689f06a4d2",
    "applicable_regulation": "REGULATION_E",
    "creation_time": "2024-05-28T22:48:24.279984Z",
    "credit_status": "NONE",
    "currency": "USD",
    "customer_id": "9d9ba3c5-81b7-4f42-bbe5-6f5e3d9d71f6",
    "date_customer_reported": "2024-05-28T12:25:00Z",
    "decision": "ONGOING",
    "dispute_documents": [
      {
        "creation_time": "2024-05-28T22:56:12.921781Z",
        "dispute_id": "73688b78-8b16-4ca6-9d96-e7622799b01d",
        "file_name": "file.pdf",
        "id": "dff07f15-417f-4998-9bcf-82881144f8d9",
        "category": "OTHER",
        "tenant": "asbght_iujkio"
      }
    ],
    "disputed_amount": 500,
    "id": "73688b78-8b16-4ca6-9d96-e7622799b01d",
    "last_action_by": "INITIATOR",
    "last_updated_time": "2024-05-29T14:30:00.010000Z",
    "memo": "Some details about the reason for creating the dispute.",
    "network": "ACH",
    "payment_rail": "ACH",
    "status": "OPEN",
    "tenant": "asbght_iujkio",
    "timestamp_investigation_due": "2024-07-12T12:25:00Z",
    "timestamp_provisional_credit_due": "2024-06-11T12:25:00Z",
    "transaction_id": "10c6290e-d9bb-4e0f-a769-d38f25687ccc",
    "action_history": [
      {
        "action": "ACH_RETURN",
        "creation_time": "2024-05-28T22:58:30.396998Z",
        "id": "109ac96e-9572-4d43-9a01-772631d0e869",
        "message": "Customer did not authorize this debit",
        "payment_rail": "ACH",
        "reason_code": "UNAUTHORIZED_TRANSACTION",
        "return_code": "R10",
        "status": "SUBMITTED",
        "tenant": "asbght_iujkio"
      },
      {
        "action": "ACH_RETURN",
        "creation_time": "2024-05-29T14:30:00Z",
        "id": "c501b7c7-4ad9-4091-8b37-c0c0299fc12f",
        "message": "Need more authorization evidence",
        "payment_rail": "ACH",
        "reason_code": "UNAUTHORIZED_TRANSACTION",
        "status": "MORE_INFO_REQUIRED",
        "tenant": "asbght_iujkio"
      }
    ],
    "available_actions": [
      {
        "action": "ACH_RETURN",
        "state": "CREATE"
      },
      {
        "action": "ACH_RETURN",
        "state": "REJECT"
      }
    ],
    "lifecycle_state": "ACH_MORE_INFO_REQUIRED"
  }
  ```
</CodeGroup>

In `ACH_MORE_INFO_REQUIRED`, you can re-submit the same action type (`ACH_RETURN` with `state` = `CREATE`, including `reason_code` and `return_code`) after uploading additional documents, or reject the action. Use document IDs from `dispute_documents` to retrieve contents for review.

### 5. Review Additional Supporting Documents

To retrieve supporting documentation from the dispute, use [`GET /v1/disputes/documents/{document_id}/contents`](/v2/reference/getdisputedocumentcontents)

<CodeGroup>
  ```bash Shell theme={"system"}
  curl \
  -X GET \
  $baseurl/v1/disputes/documents/{$document_id}/contents \
  -H "Authorization: Bearer $apiKey" \
  -o file.pdf
  ```
</CodeGroup>

The response body contains the document contents and is saved as `file.pdf`.

### 6. Re-submit the ACH Return

After providing the requested information, re-submit the ACH return using an action listed in `available_actions`.

<CodeGroup>
  ```bash Shell theme={"system"}
  curl \
  -X POST \
  $baseurl/v1/disputes/{$dispute_id}/actions \
  -H "Authorization: Bearer $apiKey" \
  --json '
  {
    "payment_rail": "ACH",
    "action": "ACH_RETURN",
    "state": "CREATE",
    "reason_code": "UNAUTHORIZED_TRANSACTION",
    "return_code": "R10",
    "supporting_doc_id": "{$document_id}",
    "message": "Attached customer affidavit"
  }
  '
  ```
</CodeGroup>

This returns the re-submitted action:

<CodeGroup>
  ```json JSON theme={"system"}
  {
    "action": "ACH_RETURN",
    "creation_time": "2024-05-29T15:00:00Z",
    "id": "6917ee86-deac-4f08-8472-8888601adbf6",
    "message": "Attached customer affidavit",
    "payment_rail": "ACH",
    "reason_code": "UNAUTHORIZED_TRANSACTION",
    "return_code": "R10",
    "status": "SUBMITTED",
    "tenant": "asbght_iujkio"
  }
  ```
</CodeGroup>

The dispute returns to `ACH_AWAITING_APPROVAL` while Synctera reviews the additional information.

### 7. Review the Final Decision

When the ACH return is accepted, another `DISPUTE.UPDATED` webhook is sent. You can also retrieve the current state with [`GET /v1/disputes/{dispute_id}`](/v2/reference/getdispute):

<CodeGroup>
  ```bash Shell theme={"system"}
  curl \
  -X GET \
  $baseurl/v1/disputes/{$dispute_id} \
  -H "Authorization: Bearer $apiKey"
  ```
</CodeGroup>

<CodeGroup>
  ```json JSON theme={"system"}
  {
    "account_id": "bdec606d-e6ed-473d-b645-4e689f06a4d2",
    "applicable_regulation": "REGULATION_E",
    "creation_time": "2024-05-28T22:48:24.279984Z",
    "credit_status": "NONE",
    "currency": "USD",
    "customer_id": "9d9ba3c5-81b7-4f42-bbe5-6f5e3d9d71f6",
    "date_customer_reported": "2024-05-28T12:25:00Z",
    "decision": "WON",
    "dispute_documents": [
      {
        "creation_time": "2024-05-28T22:56:12.921781Z",
        "dispute_id": "73688b78-8b16-4ca6-9d96-e7622799b01d",
        "file_name": "file.pdf",
        "id": "dff07f15-417f-4998-9bcf-82881144f8d9",
        "category": "OTHER",
        "tenant": "asbght_iujkio"
      }
    ],
    "disputed_amount": 500,
    "id": "73688b78-8b16-4ca6-9d96-e7622799b01d",
    "last_action_by": "INITIATOR",
    "last_updated_time": "2024-05-30T16:00:00.010000Z",
    "memo": "Some details about the reason for creating the dispute.",
    "network": "ACH",
    "payment_rail": "ACH",
    "status": "OPEN",
    "tenant": "asbght_iujkio",
    "timestamp_final_decision": "2024-05-30T16:00:00Z",
    "timestamp_investigation_due": "2024-07-12T12:25:00Z",
    "timestamp_provisional_credit_due": "2024-06-11T12:25:00Z",
    "transaction_id": "10c6290e-d9bb-4e0f-a769-d38f25687ccc",
    "action_history": [
      {
        "action": "ACH_RETURN",
        "creation_time": "2024-05-28T22:58:30.396998Z",
        "id": "109ac96e-9572-4d43-9a01-772631d0e869",
        "message": "Customer did not authorize this debit",
        "payment_rail": "ACH",
        "reason_code": "UNAUTHORIZED_TRANSACTION",
        "return_code": "R10",
        "status": "SUBMITTED",
        "tenant": "asbght_iujkio"
      },
      {
        "action": "ACH_RETURN",
        "creation_time": "2024-05-29T14:30:00Z",
        "id": "c501b7c7-4ad9-4091-8b37-c0c0299fc12f",
        "message": "Need more authorization evidence",
        "payment_rail": "ACH",
        "reason_code": "UNAUTHORIZED_TRANSACTION",
        "status": "MORE_INFO_REQUIRED",
        "tenant": "asbght_iujkio"
      },
      {
        "action": "ACH_RETURN",
        "creation_time": "2024-05-29T15:00:00Z",
        "id": "6917ee86-deac-4f08-8472-8888601adbf6",
        "message": "Attached customer affidavit",
        "payment_rail": "ACH",
        "reason_code": "UNAUTHORIZED_TRANSACTION",
        "return_code": "R10",
        "status": "SUBMITTED",
        "tenant": "asbght_iujkio"
      },
      {
        "action": "ACH_RETURN",
        "creation_time": "2024-05-30T16:00:00Z",
        "id": "82f203c5-fe66-488b-937b-1b6ee42ba06c",
        "payment_rail": "ACH",
        "reason_code": "UNAUTHORIZED_TRANSACTION",
        "return_code": "R10",
        "status": "ACCEPTED",
        "tenant": "asbght_iujkio"
      }
    ],
    "available_actions": [],
    "lifecycle_state": "ACH_FILED_WITH_NETWORK"
  }
  ```
</CodeGroup>

An accepted ACH return sets `decision` to `WON` and `lifecycle_state` to `ACH_FILED_WITH_NETWORK`. A rejected return instead sets `decision` to `LOST` and `lifecycle_state` to `ACH_REJECTED`.

### 8. Close Dispute

After the dispute reaches a final decision, close it with [`PATCH /v1/disputes/{dispute_id}`](/v2/reference/updatedispute):

<CodeGroup>
  ```bash Shell theme={"system"}
  curl \
  -X PATCH \
  $baseurl/v1/disputes/{$dispute_id} \
  -H "Authorization: Bearer $apiKey" \
  --json '
  {
    "status": "CLOSED"
  }
  '
  ```
</CodeGroup>

The response is the updated dispute. Its final decision and lifecycle do not change; `status` becomes `CLOSED`, `last_updated_time` reflects the close, and `available_actions` remains empty.
