> ## 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 withdrawal via the REST API

> Send crypto withdrawals with the Uphold REST API: collect destination details, create a quote, handle requirements, and monitor for settlement.

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

## Prerequisites

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

<Warning>
  If the destination network requires an **additional reference** (e.g., destination tag, memo), strongly encourage your users to provide it. Missing references often lead to loss of funds or lengthy recovery.
</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 N as Blockchain Network

  Usr->>U: Start crypto withdrawal
  U->>B: List accounts
  B->>A: GET /core/accounts
  A-->>B: { accounts }
  B-->>U: { accounts }
  Usr->>U: Choose source account and amount
  U->>B: Request quote
  B->>A: Create quote
  A-->>B: { quote }
  B-->>U: { quote }
  Usr->>U: Confirm quote
  U->>B: Create transaction
  B->>A: Create transaction
  A-->>B: { transaction }
  A-->>B: webhook: transaction.created (processing)
  A->>N: Broadcast withdrawal
  N-->>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 withdraw to, and verify the `withdraw` 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 `"withdraw"`. For assets supported by multiple networks, require an explicit network selection from the user. Use the network's `reference` field to determine whether to show a destination tag or memo input in your UI.

```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 source account

Crypto withdrawals can be sourced from any account. If the selected account is not in the withdrawal asset, the balance will be converted at the time of the transaction using Uphold's prevailing rate. Make sure the origin asset has the necessary [features enabled](/rest-apis/core-api/assets/introduction#features-and-deposits-/-withdrawals).

Call [List accounts](/rest-apis/core-api/accounts/list-accounts) to retrieve the user's accounts and let them choose one with sufficient balance for the withdrawal.

```http theme={null}
GET /core/accounts?currency=BTC
```

```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 quote

Create a quote for the withdrawal using the [Create quote](/rest-apis/core-api/transactions/create-quote) endpoint.

```http theme={null}
POST /core/transactions/quote
{
  "origin": {
    "type": "account",
    "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8"
  },
  "destination": {
    "type": "crypto-address",
    "asset": "BTC",
    "network": "bitcoin",
    "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
  },
  "denomination": {
    "asset": "GBP",
    "amount": "100.00",
    "target": "origin"
  }
}
```

A successful response returns a `quote` object with details about the withdrawal, including fees and expiration.

```json [expandable] theme={null}
{
  "quote": {
    "id": "623000c8-9bdf-4a2b-aa3d-6a6b44a7f6a0",
    "origin": {
      "amount": "0.00121023",
      "asset": "BTC",
      "rate": "0.00002629253259492961",
      "node": {
        "type": "account",
        "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      }
    },
    "destination": {
      "amount": "0.00121023",
      "asset": "BTC",
      "rate": "1",
      "node": {
        "type": "crypto-address",
        "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
        "network": "bitcoin",
        "execution": {
          "mode": "onchain"
        }
      }
    },
    "denomination": {
      "amount": "100.00",
      "asset": "GBP",
      "target": "origin",
      "rate": "0.00001210225938333485"
    },
    "fees": [],
    "expiresAt": "2024-07-24T15:22:39Z"
  }
}
```

<Info>Quotes typically **expire** quickly. Prompt for user confirmation within the expiry window and regenerate if needed.</Info>

## Handle quote requirements

When the quote is returned, check the `requirements` array. If non-empty, resolve each requirement before creating the transaction.

```json theme={null}
{
  "quote": {
    "id": "623000c8-9bdf-4a2b-aa3d-6a6b44a7f6a0",
    "requirements": [
      "travel-rule"
    ],
    "expiresAt": "2024-07-24T15:22:39Z"
  }
}
```

### Travel Rule

If the `requirements` array contains `travel-rule`, you must collect the required originator and beneficiary information before creating the transaction. For the full step-by-step implementation, see the [Travel Rule withdrawal](/developer-guides/travel-rule/withdrawal) guide.

## Create a transaction

Once the user confirms the quote, create the transaction using the [Create transaction](/rest-apis/core-api/transactions/create-transaction) endpoint.

```http theme={null}
POST /core/transactions
{
  "quoteId": "623000c8-9bdf-4a2b-aa3d-6a6b44a7f6a0"
}
```

<Note>If the quote required Travel Rule, include the data collected by the widget under `params.travelRule`. See the [Travel Rule withdrawal flow](/developer-guides/travel-rule/withdrawal) guide.</Note>

In a successful crypto withdrawal, the origin is the source account and the destination is a `crypto-address` node reflecting the recipient's on-chain address.

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

### Execution modes

Crypto withdrawals support different execution modes depending on the destination and environment:

* **On-chain execution**: The transaction is processed directly on the blockchain network. The `destination.node.execution.mode` will be `onchain` and include blockchain-specific details such as transaction hashes upon completion.
* **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 onchain processing. The `destination.node.execution.mode` will be `offchain`. For offchain transactions, the `execution` object includes additional properties: `accountOwnerId` (the recipient user ID) and `accountId` (the recipient account ID).
* **Simulated execution**: Used in development environments for testing purposes. The transaction appears processed but does not affect actual blockchain state (user balances will be affected though). The `destination.node.execution.mode` will be `simulated`.

## Monitor for settlement

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` → initiated but not yet broadcast
  * [core.transaction.status-changed](/rest-apis/core-api/transactions/webhooks/transaction-status-changed)
    * `status: completed` → broadcast and confirmed
    * `status: on-hold` → transaction checks paused (e.g., pending RFIs)
    * `status: failed` → transaction failed, check `statusDetails` for more info
* Polling (fallback): [Get transaction](/rest-apis/core-api/transactions/get-transaction)

## Notify the user

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

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