Integrate with the Disputes API

Merchants can integrate directly with the Disputes API to scale their disputes process and integrate with other order management and customer service tools. This is helpful for merchants who handle a high volume of transactions.

ActionEndpointPurpose
Receive disputeGET /v2/disputes/{dispute_id}Get detailed information about a dispute.
List disputes/v2/disputesList disputes based on a set of criteria.
Accept dispute/v2/disputes/{dispute_id}/acceptAccept a dispute case.
Respond to disputePOST /v2/disputes/{dispute_id}Submit evidence to respond to a dispute.
Upload file/v2/disputes/filesUpload a file for a dispute.
Retrieve file/v2/disputes/files/{id}Retrieve a file for a dispute.

Dispute notifications

Cash App Afterpay notifies merchants using webhooks when a dispute is created and any time it is updated. Cash App Afterpay expects the ACK (acknowledgement) with a 200 response. If the acknowledgement fails, Cash App Afterpay will reattempt sending the webhook a few times with exponential backoff.

The following table outlines the content for the webhook call:

Field nameData typeDescription
webhook_event_idStringThe event_id of the webhook.
webhook_event_typeStringAn enum variable that indicates if the dispute was created or updated. Possible values are created and updated
dispute_idStringDispute Identifier.
merchant_referenceStringMerchant identifier.

A dispute_id is passed in the webhook call. Merchants can use the Get Dispute endpoint to get the details for the dispute.

Notification setup

Merchants must provide a webhook URL and merchant IDs to the Cash App Afterpay merchant service/dispute team to get the HMAC key and enable the notification.

The webhook endpoint should be maintained by merchants or partners, it should allow POST requests with content-type = application/json.

The payload format is defined in the previous table.

Notification authentication

HMAC signature

Cash App Afterpay recommends that you use HMAC for the authentication of the webhook notification. Consider the following structure of the raw HTTP message.

1POST ${notification_uri} HTTP/1.1
2Host: ${notification_base_url}
3X-Afterpay-Request-Date: 1664239810
4X-Afterpay-Request-Signature: ${signature}
5Content-Type: application/json
6{
7 "webhook_event_id": "b4df2187-4090-4845-be15-a73546107cbe",
8 "webhook_event_type": "created",
9 "dispute_id": "dp_KvGaECApCMdsH8earUSa2V",
10 "merchant_reference": "08CF65ZSFNHVM"
11}

There will be two extra fields for authentication.

  • X-Afterpay-Request-Date records the send time for the webhook request. We recommned aborting the stale notification after a fixed time (if you receive the webhook and current timestamp - ${X-Afterpay-Request-Date} is greater than 5 minutes).

  • X-Afterpay-Request-Signature records the signature of the HMAC key. Typically we generate the signature using the following steps:

    1PAYLOAD={"webhook_event_id": "b4df2187-4090-4845-be15-a73546107cbe", "webhook_event_type": "created", "dispute_id": "dp_KvGaECApCMdsH8earUSa2V", "merchant_reference": "08CF65ZSFNHVM"}
    2URL= "${partner_notification_uri}"
    3SECRET=<hmac secret key here>
    4TIME=1664239810
    5MESSAGE="$URL\n$TIME\n$PAYLOAD"
    6X-Afterpay-Request-Signature=$(printf "${MESSAGE}" | openssl dgst -hmac ${SECRET} -sha256 -binary | base64)

When a merchant or merchant agency receives a webhook notification, we recommend generating verification signatures in following steps.

If HMAC == X-Afterpay-Request-Signature, then continue to process the notification, or the merchant should abort the request.

1PAYLOAD={"webhook_event_id": "b4df2187-4090-4845-be15-a73546107cbe", "webhook_event_type": "created", "dispute_id": "dp_KvGaECApCMdsH8earUSa2V", "merchant_reference": "08CF65ZSFNHVM"}
2URL= "${Notification_uri}"
3SECRET=<hmac secret key here>
4TIME=${X-Afterpay-Request-Date}
5MESSAGE="$URL\n$TIME\n$PAYLOAD"
6HMAC=$(printf "${MESSAGE}" | openssl dgst -hmac ${SECRET} -sha256 -binary | base64)

Series of events

TriggerAPI eventOutcome
The customer creates a dispute in the appWebhook notifies the merchant (incl. webhook_event_type = created and a dispute_id)The dispute is created and the merchant is notified. The dispute status is updated to needs_response.
The merchant retrieves the dispute informationThe Get Dispute endpoint is called to fetch status of the dispute (based on Dispute ID), and returns the updated Dispute object. If images or attachments were supplied; these are retrieved with the Retrieve File api endpoint.The merchant can challenge or accept the dispute.
The merchant challenges the disputeThe merchant collates their response collateral internally. If there are files to upload, the Upload File endpoint is called for the relevant files. The Respond to Dispute endpoint is called which references the file IDs for those files.The merchant has submitted evidence to challenge the dispute. The dispute status is updated to under_review.
The merchant accepts the disputeThe Accept Dispute endpoint is called, returns the Dispute object to the merchant.The dispute status is updated to lost and the dispute is closed. The closing reason is set to merchant_accepted.
The customer accepts the merchant’s evidenceIf webhook is enabled, this will come through as a notificationThe dispute status is updated to ‘won’ and the dispute is closed. The closing reason is set to evidence_accepted.
The customer rejects the merchant’s evidenceThe dispute is sent to Afterpay for adjudication
Afterpay adjudicates in the merchant’s favorIf webhook is enabled, this will come through as a notificationThe dispute status is updated to ‘won’ and the dispute is closed. The closing reason is set to evidence_accepted.
Afterpay adjudicates in the customer’s favorIf webhook is enabled, this will come through as a notificationThe dispute status is updated to lost and the dispute is closed. The closing reason is set to evidence_rejected.
The customer cancels the disputeIf webhook is enabled, this will come through as a notificationThe dispute status is updated to won and the dispute is closed. The closing reason is set to customer_cancelled.
The customer updates the dispute.Webhook notifies merchant (incl. webhook_event_type = updated and a dispute_id) Get Dispute endpoint is called to fetch status of the dispute (based on Dispute ID), returns the updated Dispute object.The dispute status is updated. The dispute status is updated to needs_response.