Skip to main content
This guide walks you through supporting crypto withdrawals using the REST API.

Prerequisites

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.

Walkthrough

Check available rails

Call List rails to confirm the asset and network the user wants to withdraw to, and verify the withdraw feature is enabled.
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.

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. Call List accounts to retrieve the user’s accounts and let them choose one with sufficient balance for the withdrawal.

Select a destination

Crypto withdrawals support two ways of specifying the destination: a raw crypto-address (address entered on every transaction) or a saved external-account of type crypto (address registered once via Create external account, then reused across withdrawals).
Collect the destination asset, network and address from the user on each withdrawal.

Create a quote

Create a quote for the withdrawal using the Create quote endpoint.
A successful response returns a quote object with details about the withdrawal, including fees and expiration.
Quotes typically expire quickly. Prompt for user confirmation within the expiry window and regenerate if needed.

Handle quote requirements

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

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

Create a transaction

Once the user confirms the quote, create the transaction using the Create transaction endpoint.
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.

Execution modes

Crypto withdrawals are executed in one of the following modes, indicated by destination.node.execution.mode:
The transaction is broadcast to the blockchain network. destination.node.execution.mode is onchain, and destination.node.execution.transactionHash is set once the transaction is completed.
When both the sender and recipient are Uphold users, the transfer is processed within Uphold’s infrastructure instead of the blockchain. This avoids network fees and is faster than on-chain processing.Each side sees the transfer from its own perspective:When both users belong to the same organization, the execution also identifies the counterpart account: destination.node.execution.accountOwnerId and destination.node.execution.accountId for the sender, and origin.node.execution.accountOwnerId and origin.node.execution.accountId for the recipient.Because funds move between Uphold accounts, the assets may differ from an on-chain transfer:
  • Sender: destination.asset is the asset of the recipient account associated with the address, which may differ from the one in the quote.
  • Recipient: origin.asset is the asset of the sender’s account, which may differ from the network’s asset or even be one the network doesn’t support, such as a fiat asset.
Used in development environments for testing. The transaction appears processed without affecting blockchain state, although user balances are updated. destination.node.execution.mode is simulated.
If the destination was a saved external-account, destination.node keeps the same { type: "external-account", via: "crypto", id, ownerId, network } shape shown in Create a quote above, with an execution object added once on-chain details are known.

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
      • status: processing → initiated but not yet broadcast
    • core.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

Notify the user

Display an in-app confirmation when the transaction is completed, and send an email if applicable.
You now support crypto withdrawals with the Enterprise API Suite.