Skip to navigation

API Integration Quickstart

This guide covers both ways to move money with the Cash App Pay API:

  • Payments: a customer pays a merchant from their Cash App account.
  • Payouts: a merchant sends funds to a customer’s Cash App account.

Both flows use the same setup: create a brand and merchant, then link a customer with a customer request. They differ in the action you request from the customer and the API you call with the resulting grant. If you are only implementing payouts, complete Steps 1 and 2 using the ON_FILE_PAYOUT action, then skip to Create a Payout.

Payouts

Payouts is an early access feature and is only available to Cash App Pay PSP partners. To learn more about payouts, including funding, fees, and settlement, see Payouts.

Before getting started, make sure that you have access to:

  • API credentials and API access
  • Cash App Sandbox App

We recommend reading the following pages:

Integrate with the Cash App Pay API

Step 1: Create a Brand and Merchant

First, create a Brand and associate a Merchant with that brand.

Make these calls from your server. The Network API requires your API key, which is a secret credential. Never expose it in your web frontend or mobile app.

  1. Create a Brand

    curl --location 'https://sandbox.api.cash.app/network/v1/brands' \
    --header 'Authorization: {{api_creds}}' \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --header 'X-Region: PDX' \
    --data '{
    "brand": {
    "name": "Cash App",
    "reference_id": "external-id"
    },
    "idempotency_key": "224841f7-31be-4bc6-b1df-e102a8fa476f"
    }'
  2. Create a Merchant

    curl --location 'https://sandbox.api.cash.app/network/v1/merchants' \
    --header 'Authorization: {{api_creds}}' \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --header 'X-Region: PDX' \
    --data '{
    "merchant": {
    "address": {
    "address_line_1": "1 Market Street",
    "locality": "San Francisco",
    "country": "US",
    "postal_code": "94105",
    "administrative_district_level_1": "CA"
    },
    "name": "Cash App Pay on Market Street",
    "brand_id": "BRAND_bifwxjq70mfk06l9nr6q4q1f9",
    "country": "US",
    "currency": "USD",
    "category": "5500",
    "reference_id": "external-id"
    },
    "idempotency_key": "b12fa940-d07a-48c6-a08a-89511547661f"
    }'

To link a customer, create a customer request, have the customer approve it in Cash App, and save the resulting grants. You can do this by calling the Customer Request API directly, or by using Pay Kit, the Cash App Pay SDK for web, iOS, and Android.

Choose an integration option

OptionRuns inChannelHandles for youYou build
Customer Request API (no SDK)Web, mobile app, POS device, or serverONLINE, IN_APP, IN_PERSONAPI calls onlyQR code or redirect UI, QR code refreshes, and polling or webhooks
Pay Kit WebWeb frontendONLINEButton, QR code, mobile redirect, and pollingA CUSTOMER_REQUEST_APPROVED listener
Pay Kit iOSiOS appIN_APPRequest, redirect, and pollingURL handling, a button, and state handling
Pay Kit AndroidAndroid appIN_APPRequest, redirect, and pollingAn intent filter, a button, and state handling

We recommend Pay Kit for websites and native mobile apps. Call the Customer Request API directly when you:

  • Accept Cash App Pay in person or on a point-of-sale device.
  • Create customer requests from your server.
  • Need full control over the customer experience, or run on a platform that Pay Kit doesn’t support.

Every option authenticates with your client ID only, not your secret API key, so it can run in your web frontend or mobile app. Whichever option you choose, send the approved Grant IDs to your server to create payments or payouts in Step 3.

The examples below show each option in its own tab: API, Web, iOS, and Android.

Create a customer request

Create a customer request with one channel and at least one action.

Available ActionsAvailable Channels
ONE_TIME_PAYMENT
ON_FILE_PAYMENT
ON_FILE_PAYOUT
IN_APP
ONLINE
IN_PERSON

See the list of supported actions and channels here. You can have many actions but only one channel. See Combine actions in one request.

Example - Create Customer Request for Payment

curl --location 'https://sandbox.api.cash.app/customer-request/v1/requests' \
--header 'Authorization: Client {{client_id}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"request": {
"actions": [
{
"amount": 1234,
"currency": "USD",
"scope_id": "{{client_id || brand_id || merchant_id}}",
"type": "ONE_TIME_PAYMENT"
}
],
"reference_id": "external-id",
"channel": "ONLINE"
},
"idempotency_key": "cd8b0b0a-0ffb-478e-ae8f-e31aef666a1a"
}'

Example - Create Customer Request for Payouts

For payouts, use the ON_FILE_PAYOUT action. Its scope_id must be a client ID or brand ID; merchant IDs are not accepted. The resulting grant can be reused for multiple payouts until the customer revokes it.

curl --location 'https://sandbox.api.cash.app/customer-request/v1/requests' \
--header 'Authorization: Client {{client_id}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"request": {
"actions": [
{
"scope_id": "{{client_id || brand_id}}",
"account_reference_id": "external-account-id",
"type": "ON_FILE_PAYOUT"
}
],
"reference_id": "external-id",
"channel": "ONLINE"
},
"idempotency_key": "6f1c2a8e-3b7d-4e59-9a0c-8d2f4b1e7c35"
}'

Combine actions in one request

A customer request can include multiple actions. The customer approves or declines them all at once, so you can collect everything you need in one step. For example, charge a customer for their first order and save their Cash App account for future orders.

Keep the following in mind:

  • Each action has its own scope_id. On-file payment and payout actions must use a brand ID or client ID.
  • Don’t repeat an action type in the same request.
  • When the request is APPROVED, the grants array contains one grant per action. Use each grant’s action.type to match it to the right API call.
  • One-time payment grants are used once. On-file payment and on-file payout grants can be reused until the customer revokes them.
  • Combining ON_FILE_PAYMENT and ON_FILE_PAYOUT in one request is only available to clients that Cash App has enabled for it. Contact the Cash App Pay Partner Engineering team to request access.
Use caseActions
Charge now and save the account for future paymentsONE_TIME_PAYMENT + ON_FILE_PAYMENT
Charge the customer and send them funds laterON_FILE_PAYMENT + ON_FILE_PAYOUT

Example - Create Customer Request with One-Time and On-File Payment

curl --location 'https://sandbox.api.cash.app/customer-request/v1/requests' \
--header 'Authorization: Client {{client_id}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"request": {
"actions": [
{
"amount": 1234,
"currency": "USD",
"scope_id": "{{merchant_id}}",
"type": "ONE_TIME_PAYMENT"
},
{
"scope_id": "{{brand_id}}",
"account_reference_id": "external-account-id",
"type": "ON_FILE_PAYMENT"
}
],
"reference_id": "external-id",
"channel": "ONLINE"
},
"idempotency_key": "3d8a5f2c-7e41-4b9a-a6d0-5c2e9f1b8a74"
}'

After approval, create the first payment with the ONE_TIME_PAYMENT grant. Store the ON_FILE_PAYMENT grant to create future payments without asking the customer again.

Example - Create Customer Request with On-File Payment and Payout

This request asks the customer for permission to charge their Cash App account and to send funds to it. Your client must be enabled for this combination. Otherwise, the request fails with a FEATURE_DISABLED error.

curl --location 'https://sandbox.api.cash.app/customer-request/v1/requests' \
--header 'Authorization: Client {{client_id}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"request": {
"actions": [
{
"scope_id": "{{brand_id}}",
"account_reference_id": "external-account-id",
"type": "ON_FILE_PAYMENT"
},
{
"scope_id": "{{brand_id}}",
"account_reference_id": "external-account-id",
"type": "ON_FILE_PAYOUT"
}
],
"reference_id": "external-id",
"channel": "ONLINE"
},
"idempotency_key": "8b2f6d14-9c3e-4a75-b1e8-0d7a4c5f2e96"
}'

After approval, store both grants. Use the ON_FILE_PAYMENT grant with Create payment and the ON_FILE_PAYOUT grant with Create payout.

Get approval and save the grants

If you call the Customer Request API directly:

  • Save the Request ID and the URLs in the auth_flow_triggers object of the response. These include the QR code URL, mobile URL, and desktop URL that send the customer to Cash App.
  • Send the customer to Cash App to approve the request:
    • Desktop web: render the QR code yourself, using the image at qr_code_image_url (PNG) or qr_code_svg_url (SVG). The QR code rotates and expires, so replace it with the latest URL before the refreshes_at time. See Listen for updates to the customer request for how to get the latest QR code.
    • Mobile web or native app: redirect the customer to mobile_url.
  • Listen for updates to the customer request. When the request enters the APPROVED state, stop polling.

If you use Pay Kit, it polls for you and returns the grants when the customer approves: in the .approved state on iOS, the Approved state on Android, or the CUSTOMER_REQUEST_APPROVED event on the web.

Save the Grant IDs listed in the grants array to create a payment or payout later.

To test the customer request, you can use the Sandbox App or Sandbox Web to scan and approve the request. See more at Sandbox App and Developer Sandbox.

Listen for updates to the customer request

This section applies only when you call the Customer Request API directly, as in the API tabs above. Pay Kit on web, iOS, and Android handles polling and QR code refreshes for you.

You can listen for updates to the customer request in two ways:

  • Polling (recommended): Call retrieve customer request repeatedly (ideally once per second or more frequently).
  • Webhooks: Subscribe to the customer_request.state.updated event.

QR codes rotate every 30 seconds and expire every 60 seconds, so you must get the latest QR code. This will change based on how you listen for customer request updates:

  • If you are using polling, set the image tag’s URL to the latest QR code that is returned after each polling response. Since you poll more frequently than QR codes rotate, you don’t need to keep track of the refreshes_at value.
  • If using webhook, there is no webhook event for QR code rotation. Instead, you should fetch the latest customer request once the current timestamp is after the refreshes_at value. The auth flow triggers will contain the newest, valid QR code.

Example - Retrieve Customer Request

curl --location --globoff 'https://sandbox.api.cash.app/customer-request/v1/requests/{{customer_request_id}}' \
--header 'Authorization: Client {{client_id}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json'

Step 3: Create a Payment or Payout

Make these calls from your server. Like Step 1, the Network API requires your API key, which is a secret credential. If you use Pay Kit, send the Grant IDs from your web frontend or mobile app to your server, and create the payment or payout there.

Use the Grant ID and Merchant ID from the previous steps to create a payment, a payout, or both, depending on your integration.

Create a Payment

Create a payment with the Create a payment request endpoint. You can use void, capture, or refund actions depending on the state of the payment.

We use magic values in the amount field to determine outcomes for payments in the sandbox environment. You can use any amount, but these amounts will result in specific outcomes.

Example - Create Payment

curl --location 'https://sandbox.api.cash.app/network/v1/payments' \
--header 'Authorization: {{api_creds}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Region: PDX' \
--data '{
"payment": {
"capture": true,
"amount": 1234,
"currency": "USD",
"merchant_id": "{{merchant_id}}",
"grant_id": "{{grant_id}}",
"reference_id": "external-id"
},
"idempotency_key": "2a77b3a5-9104-4587-9517-53ac5d968f25"
}'

Create a Payout

Create a payout with the Create payout endpoint, using the grant from your ON_FILE_PAYOUT customer request.

Example - Create Payout

curl --location 'https://sandbox.api.cash.app/network/v1/payouts' \
--header 'Authorization: {{api_creds}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Region: PDX' \
--data '{
"payout": {
"capture": true,
"amount": 1500,
"currency": "USD",
"merchant_id": "{{merchant_id}}",
"grant_id": "{{grant_id}}",
"purpose": "SERVICES",
"note": "Payment for consulting services",
"reference_id": "external-id"
},
"idempotency_key": "9c4e7b21-5a3f-4d86-b0e2-7f1a6c9d3e48"
}'

To learn more about payouts, including request validation, statuses, funding, sandbox testing, and failure codes, see Payouts.

Notes

Pay Kit SDK

Pay Kit is the name of the Cash App Pay SDK. This SDK specifically handles linking a Customer to a Merchant and uses the Customer Request API underneath. Instead of using the SDK, you can call the APIs directly as described in the steps to integrate with the Cash App Pay API above. To know more about our SDK, see Pay Kit.

Signatures

Cash App Pay Network API and Management API require that all requests be signed. However, when using Sandbox, you can skip this by setting x-signature to the value sandbox:skip-signature-check. Use these Magic Values to control the behavior in Sandbox and to produce preset outcomes.