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

# Transfers Quickstart

> Create transfers to a crypto address, email, and payment method in Sandbox

This guide creates transfers to a crypto address, an email recipient, and a payment method in Sandbox, then shows how to validate, poll status, handle webhooks, and list transfers. The Sandbox does not connect to any blockchain network or settle funds on real fiat rails.

**Base URL:** `https://sandbox.cdp.coinbase.com`

## Prerequisites

Before you begin, you'll need:

<AccordionGroup>
  <Accordion title="CDP CLI">
    Install the CDP CLI (requires Node.js 22+):

    ```bash theme={null}
    npm install -g @coinbase/cdp-cli
    ```

    Configure a Sandbox environment using your CDP Secret API Key JSON file from the [CDP Portal](https://portal.cdp.coinbase.com):

    ```bash theme={null}
    cdp env sandbox --key-file ./cdp-api-key.json --url https://sandbox.cdp.coinbase.com
    ```

    <Warning>
      Keep the API key secret. Never commit it to source control.
    </Warning>
  </Accordion>

  <Accordion title="A funded Sandbox account">
    See the [Custodial Accounts Quickstart](/wallets/custodial-wallets/quickstart) for setting up a Sandbox account with funds.

    Set the account ID:

    ```bash theme={null}
    export ACCOUNT_ID="account_db458f63-..."
    ```
  </Accordion>
</AccordionGroup>

<Warning>
  Sandbox transfers do not move real funds. Crypto targets are placeholder addresses, email targets are mock recipients, and payment method targets simulate fiat rails. Do **not** use real recipient details when testing in Sandbox.
</Warning>

## 1. Create a transfer to a crypto address

Send USDC from the funded account to an external on-chain address. In Sandbox, use these reserved addresses to test specific outcomes:

| Reserved address                             | Outcome             |
| -------------------------------------------- | ------------------- |
| `0x1111111111111111111111111111111111111111` | Success             |
| `0x2222222222222222222222222222222222222222` | Invalid target      |
| `0x3333333333333333333333333333333333333333` | Invalid address     |
| `0x4444444444444444444444444444444444444444` | Unsupported network |

Send to the success address:

```bash theme={null}
cdp api -X POST /platform/v2/transfers -e sandbox \
  source.accountId=$ACCOUNT_ID \
  source.asset=usdc \
  target.network=base \
  target.address=0x1111111111111111111111111111111111111111 \
  target.asset=usdc \
  amount=5.00 \
  asset=usdc \
  'execute:=true'
```

<Accordion title="Example response">
  ```json theme={null}
  {
    "transferId": "transfer_8b707d29-4690-4948-b645-de1cd1f5fd05",
    "status": "completed",
    "source": {
      "accountId": "account_db458f63-418a-4a91-a045-fab93ac35c3f",
      "asset": "usdc"
    },
    "target": {
      "network": "base",
      "address": "0x1111111111111111111111111111111111111111",
      "asset": "usdc"
    },
    "sourceAmount": "5.00",
    "sourceAsset": "usdc",
    "targetAmount": "5.00",
    "targetAsset": "usdc",
    "createdAt": "2026-02-11T23:19:24.086Z",
    "updatedAt": "2026-02-11T23:19:24.183Z"
  }
  ```
</Accordion>

Save the transfer ID for later steps:

```bash theme={null}
export TRANSFER_ID="transfer_8b707d29-4690-4948-b645-de1cd1f5fd05"
```

## 2. Create a transfer to an email

Send USDC to a Coinbase user by email. In Sandbox, use these reserved test emails to avoid privacy issues with real addresses:

| Test email                         | Outcome                            |
| ---------------------------------- | ---------------------------------- |
| `testuser1@domain.com`             | Success                            |
| `sandboxinvalidtarget@domain.com`  | Invalid email                      |
| `sandboxexecutionfails@domain.com` | Validation passes, execution fails |

Send to the success email:

```bash theme={null}
cdp api -X POST /platform/v2/transfers -e sandbox \
  source.accountId=$ACCOUNT_ID \
  source.asset=usdc \
  target.email=testuser1@domain.com \
  target.asset=usdc \
  amount=5.00 \
  asset=usdc \
  'execute:=true'
```

## 3. Create a fiat withdrawal to a payment method

Withdraw USD from the account to a bank-rail payment method (Fedwire, SWIFT, or SEPA). The rail is determined by the payment method itself.

Sandbox auto-provisions mock payment methods on every entity. List them and pick one to use:

```bash theme={null}
cdp api /platform/v2/payment-methods -e sandbox

export PAYMENT_METHOD_ID="paymentMethod_8e03978e-..."
```

Send the withdrawal:

```bash theme={null}
cdp api -X POST /platform/v2/transfers -e sandbox \
  source.accountId=$ACCOUNT_ID \
  source.asset=usd \
  target.paymentMethodId=$PAYMENT_METHOD_ID \
  amount=100.00 \
  asset=usd \
  'execute:=true'
```

## 4. Validate before executing

Use `validateOnly: true` to verify recipient details before committing a transfer. This is useful for preflight checks on user-entered addresses or emails:

```bash theme={null}
cdp api -X POST /platform/v2/transfers -e sandbox \
  source.accountId=$ACCOUNT_ID \
  source.asset=usdc \
  target.network=base \
  target.address=0x1111111111111111111111111111111111111111 \
  target.asset=usdc \
  amount=5.00 \
  asset=usdc \
  'validateOnly:=true'
```

A `200` response means the transfer would succeed. A `4xx` response contains an `errorType` explaining why validation failed.

<Note>
  `validateOnly` and `execute` are mutually exclusive. Do not set both to `true`.
</Note>

## 5. Check transfer status

Poll the transfer to see its current status:

```bash theme={null}
cdp api /platform/v2/transfers/$TRANSFER_ID -e sandbox --jq '.status'
```

## 6. Handle webhooks

In production, subscribe to `payments.transfers.*` events to receive real-time status updates rather than polling. See [Webhooks](/webhooks/transfers/overview) for setup.

**Events fired for a successful transfer:**

1. `payments.transfers.processing`, transfer is executing
2. `payments.transfers.completed`, transfer succeeded

**Events fired for a failed transfer:**

1. `payments.transfers.processing`, transfer is executing
2. `payments.transfers.failed`, transfer failed; inspect `failureReason`

## 7. List transfers

View all transfers for your entity:

```bash theme={null}
cdp api /platform/v2/transfers -e sandbox
```

## Move to production

To run this flow on real rails, switch from the Sandbox base URL to the production base URL and use a production API key. Production transfers move real funds: crypto targets settle on-chain, email targets credit real Coinbase users, and payment method targets execute on Fedwire, SWIFT, or SEPA.

## What to read next

<CardGroup cols={2}>
  <Card title="Transfers overview" icon="circle-info" href="/payments/transfers/overview">
    Transfer types, fee quotes, travel rule, and lifecycle
  </Card>

  <Card title="Deposit Destinations" icon="arrow-down-to-line" href="/payments/deposit-destinations/quickstart">
    Receive inbound crypto into a custodial account
  </Card>

  <Card title="Webhooks" icon="webhook" href="/webhooks/transfers/overview">
    Subscribe to real-time transfer status events
  </Card>

  <Card title="REST API reference" icon="code" href="/api-reference/v2/rest-api/transfers/transfers">
    Create, execute, list, and get transfers
  </Card>
</CardGroup>
