Disputes API

Process a Dispute in the Sandbox

A dispute can be either accepted or challenged with evidence using the Disputes API. This topic shows you how to validate that your Disputes API integration can complete these actions in the Square Sandbox. On validation of your integration, it is ready to be put into production.

The walkthrough takes you through the following steps:

  1. Trigger a new dispute by creating a payment in the Sandbox.

  2. Respond to the dispute.created webhook or request a list of open disputes

  3. (optional) Accept the dispute.

  4. (optional) Challenge the dispute by uploading and submitting evidence.

  5. Check the state of the dispute.

Try running through the walkthrough by taking the accept dispute path and then running through it again on the challenge dispute path.

Important

The API lets you accept a dispute or challenge a dispute. You cannot take both actions on the same dispute. After a dispute is accepted, it cannot be challenged.

Test the Disputes API in the Square Sandbox Permalink Get a link to this section

You can use the Sandbox environment to test the Disputes API. Use the following guidelines to generate sample disputes, challenge disputes, and obtain resolutions:

  • Trigger a dispute. To trigger a dispute, create a payment by setting one of the following amounts in a CreatePayment request. The Sandbox creates a dispute whose dispute reason (DisputeReason) corresponds to the charge amount you 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 you provide in the CreatePayment request. For example, USD is in cents.

  • Accept a dispute. To accept a dispute, call the AcceptDispute endpoint.

  • Challenge a dispute. To challenge a dispute, upload one or more pieces of evidence. The last piece of sample evidence you upload should be a file with the name "evidence_won" or "evidence_lost". Square uses the last file name to automatically resolve the dispute accordingly.

Note

In this walkthrough, the code examples specify the Sandbox domain in the endpoint URL (connect.squareupsandbox.com).

Prepare your application Permalink Get a link to this section

To prepare for the walkthrough, complete the following steps:

  1. If your application is using the OAuth API authorization flow, verify that your application is requesting the DISPUTES_READ and DISPUTES_WRITE OAuth permissions.

  2. Create two PDF documents (the content of the PDF documents does not matter in this testing example). Name the two documents samplePDF.pdf and evidence_won.pdf. Upload these test documents as evidence when you challenge the disputes in the Sandbox.

  3. (optional) In the walkthrough, the ListDisputes endpoint is used to get a list of disputes. You can also subscribe to the webhook events to get notification when dispute events occur. For more information, see Subscribe to Events.

Step 1: Trigger a Sandbox dispute Permalink Get a link to this section

Create a payment for the amount of $88.03 USD. Square automatically generates a dispute with the reason DUPLICATE.

  • Send a CreatePayment request.

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

    The following is an example response:

    {
       "payment":{
          "id":"0dG0pUTlY5bYMr2CJbttiLByvaB",
          "created_at":"2019-12-16T01:21:56.614Z",
          "updated_at":"2019-12-16T01:21:56.787Z",
          "amount_money":{
             "amount":8803,
             "currency":"USD"
          },
          "status":"COMPLETED",
          "source_type":"CARD",
          "card_details":{
             "status":"CAPTURED",
             "card":{
                "card_brand":"AMERICAN_EXPRESS",
                "last_4":"6550",
                "exp_month":12,
                "exp_year":2021,
                "fingerprint":"sq-1-Qo2zq6ihytSFS7jL8DaOro1sBUOfsv8o5rzl1uxie4KPd-gZcTxOJRj3moHXZ-f2CA",
                "bin":"371263"
             },
             "entry_method":"KEYED",
             "cvv_status":"CVV_ACCEPTED",
             "avs_status":"AVS_ACCEPTED",
             "statement_description":"SQ *DEFAULT TEST ACCOUNT"
          },
          "location_id":"S8GWD5R9QB376",
          "order_id":"6Sm73w9MK2YNqsnFOliz3S9VrRFZY",
          "total_money":{
             "amount":8803,
             "currency":"USD"
          },
          "receipt_number":"0dG0",
          "receipt_url":"https://squareup.com/receipt/preview/0dG0pUTlY5bYMr2CJbttiLByvaB"
       }
    }
    

Step 2: Get new disputes Permalink Get a link to this section

The Sandbox responds to the payment of $88.03 by creating a Dispute object that mocks the production dispute that would be created if a card holder requested a chargeback. Your application gets this Dispute object by listening for a disputes webhook or by calling the ListDisputes endpoint.

Listen for the dispute.created notification Permalink Get a link to this section

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

  • Listen for the dispute.created webhook notification.

  • Get the Dispute object from the notification payload. It is the value of data.object.dispute in the following JSON:

    {
      "merchant_id": "0HPGX5JYE6EE1",
      "location_id": "VJDQQP3CG14EY",
      "type": "dispute.created",
      "event_id": "ce8464b5-6628-4ac2-9264-e06c34df3e82",
      "created_at": "2019-12-16T01:21:56.714Z",
      "data": {
        "type": "dispute",
        "id": "ORSEVtZAJxb37RA1EiGw",
        "object": {
          "dispute": {
            "amount_money": {
              "amount": 8803,
              "currency": "USD"
            },
            "brand_dispute_id": "r9rKGSBBQbywBNnWWIiGFg",
            "card_brand": "AMERICAN_EXPRESS",
            "created_at": "2019-12-16T01:21:56.714Z",
            "id": "ORSEVtZAJxb37RA1EiGw",
            "disputed_payment": {
              "payment_id": "0dG0pUTlY5bYMr2CJbttiLByvaB"
            },
            "due_at": "2020-01-04T00:00:00.000Z",
            "location_id": "VJDQQP3CG14EY",
            "reason": "DUPLICATE",
            "reported_at": "2019-12-16T01:21:56.714Z",
            "state": "EVIDENCE_REQUIRED",
            "updated_at": "2019-12-16T01:21:56.714Z",
            "version": 1
          }
        }
      }
    }
    

Get a list of disputes Permalink Get a link to this section

You can set up periodic polling for open disputes such as a request every 24 hours. The ListDisputes endpoint request must be filtered to return dispute objects that are awaiting seller action. That is, they are awaiting the evidence needed for a dispute or simply the seller acceptance of the buyer's chargeback request. An unfiltered request returns all open disputes.

Did you know?

A seller typically has 7 or more days to respond to a new dispute. The polling delay in displaying new disputes is usually a small fraction of the alloted response time. If this is an issue for the seller who uses your application, consider implementing webhook notifications to get notified of new disputes as they are created.

If your application is polling for open disputes that are awaiting evidence, you need to write application logic that assumes the same dispute might have been returned in the previous polling request. When using webhooks, you do not need this logic because Square only sends a dispute.created notification once per dispute.

In the following example ListDisputes request, the access token in the Authorization header identifies the specific Square seller account for which to return the dispute list. The request is filtered to the dispute states needed for returning open disputes that have had no actions taken.

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

The following is a sample response. It shows a new dispute awaiting evidence.

{
   "disputes":[
      { 
         "id":"ORSEVtZAJxb37RA1EiGw",
         "amount_money":{ 
            "amount":8803,
            "currency":"USD"
         },
         "reason":"DUPLICATE",
         "state":"EVIDENCE_REQUIRED",
         "due_at":"2020-01-04T00:00:00.000Z",
         "disputed_payment":{ 
            "payment_id":"0dG0pUTlY5bYMr2CJbttiLByvaB"
         },
         "card_brand":"AMERICAN_EXPRESS",
         "created_at":"2019-12-16T18:07:57.373Z",
         "updated_at":"2019-12-17T01:38:51.767Z",
         "brand_dispute_id":"JVhxqiFNQ3eAJCJ_yBmAgg",
         "reported_at":"2019-12-16T00:00:00.000Z",
         "version":1,
         "location_id":"S8GWD5R9QB376"
      },
      {... more disputes...}
   ]
}

Important

If the seller does not respond by the due_at deadline, the dispute state changes from evidence_required to processing and your application cannot take further action on the dispute.

A seller might also take initial action on a dispute by using the Disputes Dashboard. If a seller starts the process in the dashboard before action is taken in your application, the dispute state changes to processing and your application cannot take further action.

When a dispute state indicates that evidence is required, the seller can accept or challenge the dispute. If the seller wants to challenge the dispute, the seller should submit evidence that directly addresses the dispute reason type. For a list of dispute reasons and related explanations, see the reason field of the Dispute type.

Step 3: (optional) Accept a dispute Permalink Get a link to this section

If the seller accepts a dispute, send a POST request to the AcceptDispute endpoint. This is not reversible. When they accept a dispute, they cannot go back and challenge it later.

The following is an example request:

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

In the example:

  • dispute_id in the endpoint URL identifies the dispute being accepted.

  • access_token in the Authorization header identifies the seller who is responsible for managing the dispute.

When the seller accepts the dispute, Square debits the disputed amount from the balance of their Square account. If their Square account balance does not have sufficient funds, Square debits the funds from their associated bank account. The following is a sample response:

{
   "dispute":{
      "id":"ORSEVtZAJxb37RA1EiGw",
      "amount_money":{
         "amount":100,
         "currency":"USD"
      },
      "reason":"DUPLICATE",
      "state":"ACCEPTED",
      "due_at":"2019-06-03T00:00:00.000Z",
      "disputed_payments":[
         {
            "payment_id":"0dG0pUTlY5bYMr2CJbttiLByvaB"
         }
      ],
      "card_brand":"american_express",
      "created_at":"2019-05-21T17:45:16.284Z",
      "updated_at":"2019-05-21T23:07:13.782Z",
      "brand_dispute_id":"100000294534",
      "reported_at":"2019-05-20T00:00:00.000Z",
      "version":2
   }
}

The state value ACCEPTED indicates that the seller has accepted the dispute.

Step 4: (optional) Challenge the dispute Permalink Get a link to this section

When uploading evidence, you provide both the evidence and the evidence type. You can:

  • Provide general evidence and dispute-specific evidence (addressing the cardholder’s specific claim). General evidence refers to information that the card networks find important regardless of the dispute reason.

  • Upload evidence as a file (CreateDisputeEvidenceFile) or a string (CreateDisputeEvidenceText). For example, you might upload a PDF file of an email thread with the customer as evidence or you might upload a shipment tracking number directly in the request body.

    Square supports these file types: image/tiff, application/pdf, image/jpeg, image/png, and image/heif. The file you upload can be up to 5 MB in size.

    Each piece of evidence text must be uploaded individually using the CreateDisputeEvidenceText request.

In this example, upload the following three pieces of evidence:

  • Two pieces of general evidence. This includes:

    • An email from the customer that shows the customer ordered the item twice. You upload this evidence as samplePDF.pdf and choose cardholder_communication as the evidence_type.

    • An explanation that the customer ordered the item twice and therefore the cardholder dispute is invalid. You upload this evidence as a string “The customer ordered the item twice; on date 1-and date-2” and choose rebuttal_explanation as the evidence_type.

  • One piece of dispute-specific evidence. The dispute reason in this example is DUPLICATE because the cardholder claims they were charged twice for the same purchase. Assume you have two separate receipts as evidence. Upload the receipt images as a PDF file (evidence_won.pdf) and specify duplicate_charge_documentation as the suitable evidence_type.

Step 4.1: Upload evidence file Permalink Get a link to this section

Call CreateDisputeEvidenceFile to upload the samplePDF.pdf file with cardholder_communication as the evidence_type.

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

The following is an example response:

{
   "evidence":{
      "id":"Ri6eRTG3xjT0nnUfN0SoQ",
      "dispute_id":"xe8rb2X4ifCcWd1xIjuaKB",
      "evidence_file":{
         "filename":"samplePDF.pdf",
         "filetype":"application/pdf"
      },
      "uploaded_at":"2019-12-23T02:24:58.000Z"
   }
}

Step 4.2: Upload evidence text Permalink Get a link to this section

Call CreateDisputeEvidenceText to upload the string "The customer ordered the item twice; on date-1 and date-2" with REBUTTAL_EXPLANATION as the evidence_type.

Create Dispute Evidence Text
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
curl https://connect.squareupsandbox.com/v2/disputes/DISPUTE_ID/evidence-text \
  -X POST \
  -H 'Square-Version: 2021-10-20' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "idempotency_key": "general_2_string",
    "evidence_type": "REBUTTAL_EXPLANATION",
    "evidence_text": "The customer ordered the item twice; on date-1 and date-2"
  }'

The following is an example response:

{
   "evidence":{
      "id":"ny5BJ2JvzHZlNIReqkJAzC",
      "dispute_id":"QQa9GkoZNFhBKPYWYgRq4B",
      "evidence_text": "the customer ordered the item twice; on date-1 and date-2",
      "uploaded_at":"2020-01-07T17:52:35.000Z"
   }
}

Step 4.3: Upload another evidence file Permalink Get a link to this section

Call CreateDisputeEvidenceFile to upload the evidence_won.pdf file with duplicate_charge_documentation as the evidence_type.

Create Dispute Evidence File
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
curl https://connect.squareupsandbox.com/v2/disputes/DISPUTE_ID/evidence-files \
  -X POST \
  -H 'Square-Version: 2021-10-20' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Accept: application/json' \
  -F 'file=@/path/to/file/evidence_won.pdf' \
  -F 'request={
    "idempotency_key": "dispute_reason_specific_1",
    "content_type": "application/pdf",
    "evidence_type": "DUPLICATE_CHARGE_DOCUMENTATION"
  }'

The following is an example response:

{
   "evidence":{
      "id":"WKoZd9VlUEZSfI6Q4lu0cD",
      "dispute_id":"xe8rb2X4ifCcWd1xIjuaKB",
      "evidence_file":{
         "filename":"evidence_won.pdf",
         "filetype":"application/pdf"
      },
      "uploaded_at":"2019-12-23T02:40:01.000Z"
   }
}

Step 4.4: Submit the evidence Permalink Get a link to this section

Call the SubmitEvidence endpoint to submit all the evidence to Square.

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

The following is an example response:

{
   "dispute":{
      "id":"xe8rb2X4ifCcWd1xIjuaKB",
      "amount_money":{
         "amount":8803,
         "currency":"USD"
      },
      "reason":"DUPLICATE",
      "state":"PROCESSING",
      "due_at":"2019-12-30T00:00:00.000Z",
      "disputed_payment":{
         "payment_id":"0dG0pUTlY5bYMr2CJbttiLByvaB"
      },
      "card_brand":"VISA",
      "created_at":"2019-12-16T01:21:59.983Z",
      "updated_at":"2019-12-23T02:41:34.969Z",
      "brand_dispute_id":"6rjByNRfR5OpFZeJs_PNKw",
      "reported_at":"2019-12-16T00:00:00.000Z",
      "version":4,
      "location_id":"S8GWD5R9QB376"
   }
}

After submitting all evidence, the bank determines who won the dispute and notifies Square. Square then sets the state of the dispute to either WON or LOST.

Did you know?

In the Square Sandbox, a dispute is WON by setting the name of the last piece of uploaded evidence file to evidence_won.pdf. There is no actual bank in the Sandbox to make a judgment in favor of the seller (WON) or the card holder (LOST) .

Step 5: Verify dispute state Permalink Get a link to this section

Listen for the dispute.state.updated webhook notification which is sent when the state of the dispute changes. In production, your application should not immediately poll the RetrieveDispute endpoint because the bank may not make a judgment on the dispute for several days.

If you want your application to do limited polling of the Disputes API for a new dispute state, call RetrieveDispute and verify the dispute state.

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

The following is an example response:

{
   "type":"dispute",
   "id":"xe8rb2X4ifCcWd1xIjuaKB",
   "object":{
      "amount_money":{
         "amount":8803,
         "currency":"USD"
      },
      "brand_dispute_id":"6rjByNRfR5OpFZeJs_PNKw",
      "card_brand":"VISA",
      "created_at":"2019-12-16T01:21:59.983Z",
      "id":"xe8rb2X4ifCcWd1xIjuaKB",
      "disputed_payment":{
         "payment_id":"0dG0pUTlY5bYMr2CJbttiLByvaB"
      },
      "due_at":"2019-12-30T00:00:00.000Z",
      "location_id":"S8GWD5R9QB376",
      "reason":"DUPLICATE",
      "reported_at":"2019-12-16T00:00:00.000Z",
      "state":"WON",
      "updated_at":"2019-12-23T02:41:38.024Z",
      "version":5
   }
}

The response shows the dispute state as WON. If you configured webhooks, you get a notification with the same information.