Learn how to test the Disputes API in the Square Sandbox.
Disputes API

Test the Disputes API

Developers use the Disputes API to programmatically complete the steps of the dispute process. To test your application without creating actual payment disputes with a bank, make calls to the Disputes API using the Square Sandbox. This topic walks through the following steps:

  1. Trigger a dispute in the Sandbox

  2. Get new disputes

  3. Respond by accepting or challenging the dispute

  4. Verify the state of the dispute

The following flowchart outlines the steps of the dispute process and possible outcomes, beginning with the customer’s initial chargeback request. For more information about the seller’s role in the dispute process and details about the use of each Disputes API endpoint in a production application, see Process Disputes.

A diagram showing the dispute process from initiation through resolution

To trigger a test dispute in the Square Sandbox, send a CreatePayment request with one of the following charge amounts. The Sandbox creates a Dispute object whose reason corresponds to the charge amount set.

Charge amountDispute reason
8801AMOUNT_DIFFERS
8802CANCELLED
8803DUPLICATE
8804NO_KNOWLEDGE
8805NOT_AS_DESCRIBED
8806NOT_RECEIVED
8807PAID_BY_OTHER_MEANS
8808CUSTOMER_REQUESTS_CREDIT
8809EMV_LIABILITY_SHIFT

Note

The amounts shown are in the lowest denomination of the currency provided in the request. For example, USD is in cents.

The following Sandbox request creates a payment for the amount of $88.03 USD. This generates a Dispute with the reason of DUPLICATE. When testing payments in the Sandbox, you can use one of the test payment tokens as the source_id in the request.

Create Payment
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
curl https://connect.squareupsandbox.com/v2/payments \
  -X POST \
  -H 'Square-Version: 2022-07-20' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "idempotency_key": "53427950-0d65-40e2-9108-d3072535961f",
    "source_id": "cnon:card-nonce-ok",
    "amount_money": {
      "amount": 8803,
      "currency": "USD"
    }
  }'

The following is an example response:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
{
  "payment": {
    "id": "BqzL87eLnz9gJRuoiIYSY44p9ORZY",
    "created_at": "2022-05-02T15:08:42.217Z",
    "updated_at": "2022-05-02T15:08:42.481Z",
    "amount_money": {
      "amount": 8803,
      "currency": "USD"
    },
    "status": "COMPLETED",
    "delay_duration": "PT168H",
    "source_type": "CARD",
    "card_details": {
      "status": "CAPTURED",
      "card": {
        "card_brand": "VISA",
        "last_4": "5858",
        "exp_month": 5,
        "exp_year": 2024,
        "fingerprint": "sq-1-il5Ik5fUhNr9fTjLEWcZWaLpV0Ozij13Sry1jvqRiybpgAgbv4rOT3DPxVjs_tJOzQ",
        "card_type": "CREDIT",
        "prepaid_type": "NOT_PREPAID",
        "bin": "453275"
      },
      "entry_method": "KEYED",
      "cvv_status": "CVV_ACCEPTED",
      "avs_status": "AVS_ACCEPTED",
      "statement_description": "SQ *DEFAULT TEST ACCOUNT",
      "card_payment_timeline": {
        "authorized_at": "2022-05-02T15:08:42.327Z",
        "captured_at": "2022-05-02T15:08:42.482Z"
      }
    },
    "location_id": "L1HN3ZMTZEB87",
    "order_id": "QKE7BmUeP58xIxdVeL4ps2CQ5c4F",
    "risk_evaluation": {
      "created_at": "2022-05-02T15:08:42.327Z",
      "risk_level": "NORMAL"
    },
    "total_money": {
      "amount": 8803,
      "currency": "USD"
    },
    "approved_money": {
      "amount": 8803,
      "currency": "USD"
    },
    "receipt_number": "7tMe",
    "receipt_url": "https://squareupsandbox.com/receipt/preview/7tMeeuCCMOF3Xh1iRyGmdd1MuSBZY",
    "delay_action": "CANCEL",
    "delayed_until": "2022-05-09T15:08:42.217Z",
    "application_details": {
      "square_product": "ECOMMERCE_API",
      "application_id": "sandbox-sq0idb-TINhb_yF4yhyks_OiADYzA"
    },
    "version_token": "iI6Z7ot8md2wc9V6Xp0sF2hBdiKzT4f2LxcANqA86yw6o"
  }
}

Your application receives new Dispute objects by listening for the dispute.created webhook or by calling the ListDisputes endpoint.

If you set up a subscription for disputes webhooks , your listening endpoint receives a dispute.created notification whenever a new dispute is created. The body of the notification contains the new Dispute object.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
{
  "merchant_id": "MGYG72TMMXMCQ",
  "location_id": "L1HN3ZMTZEB87",
  "type": "dispute.created",
  "event_id": "4f5cf45b-ff26-4ec1-b720-4d4e934883f9",
  "created_at": "2022-05-02T15:08:42.217Z",
  "data": {
    "type": "dispute",
    "id": "OWo09e15R49UrfXjG5Bod",
    "object": {
      "dispute": {
        "amount_money": {
          "amount": 8803,
          "currency": "USD"
        },
        "brand_dispute_id": "P9td9draSX6ACrUO3KEI6Q",
        "card_brand": "VISA",
        "created_at": "2022-05-02T15:08:42.217Z",
        "disputed_payment": {
          "payment_id": "BqzL87eLnz9gJRuoiIYSY44p9ORZY"
        },
        "due_at": "2022-05-16T00:00:00.000Z",
        "id": "OWo09e15R49UrfXjG5Bod",
        "location_id": "L1HN3ZMTZEB87",
        "reason": "DUPLICATE",
        "reported_at": "2022-05-02T15:08:42.217Z",
        "state": "EVIDENCE_REQUIRED",
        "updated_at": "2022-05-02T15:40:42.978Z"
      }
    }
  }
}

If you do not want to use webhook notifications, you can make periodic calls to ListDisputes . An unfiltered request returns all disputes, so it might be helpful to filter the request to only return disputes awaiting seller action.

Important

A seller typically has 14 days or less to respond to a new dispute. Depending on how often your application calls ListDisputes, information about disputes might be delayed getting to sellers. Consider implementing webhook notifications to receive dispute data as it is created.

The following ListDisputes request is filtered to return only open disputes in the EVIDENCE_REQUIRED state (that is, awaiting seller action):

List Disputes
  • 1
  • 2
  • 3
  • 4
curl https://connect.squareupsandbox.com/v2/disputes?states=EVIDENCE_REQUIRED \
  -H 'Square-Version: 2022-07-20' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json'

The following sample response shows two disputes: the DUPLICATE dispute created in the previous step and a dispute with the reason of NOT_RECEIVED. Both are awaiting action.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
{
  "disputes": [
    {
      "amount_money": {
        "amount": 8803,
        "currency": "USD"
      },
      "reason": "DUPLICATE",
      "state": "EVIDENCE_REQUIRED",
      "due_at": "2022-05-16T00:00:00.000Z",
      "disputed_payment": {
        "payment_id": "BqzL87eLnz9gJRuoiIYSY44p9ORZY"
      },
      "card_brand": "VISA",
      "created_at": "2022-05-02T15:08:42.217Z",
      "updated_at": "2022-05-02T15:08:42.481Z",
      "brand_dispute_id": "P9td9draSX6ACrUO3KEI6Q",
      "location_id": "L1HN3ZMTZEB87",
      "id": "OWo09e15R49UrfXjG5Bod",
      "reported_at": "2022-05-02T00:00:00.000Z"
    },
    {
      "amount_money": {
        "amount": 8806,
        "currency": "USD"
      },
      "reason": "NOT_RECEIVED",
      "state": "EVIDENCE_REQUIRED",
      "due_at": "2022-06-16T00:00:00.000Z",
      "disputed_payment": {
        "payment_id": "rRozdpYme93hXWPPUIXEjvB8kdVZY"
      },
      "card_brand": "VISA",
      "created_at": "2022-06-02T15:46:06.585Z",
      "updated_at": "2022-06-02T15:52:28.759Z",
      "brand_dispute_id": "PGAM7Z22So2Y5kZVYCEbQA",
      "version": 2,
      "location_id": "L1HN3ZMTZEB87",
      "id": "yVD4obqS9rn7Zrr9MIS3P",
      "reported_at": "2022-06-02T00:00:00.000Z"
    }
  ]
}

Important

  • If the due_at deadline passes with no action from the seller, Square automatically challenges the dispute on the seller’s behalf.

  • If a seller takes an initial action on a dispute by using the Disputes Dashboard, the dispute state changes to PROCESSING and your application cannot take further action.

Sellers respond by either accepting or challenging the dispute.

To accept the dispute on behalf of a seller, have your application call AcceptDispute. This is not reversible. If a dispute is accepted, it cannot be challenged later.

Accept Dispute
  • 1
  • 2
  • 3
  • 4
  • 5
curl https://connect.squareupsandbox.com/v2/disputes/OWo09e15R49UrfXjG5Bod/accept \
  -X POST \
  -H 'Square-Version: 2022-07-20' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json'

The following response shows that the state of the test dispute has changed to ACCEPTED:

Challenging a dispute using the Disputes API is a two-step process:

  1. Upload evidence. Your application provides one or more pieces of evidence related to the payment. These can be images, PDFs, or text. For more information about the requirements and best practices for uploading evidence, see Uploading evidence .

  2. Submit the evidence. Your application calls the SubmitEvidence endpoint to submit the provided evidence to the bank.

For testing purposes, disputes managed in the Square Sandbox can be WON or LOST by submitting a piece of evidence with the name evidence_won or evidence_lost. Submitting any of the allowed file types with either of these names causes an automatic WON or LOST state change.

Suppose you are testing a sample dispute in the Sandbox with the reason of NOT_RECEIVED. The following example call to CreateDisputeEvidenceFile uploads an image delivery-confirmation.png as PROOF_OF_DELIVERY_DOCUMENTATION.

Create Dispute Evidence File
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
curl https://connect.squareupsandbox.com/v2/disputes/yVD4obqS9rn7Zrr9MIS3P/evidence-files \
  -X POST \
  -H 'Square-Version: 2022-07-20' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Accept: application/json' \
  -F 'file=@/path/to/file/delivery-confirmation.png' \
  -F 'request={
    "idempotency_key": "3fee30ce-e0a0-4152-b53b-13aa1533b0a3",
    "evidence_type": "PROOF_OF_DELIVERY_DOCUMENTATION",
    "content_type": "image/png"
  }'

To complete testing and trigger an automatic WON or LOST state for the dispute, make another call to CreateDisputeEvidenceFile and include a file of the application/pdf type named evidence_won.pdf (to test a winning dispute state) or evidence_lost.pdf (to test a losing dispute state).

Create Dispute Evidence File
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
curl https://connect.squareupsandbox.com/v2/disputes/yVD4obqS9rn7Zrr9MIS3P/evidence-files \
  -X POST \
  -H 'Square-Version: 2022-07-20' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Accept: application/json' \
  -F 'file=@/path/to/file/evidence_won.pdf' \
  -F 'request={
    "idempotency_key": "897b9c14-217a-45e7-bc59-d9499b2639c4",
    "evidence_type": "GENERIC_EVIDENCE",
    "content_type": "application/pdf"
  }'

Finally, submit the evidence using the SubmitEvidence endpoint. Do not call SubmitEvidence for each piece of uploaded evidence. Call the endpoint after the complete body of evidence has been uploaded to Square. By calling SubmitEvidence, the challenge process starts and you can no longer add or remove evidence.

Submit Evidence
  • 1
  • 2
  • 3
  • 4
  • 5
curl https://connect.squareupsandbox.com/v2/disputes/yVD4obqS9rn7Zrr9MIS3P/submit-evidence \
  -X POST \
  -H 'Square-Version: 2022-07-20' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json'

The following is an example response:

After a seller submits evidence to challenge a dispute, the state changes to PROCESSING while the bank deliberates. Your application can listen for the dispute.state.updated webhook notification to receive the most timely notification when a bank responds to the dispute challenge.

When testing the Disputes API in the Square Sandbox, you can cause a dispute state change to WON or LOST by submitting a piece of evidence named evidence_won or evidence_lost, respectively. Because there is no bank involved in Sandbox disputes, if you submit a dispute without any evidence with these names, the state changes to PROCESSING, but does not resolve.

In the previous step, delivery-confirmation.png and evidence_won.pdf were submitted as evidence for a dispute. The state changes to WON, and the webhook notification contains the following data:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
{
  "merchant_id": "MGYG72TMMXMCQ",
  "location_id": "L1HN3ZMTZEB87",
  "type": "dispute.state.updated",
  "event_id": "a6c77a1e-d426-4659-a585-db13fbd76c12",
  "created_at": "2022-06-02T14:55:09.831Z",
  "data": {
    "type": "dispute",
    "id": "yVD4obqS9rn7Zrr9MIS3P",
    "object": {
      "dispute": {
        "amount_money": {
          "amount": 8806,
          "currency": "USD"
        },
        "brand_dispute_id": "P9td9draSX6ACrUO3KEI6Q",
        "card_brand": "VISA",
        "created_at": "2022-06-02T16:38:37.460Z",
        "disputed_payment": {
          "payment_id": "rRozdpYme93hXWPPUIXEjvB8kdVZY"
        },
        "due_at": "2022-06-16T00:00:00.000Z",
        "id": "yVD4obqS9rn7Zrr9MIS3P",
        "location_id": "L1HN3ZMTZEB87",
        "reason": "NOT_RECIEVED",
        "reported_at": "2022-06-02T00:00:00.000Z",
        "state": "WON",
        "updated_at": "2022-06-02T14:55:09.831Z",
        "version": 6
      }
    }
  }
}

Another way to receive information about a dispute is to call RetrieveDispute with a dispute ID. Note that it might take a bank several days or more to respond to a dispute challenge. Therefore, if your application regularly queries for information about open disputes, it might take time to receive new information.

Retrieve Dispute
  • 1
  • 2
  • 3
  • 4
curl https://connect.squareupsandbox.com/v2/disputes/yVD4obqS9rn7Zrr9MIS3P \
  -H 'Square-Version: 2022-07-20' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json'

The following is an example response:

If you need more assistance, contact Developer Support or ask for help in the Developer Forums.