> This page is for Cash App Pay Partner API.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.cash.app/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.cash.app/_mcp/server.

# 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](#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](/cash-app-pay-partner-api/guides/technical-guides/payouts/about).

> **Note**
>
> 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:
>
> * [Cash App Pay Integration Basics](/cash-app-pay-partner-api/guides/technical-guides/cash-app-pay-integration-basics)
> * [Making Requests](/cash-app-pay-partner-api/guides/technical-guides/api-fundamentals/requests/making-requests)
> * [Sandbox App](/cash-app-pay-partner-api/guides/technical-guides/sandbox/sandbox-app)

## 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.

> **Warning**
>
> 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](/cash-app-pay-partner-api/api-reference/network-api/create-brand)
   ```curl
   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](/cash-app-pay-partner-api/api-reference/network-api/create-merchant)

   ```curl
   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"
    }'
   ```

### Step 2: Link a Customer to the Merchant, Brand, or Client

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

| Option                                                                                               | Runs in                                | Channel                         | Handles for you                               | You build                                                          |
| ---------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------------------------- | --------------------------------------------- | ------------------------------------------------------------------ |
| **Customer Request API** (no SDK)                                                                    | Web, mobile app, POS device, or server | `ONLINE`, `IN_APP`, `IN_PERSON` | API calls only                                | QR code or redirect UI, QR code refreshes, and polling or webhooks |
| **[Pay Kit Web](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-web-overview/getting-started)** | Web frontend                           | `ONLINE`                        | Button, QR code, mobile redirect, and polling | A `CUSTOMER_REQUEST_APPROVED` listener                             |
| **[Pay Kit iOS](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-i-os/getting-started)**         | iOS app                                | `IN_APP`                        | Request, redirect, and polling                | URL handling, a button, and state handling                         |
| **[Pay Kit Android](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-android/getting-started)**  | Android app                            | `IN_APP`                        | Request, redirect, and polling                | An 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.

> **Note**
>
> 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 Actions                                       | Available Channels              |
| ------------------------------------------------------- | ------------------------------- |
| `ONE_TIME_PAYMENT`  `ON_FILE_PAYMENT`  `ON_FILE_PAYOUT` | `IN_APP`  `ONLINE`  `IN_PERSON` |

> **Note**
>
> See the list of supported actions and channels [here](/cash-app-pay-partner-api/api-reference/customer-request-api/create-request). You can have many actions but only one channel. See [Combine actions in one request](#combine-actions-in-one-request).

**Example - Create Customer Request for Payment**

#### API

```curl
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"
}'
```

#### Web

Requires [Pay Kit Web](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-web-overview/getting-started). Load the Pay Kit script from the Cash App CDN; it can't be bundled into your app.

```html
<div id="cash-app-pay"><!-- Pay Kit renders the Cash App Pay button here --></div>

<script src="https://sandbox.kit.cash.app/v1/pay.js"></script>
<script type="module">
    const pay = await window.CashApp.pay({ clientId: 'YOUR_CLIENT_ID' });

    pay.addEventListener('CUSTOMER_REQUEST_APPROVED', ({ grants }) => {
        // Send the Grant ID to your backend to create a payment.
        const grantId = grants.payment.grantId;
    });

    await pay.render('#cash-app-pay');

    await pay.customerRequest({
        referenceId: 'external-id',
        redirectURL: window.location.href,
        actions: {
            payment: {
                amount: { currency: 'USD', value: 1234 },
                scopeId: 'YOUR_MERCHANT_ID',
            },
        },
    });
</script>
```

For full setup, events, and customization, see [Pay Kit Web: Getting Started](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-web-overview/getting-started).

#### iOS

Requires the [Pay Kit iOS SDK](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-i-os/getting-started). You must also register a URL scheme and post `CashAppPay.RedirectNotification` when Cash App returns the customer to your app. See [Implement URL handling](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-i-os/getting-started#step-2-implement-url-handling).

This example creates a one-time payment request, authorizes it when the customer taps your Cash App Pay button, and collects the Grant IDs to send to your backend.

```swift
import PayKit
import UIKit

final class CheckoutViewController: UIViewController, CashAppPayObserver {
    // Retain the SDK, or you will not receive state changes.
    private lazy var sdk: CashAppPay = {
        let sdk = CashAppPay(clientID: "YOUR_CLIENT_ID", endpoint: .sandbox)
        sdk.addObserver(self)
        return sdk
    }()

    private var customerRequest: CustomerRequest?

    override func viewDidLoad() {
        super.viewDidLoad()

        sdk.createCustomerRequest(
            params: CreateCustomerRequestParams(
                actions: [
                    .oneTimePayment(
                        scopeID: "YOUR_BRAND_ID",
                        money: Money(amount: 1234, currency: .USD)
                    )
                ],
                channel: .IN_APP,
                redirectURL: URL(string: "yourapp://callback")!,
                referenceID: "external-id",
                metadata: nil
            )
        )
    }

    // Call this when the customer taps your Cash App Pay button.
    @objc func cashAppPayButtonTapped() {
        guard let customerRequest else { return }
        sdk.authorizeCustomerRequest(customerRequest)
    }

    func stateDidChange(to state: CashAppPayState) {
        switch state {
        case let .readyToAuthorize(request):
            // Save the request and enable your Cash App Pay button.
            customerRequest = request
        case let .approved(request: _, grants: grants):
            // Send the Grant IDs to your backend to create a payment or payout.
            let grantIDs = grants.map(\.id)
            print("Approved grants: \(grantIDs)")
        case .declined:
            // The request is terminal. Let the customer start over or choose another payment method.
            customerRequest = nil
        default:
            break
        }
    }
}
```

For full setup, states, and error handling, see [Pay Kit iOS: Getting Started](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-i-os/getting-started).

#### Android

Requires the [Pay Kit Android SDK](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-android/getting-started). You must also declare an intent filter for your redirect URI so Cash App can return the customer to your app. See [Handling Deep Linking](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-android/getting-started#step-4-handling-deep-linking).

This example creates a one-time payment request, authorizes it when the customer taps your Cash App Pay button, and collects the Grant IDs to send to your backend.

```kotlin
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import app.cash.paykit.core.CashAppPay
import app.cash.paykit.core.CashAppPayFactory
import app.cash.paykit.core.CashAppPayListener
import app.cash.paykit.core.CashAppPayState
import app.cash.paykit.core.models.sdk.CashAppPayAction.OneTimeAction
import app.cash.paykit.core.models.sdk.CashAppPayCurrency
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class CheckoutActivity : AppCompatActivity(), CashAppPayListener {
    private val cashAppPay: CashAppPay = CashAppPayFactory.createSandbox("YOUR_CLIENT_ID")
    private val redirectUri = "yourapp://checkout"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        cashAppPay.registerForStateUpdates(this)

        val action = OneTimeAction(
            currency = CashAppPayCurrency.USD,
            amount = 1234,
            scopeId = "YOUR_BRAND_ID",
        )

        // createCustomerRequest makes a blocking network call, so run it off the main thread.
        lifecycleScope.launch(Dispatchers.IO) {
            cashAppPay.createCustomerRequest(action, redirectUri, referenceId = "external-id")
        }
    }

    // Call this when the customer taps your Cash App Pay button.
    private fun onCashAppPayButtonClicked() {
        cashAppPay.authorizeCustomerRequest()
    }

    override fun cashAppPayStateDidChange(newState: CashAppPayState) {
        when (newState) {
            is CashAppPayState.ReadyToAuthorize -> {
                // Enable your Cash App Pay button.
            }
            is CashAppPayState.Approved -> {
                // Send the Grant IDs to your backend to create a payment or payout.
                val grantIds = newState.responseData.grants.orEmpty().map { it.id }
            }
            is CashAppPayState.Declined -> {
                // The request is terminal. Let the customer start over or choose another payment method.
            }
            is CashAppPayState.CashAppPayExceptionState -> {
                // Hide Cash App Pay and log newState.exception.
            }
            else -> Unit
        }
    }

    override fun onDestroy() {
        cashAppPay.unregisterFromStateUpdates()
        super.onDestroy()
    }
}
```

For full setup, states, and error handling, see [Pay Kit Android: Getting Started](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-android/getting-started).

**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.

#### API

```curl
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"
}'
```

#### Web

This example uses the `pay` instance and event listener from the payment example. Pay Kit Web requires `accountReferenceId` for payouts.

```js
pay.addEventListener('CUSTOMER_REQUEST_APPROVED', ({ grants }) => {
    // Send grants.onFilePayout.grantId to your backend
    // to create payouts.
});

await pay.customerRequest({
    referenceId: 'external-id',
    redirectURL: window.location.href,
    actions: {
        onFilePayout: {
            scopeId: 'YOUR_BRAND_ID',
            accountReferenceId: 'external-account-id',
        },
    },
});
```

#### iOS

This example uses the `sdk` from the payment example. `onFilePayout` requires Pay Kit iOS 1.0.0 or later.

```swift
sdk.createCustomerRequest(
    params: CreateCustomerRequestParams(
        actions: [
            .onFilePayout(
                scopeID: "YOUR_BRAND_ID",
                accountReferenceID: "external-account-id"
            )
        ],
        channel: .IN_APP,
        redirectURL: URL(string: "yourapp://callback")!,
        referenceID: "external-id",
        metadata: nil
    )
)
```

#### Android

This example uses the `cashAppPay` instance from the payment example. Call `createCustomerRequest` off the main thread. `OnFilePayoutAction` requires Pay Kit Android 3.0.0 or later.

```kotlin
import app.cash.paykit.core.models.sdk.CashAppPayAction.OnFilePayoutAction

val action = OnFilePayoutAction(
    scopeId = "YOUR_BRAND_ID",
    accountReferenceId = "external-account-id",
)

lifecycleScope.launch(Dispatchers.IO) {
    cashAppPay.createCustomerRequest(action, redirectUri, referenceId = "external-id")
}
```

#### 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 case                                            | Actions                                |
| --------------------------------------------------- | -------------------------------------- |
| Charge now and save the account for future payments | `ONE_TIME_PAYMENT` + `ON_FILE_PAYMENT` |
| Charge the customer and send them funds later       | `ON_FILE_PAYMENT` + `ON_FILE_PAYOUT`   |

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

#### API

```curl
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"
}'
```

#### Web

This example uses the `pay` instance and event listener from the payment example.

```js
pay.addEventListener('CUSTOMER_REQUEST_APPROVED', ({ grants }) => {
    // Send both Grant IDs to your backend:
    // grants.payment.grantId and grants.onFile.grantId
});

await pay.customerRequest({
    referenceId: 'external-id',
    redirectURL: window.location.href,
    actions: {
        payment: {
            amount: { currency: 'USD', value: 1234 },
            scopeId: 'YOUR_MERCHANT_ID',
        },
        onFile: {
            scopeId: 'YOUR_BRAND_ID',
            accountReferenceId: 'external-account-id',
        },
    },
});
```

#### iOS

This example uses the `sdk` from the payment example.

```swift
sdk.createCustomerRequest(
    params: CreateCustomerRequestParams(
        actions: [
            .oneTimePayment(
                scopeID: "YOUR_MERCHANT_ID",
                money: Money(amount: 1234, currency: .USD)
            ),
            .onFilePayment(
                scopeID: "YOUR_BRAND_ID",
                accountReferenceID: "external-account-id"
            )
        ],
        channel: .IN_APP,
        redirectURL: URL(string: "yourapp://callback")!,
        referenceID: "external-id",
        metadata: nil
    )
)
```

#### Android

This example uses the `cashAppPay` instance from the payment example. Call `createCustomerRequest` off the main thread.

```kotlin
import app.cash.paykit.core.models.sdk.CashAppPayAction.OnFileAction
import app.cash.paykit.core.models.sdk.CashAppPayAction.OneTimeAction
import app.cash.paykit.core.models.sdk.CashAppPayCurrency

val actions = listOf(
    OneTimeAction(
        currency = CashAppPayCurrency.USD,
        amount = 1234,
        scopeId = "YOUR_MERCHANT_ID",
    ),
    OnFileAction(
        scopeId = "YOUR_BRAND_ID",
        accountReferenceId = "external-account-id",
    ),
)

lifecycleScope.launch(Dispatchers.IO) {
    cashAppPay.createCustomerRequest(actions, redirectUri, referenceId = "external-id")
}
```

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`](/cash-app-pay-partner-api/guides/technical-guides/api-fundamentals/errors/error-code-reference#FEATURE_DISABLED) error.

#### API

```curl
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"
}'
```

#### Web

This example uses the `pay` instance and event listener from the payment example.

```js
pay.addEventListener('CUSTOMER_REQUEST_APPROVED', ({ grants }) => {
    // Send both Grant IDs to your backend:
    // grants.onFile.grantId and grants.onFilePayout.grantId
});

await pay.customerRequest({
    referenceId: 'external-id',
    redirectURL: window.location.href,
    actions: {
        onFile: {
            scopeId: 'YOUR_BRAND_ID',
            accountReferenceId: 'external-account-id',
        },
        onFilePayout: {
            scopeId: 'YOUR_BRAND_ID',
            accountReferenceId: 'external-account-id',
        },
    },
});
```

#### iOS

This example uses the `sdk` from the payment example.

```swift
sdk.createCustomerRequest(
    params: CreateCustomerRequestParams(
        actions: [
            .onFilePayment(
                scopeID: "YOUR_BRAND_ID",
                accountReferenceID: "external-account-id"
            ),
            .onFilePayout(
                scopeID: "YOUR_BRAND_ID",
                accountReferenceID: "external-account-id"
            )
        ],
        channel: .IN_APP,
        redirectURL: URL(string: "yourapp://callback")!,
        referenceID: "external-id",
        metadata: nil
    )
)
```

#### Android

This example uses the `cashAppPay` instance from the payment example. Call `createCustomerRequest` off the main thread. `OnFilePayoutAction` requires Pay Kit Android 3.0.0 or later.

```kotlin
import app.cash.paykit.core.models.sdk.CashAppPayAction.OnFileAction
import app.cash.paykit.core.models.sdk.CashAppPayAction.OnFilePayoutAction

val actions = listOf(
    OnFileAction(
        scopeId = "YOUR_BRAND_ID",
        accountReferenceId = "external-account-id",
    ),
    OnFilePayoutAction(
        scopeId = "YOUR_BRAND_ID",
        accountReferenceId = "external-account-id",
    ),
)

lifecycleScope.launch(Dispatchers.IO) {
    cashAppPay.createCustomerRequest(actions, redirectUri, referenceId = "external-id")
}
```

After approval, store both grants. Use the `ON_FILE_PAYMENT` grant with [Create payment](/cash-app-pay-partner-api/api-reference/network-api/create-payment) and the `ON_FILE_PAYOUT` grant with [Create payout](/cash-app-pay-partner-api/api-reference/network-api/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](#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](#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](#step-3-create-a-payment-or-payout) later.

> **Note**
>
> 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](/cash-app-pay-partner-api/guides/technical-guides/sandbox/sandbox-app) and [Developer Sandbox](/cash-app-pay-partner-api/guides/technical-guides/sandbox/developer-sandbox).

#### Listen for updates to the customer request

> **Note**
>
> 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](/cash-app-pay-partner-api/api-reference/customer-request-api/retrieve-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
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

> **Warning**
>
> 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](/cash-app-pay-partner-api/api-reference/network-api/create-payment) endpoint. You can use void, capture, or refund actions depending on the state of the payment.

> **Note**
>
> 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](/cash-app-pay-partner-api/guides/technical-guides/sandbox/developer-sandbox#magic-values) will result in specific outcomes.

**Example - Create Payment**

```curl
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](/cash-app-pay-partner-api/api-reference/network-api/create-payout) endpoint, using the grant from your `ON_FILE_PAYOUT` customer request.

**Example - Create Payout**

```curl
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](/cash-app-pay-partner-api/guides/technical-guides/payouts/about).

## 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](../../reference/Customer-Request-API.v1.yaml) 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](/cash-app-pay-partner-api/guides/pay-kit-sdk/pay-kit-web-overview/getting-started).

### 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](/cash-app-pay-partner-api/guides/technical-guides/sandbox/developer-sandbox#magic-values) to control the behavior in Sandbox and to produce preset outcomes.