> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cdp.coinbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pay with a Wallet

> Let customers pay from a self-custody wallet by signing an authorization.

Pay with a Wallet lets customers pay from a self-custody wallet by signing payloads that place a hold on their funds. It supports 500+ EVM wallets, including MetaMask, Trust Wallet, Base Pay, and Rabby, and Solana wallets such as Phantom and Solflare. The session target can be a CDP account or a Base address.

> [!NOTE]
>
> Coinbase's [hosted checkout](https://docs.cdp.coinbase.com/payments/payment-acceptance/hosted-checkout.md) runs this flow for you. Call these endpoints only when you build the checkout yourself.

## How it works

```mermaid theme={null}
sequenceDiagram
    participant M as Your checkout
    participant C as Coinbase API
    participant B as Customer wallet

    M->>C: GET /authorizations/wallet/options?addresses=0xABC
    C-->>M: Available options (network, asset, payloads)
    M->>B: Present options, request signature
    B-->>M: Signed payloads
    M->>C: POST /authorizations/wallet (optionId + signedPayloads)
    C-->>M: Authorization (pending)
    C-->>M: Webhook: authorization_succeeded
```

Before you start, [create a payment session](https://docs.cdp.coinbase.com/payments/payment-acceptance/payment-sessions.md).

## 1. Get authorization options

Pass every address the connected wallet controls, up to 5, comma-separated. Each returned option gives the network, asset, amount, and payloads to sign.

* Coinbase returns at most one option per asset, from the address with the highest stablecoin balance. That can be a Solana address.
* Addresses that aren't chosen, for example because of insufficient funds, are omitted.
* Add `network` or `asset` only when you must restrict the choice. The Solana network name is `solana` in every environment, including Sandbox.

```
?addresses=0xABC,0xDEF&network=base&asset=usdc
```

> **EVM wallet**
>
> ```bash theme={null}
> cdp api /platform/v2/payment-sessions/$SESSION_ID/authorizations/wallet/options \
>   -e sandbox \
>   addresses==0xAbC1234567890aBcDeF1234567890AbCdEf123456
> ```
>
> ```json theme={null}
> {
>   "options": [
>     {
>       "optionId": "opt_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
>       "source": {
>         "address": "0xAbC1234567890aBcDeF1234567890AbCdEf123456",
>         "network": "base",
>         "asset": "usdc"
>       },
>       "amount": "25.00",
>       "asset": "usdc",
>       "network": "base",
>       "payloads": [
>         {
>           "payloadId": "payload_af2937b0-...",
>           "type": "eip3009",
>           "data": { ... }
>         }
>       ]
>     }
>   ]
> }
> ```

> **Solana wallet**
>
> ```bash theme={null}
> cdp api /platform/v2/payment-sessions/$SESSION_ID/authorizations/wallet/options \
>   -e sandbox \
>   addresses==9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin
> ```
>
> Add `network=solana` only when the payment must come from Solana.
>
> ```json theme={null}
> {
>   "options": [
>     {
>       "optionId": "opt_c3d4e5f6-a7b8-9012-cdef-1234567890ab",
>       "source": {
>         "address": "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin",
>         "network": "solana",
>         "asset": "usdc"
>       },
>       "amount": "25.00",
>       "asset": "usdc",
>       "network": "solana",
>       "payloads": [
>         {
>           "payloadId": "payload_7c18e4a2-9d53-4b61-8f20-1a6e9c0d4b87",
>           "type": "svm_spl_transfer",
>           "data": {
>             "mintAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
>             "signerAddress": "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin",
>             "transaction": "AQABAgI..."
>           }
>         }
>       ]
>     }
>   ]
> }
> ```

> [!NOTE]
>
> This call doesn't modify the session.

## 2. Sign the payloads

Sign every payload in the chosen option. The payload `type` tells you how to handle `data`:

| Type | Action | Returns |
| - | - | - |
| `eip3009` | Pass `data` to `eth_signTypedData_v4` | Hex-encoded signature |
| `permit2` | Pass `data` to `eth_signTypedData_v4` | Hex-encoded signature |
| `spend_permission` | Pass `data` to `eth_signTypedData_v4` | Hex-encoded signature |
| `erc20_approval` | Send `data` via `eth_sendTransaction` | Transaction hash |
| `svm_spl_transfer` | Sign the transaction. See [Solana signatures](#solana-signatures). | Base58-encoded 64-byte signature |

### Solana signatures

`data.transaction` is the unsigned transaction, base64-encoded. Coinbase broadcasts it, so you submit only the signature:

1. Base64-decode `data.transaction`.
2. Pass the bytes to Wallet Standard `signTransaction`.
3. Take the 64-byte ed25519 signature of the signer: `data.signerAddress` for a payment, or the customer's Solana address for a mandate approval.
4. Base58-encode that signature and submit it as `signature`.

Submitting the signed transaction bytes or a transaction ID returns `invalid_signature`.

## 3. Submit the signatures

Submit the signatures with the chosen `optionId`:

> **EVM wallet**
>
> ```bash theme={null}
> cdp api -X POST /platform/v2/payment-sessions/$SESSION_ID/authorizations/wallet \
>   -e sandbox \
>   optionId=opt_a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
>   'signedPayloads:=[{"payloadId":"payload_af2937b0-...","signature":"0xabcdef..."}]'
> ```

> **Solana wallet**
>
> ```bash theme={null}
> cdp api -X POST /platform/v2/payment-sessions/$SESSION_ID/authorizations/wallet \
>   -e sandbox \
>   optionId=opt_c3d4e5f6-a7b8-9012-cdef-1234567890ab \
>   'signedPayloads:=[{"payloadId":"payload_7c18e4a2-9d53-4b61-8f20-1a6e9c0d4b87","signature":"5Kj8h..."}]'
> ```

The authorization starts as `pending` and moves to `succeeded` or `failed`. Track it with [webhooks](https://docs.cdp.coinbase.com/webhooks/payment-acceptance/overview.md).

## What to read next

> **[Payment Sessions](https://docs.cdp.coinbase.com/payments/payment-acceptance/payment-sessions.md)**
>
> Session lifecycle, authorization outcomes, and idempotency

> **[Recurring Payments](https://docs.cdp.coinbase.com/payments/payment-acceptance/recurring-payments.md)**
>
> Approve once, then authorize payments without a new signature

> **[Webhooks](https://docs.cdp.coinbase.com/webhooks/payment-acceptance/overview.md)**
>
> Get notified when authorization succeeds or fails

> **[API Reference - Wallet Auth](https://docs.cdp.coinbase.com/api-reference/v2/rest-api/payment-sessions/authorize-a-payment-session-with-a-wallet.md)**
>
> Wallet authorization API
