Webhooks: Steps

Step 1: Create a Webhook Endpoint To Subscribe to Cash App Pay Webhook Events

The webhook endpoint URL must expect JSON data from a POST request and confirm the successful receipt of that data. To subscribe to our webhook events see Create a webhook endpoint. For a list of all Cash App Pay API events that you can subscribe to, see event_type under List Webhook Events.

The webhook endpoint must do the following:

  • Receive a POST event notification.
  • Respond with a 2xx HTTP status within the specified delivery_timeout (default 5 seconds).
  • Accept HTTPS connections.
  • Store the event notification data safely.
  • Use the event_id field in the body of each event notification as an idempotency value. Your application should ignore any duplicate values.
  • Use message versioning. If your application passes Cash App Pay event data to another application, you should add versioning to the data to avoid duplication and to make auditing of the data transfer easier.

You can use a server endpoint as a webhook endpoint URL or you can create a serverless endpoint on services such as Amazon Web Services (AWS) or Google Cloud Platform. You can test a webhook endpoint URL with websites such as https://webhook.site.

Format of an event notification

The following headers are included when making a POST request to the webhook endpoint to deliver the webhook event:

HeaderValueDescriptionExample
Accept*/*This standard header ensures that the API client and Cash App Pay API are communicating using the same MIME type in the response payload.*/*
Accept-EncodinggzipThe Accept-Encoding request HTTP header indicates the content encoding (usually a compression algorithm) that the client can understandgzip `
AuthorizationClient {CLIENT_ID} {KEY_ID}This standard header is used to authenticate your API client with theClient CA-CI_CLIENT KEY_2f6cd0d5cc26b34ac878502
Content-Typeapplication/json; charset=utf-8This standard header ensures that the API client and Cash App Pay API are communicating using the same MIME type in the request payloadapplication/json; charset=utf-8
Date{DATETIME_IN_RFC_1123_FORMAT}Contains the date and time at which the message originated.Sun, 21 Oct 2018 12:16:24 GMT
Host{DOMAIN_OF_ENDPOINT_URL}Specifies the host and port number of the server to which the request is being sent.api.cash.app
X-Retry-Count{NUMBER_OF_RETRIES}The number of times Cash App Pay has resent a notification for the given event (including the current retry) as an integer. The retry number does not include the original notification and is only present when there has been at least one unsuccessful delivery.3
X-Signed-HeadersAccept: */*, Content-Type: application/json; charset=utf-8, Host: {DOMAIN_OF_ENDPOINT_URL}, Authorization: Client {CLIENT_ID} {KEY_ID}The headers used to generate the X-Signature.Accept: */*, Content-Type: application/json; charset=utf-8, Host: api.cash.app, Authorization: Client CA-CI_CLIENT KEY_2f6cd0d5cc26b34ac878502
X-SignatureV1 hash({METHOD}\n{URL_PATH}\n{HEADERS}\n{BODY_DIGEST}) An HMAC-SHA-256 signature used to validate the event authenticity. See more at X-Signature header.V1 2bc29db277b0e2949f478691d33fe1f535a9832da90037a853ebb9d4a351cc1b
X-Delivery-Configuration-Id{WEBHOOK_ENDPOINT_ID} The Cash App Pay-provided ID of the webhook endpoint. This is returned when calling the Create Webhook Endpoint API.WC_2f6cd0d5cc26b34ac8785026b14979

Webhook signatures: Webhook deliveries also contain an X-Signature header that is computed using the same process as signing regular requests. This allows webhooks delivered by Cash App to be validated by computing the signature from the request payload and verifying that it matches the X-Signature header. See Signing Requests for more details.

The body of the webhook event has the following JSON schema:

FieldDescriptionExample
typeThe type of event that occurred.merchant.status.updated
event_idA unique identifier provided by Cash App for the event.WE_78lusoltpu8r9shziq5hdnx96
created_atWhen this event occurred in RFC 3339 format (UTC).The time that the event is delivered may be significantly later than this timestamp due to webhooks being retried for up to 72 hours.2022-12-07T20:21:46.282Z
dataThe data about the object that has a status change.See the next table for the attributes of the data object.

The event’s data object contains the following attributes:

FieldDescriptionExample
typeThe name of the affected object’s type.merchant
idThe ID of the affected object.MMI_4vxs5egfk7hmta3qx2h6rp91x
objectA JSON object containing the affected object’s data relevant to the event.See example code below

Example code for the object

1{
2 "id": "MMI_4vxs5egfk7hmta3qx2h6rp91x",
3 "brand_id": "BRAND_8ereg0tug2yiik8vx24xpe5br",
4 "name": "Example Business Name",
5 "country": "US",
6 "currency": "USD",
7 "category": "5432",
8 "reference_id": "external-id",
9 "status": "ACTIVE",
10 "created_at": "2022-01-01T12:00:00Z",
11 "updated_at": "2022-01-05T12:00:00Z",
12 "address": {
13 "address_line_1": "1215 4th Ave",
14 "address_line_2": "Suite 2300",
15 "locality": "Seattle",
16 "country": "US",
17 "postal_code": "98161-1001",
18 "administrative_district_level_1": "Washington"
19 },
20 "site_url": "http://example.com",
21 "metadata": {}
22}

Example code for event notification body

1{
2 "type": "merchant.status.updated",
3 "event_id": "WE_78lusoltpu8r9shziq5hdnx96",
4 "created_at": "2022-12-07T20:21:46.282Z",
5 "data": {
6 "id": "MMI_4vxs5egfk7hmta3qx2h6rp91x",
7 "object": {
8 "id": "MMI_4vxs5egfk7hmta3qx2h6rp91x",
9 "brand_id": "BRAND_8ereg0tug2yiik8vx24xpe5br",
10 "name": "Example Business Name",
11 "country": "US",
12 "currency": "USD",
13 "category": "5432",
14 "reference_id": "external-id",
15 "status": "ACTIVE",
16 "created_at": "2022-01-01T12:00:00Z",
17 "updated_at": "2022-01-05T12:00:00Z",
18 "address": {
19 "address_line_1": "1215 4th Ave",
20 "address_line_2": "Suite 2300",
21 "locality": "Seattle",
22 "country": "US",
23 "postal_code": "98161-1001",
24 "administrative_district_level_1": "Washington"
25 },
26 "site_url": "http://example.com",
27 "metadata": {}
28 },
29 "type": "merchant"
30 }
31}


Step 2: Verify and Validate Event Notifications in Sandbox

You can test webhook endpoints in our Sandbox environments both on an App and on the web. Go to the following links to learn more:

Step 3: Manage Webhook Operations

There are two aspects of Cash App Pay webhook events that you must understand:

  • When are events triggered?
  • How to manage event notifications?

For a list of all Cash App Pay API events that you can subscribe to, see event_type under List webhook events.

Understand when events are triggered

Events that you can subscribe to using webhooks are generated by the various Cash App Pay applications and APIs. For example, during a sales transaction, several events could be generated including an updated payment received, customer created, grant declined, etc.

Manage event notifications

When your webhook endpoint URL receives an event notification, you must respond within the specified delivery timeout (or default 5 seconds) to the POST and store the event information securely.

Cloud-based serverless applications, microservices, and function as a service (FaaS) applications let you handle event notifications without setting up a server.

Step 4: Move Webhook Event Notifications to Production

When your application is ready to be moved from the Sandbox environment to production, there are several tasks you must complete to manage webhook event notifications in production. These include the following:

  • Get production application credentials from the Cash App Pay Partner Engineering team.

    The base URL for calling Sandbox endpoints is sandbox.api.cash.app. When you move your application to production, you need production credentials and you must use api.cash.app as the base URL.

  • Update API calls to use the new credentials. Update your code to make API calls to Cash App Pay production endpoints.
  • Use the event_id field in the body of each event notification as an idempotency value. Your application should ignore any duplicate values.
  • Use message versioning. If your application passes Cash App Pay data to another application, you should add versioning to the data before passing it to avoid duplication and to make auditing of the data transfer easier.
  • Validate the webhook event notification. A non-Cash App Pay POST can potentially compromise your application. All webhook notifications from Cash App Pay include an X-Signed-Headers and X-Signature header. See Signing Requests for more information.

Handling a deleted customer webhook

The customer.deleted webhook event is delivered when a Cash App customer account is deleted. This operation is often related to requests to forget a customer’s data (for example, CCPA/GDPR), so that the customer data in the webhook event does not contain any data that the customer provided (for example, a Cashtag). Since the customer reference ID is provided by the API client, not the customer, any reference ID previously attached to the customer will be included in the webhook event data.

When a customer account is deleted, all active grants for that customer are automatically revoked. Any future attempts to use grants associated with that customer will fail. Any attempt to retrieve the customer through the API will return a CUSTOMER_DELETED_ACCOUNT error.

As a best practice, when they receive a deleted customer webhook event, developers must delete any customer PII associated with the Cash App customer that was deleted.