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

# Crypto deposit via the REST API

> Support crypto deposits with the Uphold REST API: configure the deposit method, generate a network address, and monitor for incoming on-chain transfers.

This guide walks you through supporting crypto deposits using the REST API.

## Prerequisites

* The user has [completed onboarding](/developer-guides/user-onboarding/overview) and has the required capabilities enabled.

<Warning>
  Some networks require **destination tags/memos** (e.g., XRP, XLM). If a `reference` is returned with the `address`, you can check its type by calling [Get network](/rest-apis/core-api/assets/get-network) endpoint. Educate the user on the importance of providing this information when making the deposit, as it is essential for crediting their account correctly.
</Warning>

## Walkthrough

```mermaid theme={null}
sequenceDiagram
  autonumber
  participant Usr as User
  participant U as Your App
  participant B as Your Backend
  participant A as Uphold
  participant C as Blockchain Network

  Usr->>U: Request deposit instructions
  U->>B: List accounts
  B->>A: GET /core/accounts
  A-->>B: { accounts }
  B-->>U: { accounts }
  Usr->>U: Choose destination account
  U->>B: Generate deposit method
  B->>A: PUT /core/accounts/{accountId}/deposit-method
  A-->>B: { depositMethod }
  B-->>U: { depositMethod }
  U-->>Usr: Display deposit instructions
  Usr->>C: Send crypto transfer
  C-->>A: Detect inbound tx to address
  A-->>B: webhook: transaction.created (processing)
  C-->>A: Confirmations reached
  A-->>B: webhook: transaction.status-changed (completed/failed)
  B-->>Usr: Notify the user
```

## Check available rails

Call [List rails](/rest-apis/core-api/assets/list-rails) to confirm the asset and network the user wants to deposit from, and verify the `deposit` feature is enabled.

```http theme={null}
GET /core/rails?type=crypto&asset=BTC
```

A successful response lists all rails for the asset. Each rail includes a `features` array — only proceed with networks that include `"deposit"`. For assets supported by multiple networks, require an explicit network selection from the user.

```json theme={null}
{
  "rails": [
    {
      "type": "crypto",
      "network": "bitcoin",
      "method": "crypto-transaction",
      "asset": "BTC",
      "decimals": 8,
      "features": [
        "deposit",
        "withdraw"
      ]
    },
    {
      "type": "crypto",
      "network": "lightning",
      "method": "crypto-transaction",
      "asset": "BTC",
      "decimals": 8,
      "features": []
    }
  ]
}
```

## Select destination account

Crypto deposits can target any account. If the selected account is not in the deposited asset, the amount will be converted at settlement using Uphold's prevailing rate. Make sure the destination asset has the necessary [features enabled](/rest-apis/core-api/assets/introduction#features-and-deposits-/-withdrawals).

### Find an existing account

Call [List accounts](/rest-apis/core-api/accounts/list-accounts) to retrieve the user's accounts and let them pick the one they want to fund.

```http theme={null}
GET /core/accounts
```

```json theme={null}
{
  "accounts": [
    {
      "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
      "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a",
      "label": "My BTC account",
      "asset": "BTC",
      "balance": {
        "total": "0.05",
        "available": "0.05"
      }
    }
  ]
}
```

### Create a new account

If the user has no accounts, create one with [Create account](/rest-apis/core-api/accounts/create-account) before proceeding.

```http theme={null}
POST /core/accounts
{
  "label": "My BTC account",
  "asset": "BTC"
}
```

```json theme={null}
{
  "account": {
    "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
    "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a",
    "label": "My BTC account",
    "asset": "BTC",
    "balance": {
      "total": "0",
      "available": "0"
    }
  }
}
```

## Generate deposit method

Call [Set up account deposit method](/rest-apis/core-api/accounts/set-up-account-deposit-method) with the target account id, asset, and network.

```http theme={null}
PUT /core/accounts/{accountId}/deposit-method?type=crypto&asset=BTC&network=bitcoin
```

A successful response includes the `address` and, if applicable, a `reference` (e.g., destination tag, memo).

```json theme={null}
{
  "depositMethod": {
    "type": "crypto",
    "status": "ok",
    "details": {
      "network": "bitcoin",
      "asset": "BTC",
      "address": "tb1qgu0gacn9pqpnvlqclvdwyz4gfgxz8pptfz4emt"
    }
  }
}
```

<Note>The deposit method may initially return `status: processing` while the address is being prepared. Call [Get account deposit method](/rest-apis/core-api/accounts/get-account-deposit-method) to confirm it is ready (`status: ok`) before displaying instructions to the user.</Note>

Render the address clearly and, if a `reference` is present, display it prominently and treat it as required input. We suggest also displaying a QR code to reduce input errors.

## Monitor for the incoming transfer

Prefer **webhooks** for real-time updates, or fall back to **polling** if webhooks are not feasible.

* Webhook events (recommended):
  * [core.transaction.created](/rest-apis/core-api/transactions/webhooks/transaction-created)
    * `status: processing` → detected on-chain but not yet confirmed
  * [core.transaction.status-changed](/rest-apis/core-api/transactions/webhooks/transaction-status-changed)
    * `status: completed` → necessary confirmations reached
    * `status: on-hold` → transaction checks paused (e.g., pending RFIs)
    * `status: failed` → irrecoverable error
* Polling (fallback): [Get transaction](/rest-apis/core-api/transactions/get-transaction)

## Sample transaction

In a successful crypto deposit, the origin is represented as a `crypto-address` node reflecting the sender's on-chain address. The destination is the account that was set up to receive the deposit.

```json [expandable] theme={null}
{
  "transaction": {
    "id": "223c24c5-76c6-4553-91bc-5af519441f03",
    "origin": {
      "asset": "BTC",
      "amount": "0.00121023",
      "rate": "1.00",
      "node": {
        "type": "crypto-address",
        "network": "bitcoin",
        "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
        "execution": {
          "mode": "onchain",
          "transactionHash": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
        }
      }
    },
    "destination": {
      "asset": "BTC",
      "amount": "0.00121023",
      "rate": "1.00",
      "node": {
        "type": "account",
        "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      }
    },
    "fees": [],
    "status": "completed",
    "quotedAt": "2024-07-24T15:02:39Z",
    "createdAt": "2024-07-24T15:22:39Z",
    "updatedAt": "2024-07-24T15:33:08Z",
    "denomination": {
      "asset": "BTC",
      "amount": "0.00121023",
      "rate": "1.00",
      "target": "origin"
    }
  }
}
```

### Execution modes

Crypto deposits are processed using different execution modes depending on the environment and configuration:

* **On-chain execution**: The transaction is processed directly on the blockchain network. The `origin.node.execution.mode` will be `onchain` and include a `transactionHash` as shown in the example above.
* **Off-chain execution**: When both the sender and recipient are Uphold users, the transaction is processed internally within Uphold's infrastructure. This eliminates network fees and is faster than on-chain processing. The `origin.node.execution.mode` will be `offchain`. The `execution` object for these transactions includes additional properties: `accountOwnerId` (the sender user ID) and `accountId` (the sender account ID).
* **Simulated execution (Test Helpers)**: Used in development environments for testing purposes ([Simulate crypto deposit](/rest-apis/core-api/accounts/test-helpers/simulate-crypto-deposit)). The transaction appears as processed but does not affect actual blockchain state (user balances will be affected though). The `origin.node.execution.mode` will be `simulated`.

## Handle on-hold transactions

If the crypto deposit is placed `on-hold` with reason `pending-requests-for-information`, resolve the pending RFIs before the deposit can complete. For the full step-by-step implementation, see the [Travel Rule deposit flow](/developer-guides/travel-rule/deposit) guide.

## Notify the user

Display an in-app confirmation when the transaction is `completed`, and send an email if applicable.

<Check>You now support crypto deposits with the Enterprise API Suite.</Check>
