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

# Deposit Destinations Quickstart

> Create a deposit address and simulate an inbound deposit

This guide creates a crypto deposit destination and simulates an inbound deposit in Sandbox. In Sandbox, deposit destinations are placeholder addresses for API testing. The Sandbox does not connect to any blockchain network.

**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 deposit addresses are placeholders for API testing only. They are not real blockchain addresses. Do **not** send real funds to Sandbox addresses. Your funds will be lost.
</Warning>

## 1. Create a deposit destination

Create a deposit destination for the account on Base network. The example below also includes an optional `target` (which makes it a liquidation address) and `metadata` for tracking:

```bash theme={null}
cdp api -X POST /platform/v2/deposit-destinations -e sandbox \
  accountId=$ACCOUNT_ID \
  type=crypto \
  crypto.network=base \
  target.accountId=$ACCOUNT_ID \
  target.asset=usd \
  'metadata.customer_id=123e4567-e89b-12d3-a456-426614174000' \
  metadata.reference=order-12345
```

<Accordion title="Example response">
  ```json theme={null}
  {
    "depositDestinationId": "depositDestination_af2937b0-9846-4fe7-bfe9-ccc22d935114",
    "accountId": "account_af2937b0-9846-4fe7-bfe9-ccc22d935114",
    "type": "crypto",
    "crypto": {
      "network": "base",
      "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
    },
    "target": {
      "accountId": "account_af2937b0-9846-4fe7-bfe9-ccc22d935114",
      "asset": "usd"
    },
    "status": "active",
    "metadata": {
      "customer_id": "123e4567-e89b-12d3-a456-426614174000",
      "reference": "order-12345"
    },
    "createdAt": "2023-10-08T14:30:00Z",
    "updatedAt": "2023-10-08T14:30:00Z"
  }
  ```
</Accordion>

Save the address:

```bash theme={null}
export DEPOSIT_ADDRESS="0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
```

## 2. List deposit destinations

List all deposit destinations for the account:

```bash theme={null}
cdp api /platform/v2/deposit-destinations -e sandbox accountId==$ACCOUNT_ID
```

<Accordion title="Example response">
  ```json theme={null}
  {
    "depositDestinations": [
      {
        "depositDestinationId": "depositDestination_af2937b0-9846-4fe7-bfe9-ccc22d935114",
        "accountId": "account_af2937b0-9846-4fe7-bfe9-ccc22d935114",
        "type": "crypto",
        "crypto": {
          "network": "base",
          "address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
        },
        "target": {
          "accountId": "account_af2937b0-9846-4fe7-bfe9-ccc22d935114",
          "asset": "usd"
        },
        "status": "active",
        "createdAt": "2023-10-08T14:30:00Z",
        "updatedAt": "2023-10-08T14:30:00Z"
      }
    ]
  }
  ```
</Accordion>

## 3. Simulate a deposit

Because Sandbox is not connected to a blockchain, use the fake-deposit endpoint to trigger the inbound flow.

Simulate an external sender depositing funds to the deposit address:

```bash theme={null}
cdp api -X POST /fake/deposit/crypto -e sandbox \
  deposit_address=$DEPOSIT_ADDRESS \
  amount=100.00 \
  asset_symbol=usdc \
  network=base
```

<Accordion title="Example response">
  ```json theme={null}
  {
    "transfer_id": "transfer_b340437d-4705-446f-8852-2345c83ace60",
    "created_at": "2026-02-24T03:12:10.077Z"
  }
  ```
</Accordion>

After simulation:

* **Webhook events fire**: `payments.transfers.processing` then `payments.transfers.completed`
* **Transfer record is created**: visible via the List Transfers API
* **Balance is credited**: the account balance updates immediately

<Note>
  The `asset_symbol` and `network` in the simulation request must match the deposit destination's configuration.
</Note>

## 4. Inspect the webhook payload

When the simulated deposit settles, CDP fires a `payments.transfers.completed` webhook to your subscribed endpoint. The payload includes the full transfer record, a reference back to the deposit destination, and any metadata set on the destination.

<Accordion title="Example webhook payload">
  ```json theme={null}
  {
    "eventID": "4557efb9-391b-4a9d-987d-d263b9d7fd37",
    "eventType": "payments.transfers.completed",
    "timestamp": "2026-01-21T20:15:04Z",
    "data": {
      "transferId": "transfer_af2937b0-9846-4fe7-bfe9-ccc22d935114",
      "status": "completed",
      "createdAt": "2026-01-21T20:12:46.296Z",
      "updatedAt": "2026-01-21T20:15:04.654Z",
      "source": {
        "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "asset": "usdc",
        "network": "base"
      },
      "sourceAmount": "100.00",
      "sourceAsset": "usdc",
      "target": {
        "accountId": "account_af2937b0-9846-4fe7-bfe9-ccc22d935114",
        "asset": "usdc"
      },
      "targetAmount": "100.00",
      "targetAsset": "usdc",
      "details": {
        "depositDestination": {
          "id": "depositDestination_af2937b0-9846-4fe7-bfe9-ccc22d935114"
        },
        "onchainTransactions": [
          {
            "network": "base",
            "transactionHash": "0x363cd3b3d4f49497cf5076150cd709307b90e9fc897fdd623546ea7b9313cecb"
          }
        ]
      },
      "metadata": {
        "customer_id": "123e4567-e89b-12d3-a456-426614174000",
        "reference": "order-12345"
      }
    }
  }
  ```
</Accordion>

Key fields:

* **`eventType`**: `payments.transfers.completed`, the deposit settled into the account
* **`data.source.address`**: the on-chain address of the external sender
* **`data.details.depositDestination.id`**: links the transfer back to the destination created in Step 1
* **`data.metadata`**: the metadata set on the deposit destination is propagated to every payin transfer for that destination
* **`eventID`**: unique per (transferId, status). Use it for idempotency to deduplicate retries

A `payments.transfers.processing` event also fires earlier in the flow when the deposit is first detected. For most integrations, listening only for `completed` is sufficient.

To receive these events, subscribe a webhook endpoint via the [Webhooks API](/webhooks/transfers/overview).

## 5. Verify the balance update

Confirm the deposit credited to the account:

```bash theme={null}
cdp api /platform/v2/accounts/$ACCOUNT_ID -e sandbox --jq '.balances'
```

## Using the Portal UI

Deposit destinations can also be created and deposits simulated through the Portal UI.

<Steps>
  <Step title="Navigate to Accounts">
    Go to the [Accounts page](https://portal.cdp.coinbase.com/v2/sandbox) in CDP Portal Sandbox
  </Step>

  <Step title="Open Deposit addresses tab">
    Click on an account row, then select the **Deposit addresses** tab
  </Step>

  <Step title="Create a new deposit address">
    Click **Create deposit address**, select the account and network, then click **Create address**
  </Step>

  <Step title="Simulate a deposit">
    Click **Deposit** under the Action column for the address to test, enter an amount, and click **Deposit now**
  </Step>
</Steps>

## Move to production

To run this flow on real blockchains, switch from the Sandbox base URL to the production base URL and use a production API key. Production deposit destinations are real on-chain addresses.

## What to read next

<CardGroup cols={2}>
  <Card title="Deposit Destinations overview" icon="circle-info" href="/payments/deposit-destinations/overview">
    Concepts, types, and supported networks
  </Card>

  <Card title="Transfers" icon="arrow-right-arrow-left" href="/payments/transfers/quickstart">
    Move funds from an account to an external address
  </Card>

  <Card title="Webhooks" icon="webhook" href="/webhooks/transfers/overview">
    Subscribe to real-time deposit event notifications
  </Card>

  <Card title="REST API reference" icon="code" href="/api-reference/v2/rest-api/deposit-destinations/deposit-destinations">
    Full Deposit Destinations API reference
  </Card>
</CardGroup>
