Skip to main content
This flow covers generating a deposit address, monitoring the chain or webhooks, and crediting the user’s account.

Prerequisites

  • The user is onboarded and verified (KYC is complete).
  • The crypto-deposits capability is enabled for the user.
  • An account has been created to receive the deposit.
  • The asset and network selected by the user are enabled in your environment (e.g., BTC mainnet, ETH mainnet/testnet).
  • The asset selected has the deposit feature enabled.
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 endpoint. Educate the user on the importance of providing this information when making the deposit, as it is essential for crediting their account correctly.

The flow


Using the REST API

Follow these steps to perform a crypto deposit using the REST API.

Choose asset & network

Confirm the asset (e.g., XRP) and network (e.g., xrp-ledger) that will be used to make the deposit.
For assets supported by multiple networks, require an explicit selection

Choose the target account

Let the user select the target account to credit. To list the user’s accounts, use the List accounts endpoint. When the target account asset differs from the crypto deposit asset, the conversion will happen when the deposit is settled, using Uphold’s prevailing rate.

Generate deposit method

Request a crypto deposit method for the user’s account by calling the Set up account deposit method endpoint, specifying the following parameters:
  • type: crypto
  • asset: the asset the user will deposit (e.g., XRP)
  • network: the network the user will deposit from (e.g., xrp-ledger)
POST /core/accounts/{accountId}/deposit-method?type=crypto&asset=XRP&network=xrp-ledger
A successful response includes the address and, if applicable, a reference (e.g., destination tag, memo).
{
  "depositMethod": {
    "type": "crypto",
    "status": "ok",
    "details": {
      "network": "xrp-ledger",
      "asset": "XRP",
      "address": "rfBtmHiLwwWH5maH2PT78GxubrSydRF9aY",
      "reference": "3457810109"
    }
  }
}

Display deposit instructions

Render the address clearly. 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.

Using the Payment Widget

To use the Payment Widget for crypto deposits, you must use the Select for Deposit flow.

Select for deposit flow

The Select for Deposit flow allows the user to select a deposit method, including crypto deposit, and displays the necessary instructions to complete the deposit. Please refer to the Select for deposit guide for a step-by-step tutorial.
Regardless of how the deposit instructions were generated (REST API or Payment Widget), the rest of the process is handled via REST API.

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
      • status: processing → detected on-chain but not yet confirmed
    • core.transaction.status-changed
      • status: completed → necessary confirmations reached
      • status: on-hold → transaction checks paused (e.g., pending RFIs)
      • status: failed → irrecoverable error
  • Polling (fallback):
The transaction typically has:
  • origin.node.type: crypto-address
  • origin.node.network: The origin crypto network (e.g. xrp-ledger)
  • origin.node.address: The originating crypto address (e.g. rfBtmHiLwwWH5maH2PT78GxubrSydRF9aY)
  • origin.node.reference: The source address reference, such as a destination tag (e.g. 67809592)
  • destination.node.type: account
  • destination.node.id: The id of the destination account
  • destination.node.ownerId: The id of the user that owns the destination account

Sample transaction

Below is a sample transaction object returned by the Get transaction endpoint. The origin field shows how the source of the deposit is represented:
{
  "transaction": {
    "id": "223c24c5-76c6-4553-91bc-5af519441f03",
    "origin": {
      "asset": "XRP",
      "amount": "1.00",
      "rate": "1.00",
      "node": {
        "type": "crypto-address",
        "network": "xrp-ledger",
        "execution": {
          "mode": "onchain",
          "transactionHash": "C74C5537AB6F766E9A95BCDA536FF239A6956E6BDF30A3357FA3EE174F7FFAB3"
        }
      }
    },
    "destination": {
      "asset": "XRP",
      "amount": "1.00",
      "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": "XRP",
      "amount": "1.00",
      "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: Used in development environments for testing purposes. 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 (Available soon).

Handle on-hold transactions

If the crypto deposit is placed on-hold with reason pending-requests-for-information on arrival, you’ll need to resolve pending RFIs before the deposit can complete. Follow the Transaction RFIs flow to handle this scenario.

Notify the user

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