DocsCrypto payments
  1. Docs
  2. Guides
  3. Payment methods

Crypto payments

The payer sends coins from any wallet or exchange to an address made for their order. You get order.paid once the transfer is confirmed.

De documentatie voor ontwikkelaars is beschikbaar in het Engels.

Networks and coins

networkNetworkassetTypical confirmation
tronTron (TRC-20)USDT, USDC, TRX~1 min
ethereumEthereum (ERC-20)USDT, USDC, DAI, ETH~3 min
bscBNB Smart Chain (BEP-20)USDT, USDC, BNB~1 min
solanaSolana (SPL)USDC, USDT, SOL~30 s
polygonPolygon (ERC-20)USDC, USDT, DAI, POL~5 min
baseBase (ERC-20)USDC, ETH~1 min
arbitrumArbitrum One (ERC-20)USDC, USDT, DAI, ETH~1 min
optimismOptimism (ERC-20)USDC, USDT, DAI, ETH~1 min
bitcoinBitcoinBTC~20 min
litecoinLitecoinLTC~15 min
dogecoinDogecoinDOGE~20 min

In live mode the checkout only lists networks that are running at that moment; if a chain has trouble we hide it until it recovers, and payers pick another one. Test mode always shows the full list.

How the payer pays

  1. On the checkout the payer chooses crypto, then a network and a coin.
  2. We show an address for this order, the exact amount and a QR code. The address is only used for this order.
  3. The payer sends the amount. We see the transfer, send order.processing, and once it has enough confirmations, order.paid.

Coins sent on the wrong network (for example USDT on Ethereum to a Tron address) can't be credited automatically. The checkout warns about this next to every address.

Quotes and payment windows

  • Stablecoins (USDT, USDC, DAI) count one to one against the US dollar value of the order. The address stays open for 60 minutes.
  • Other coins (BTC, ETH, SOL, …) are quoted at the current price when the payer picks them. The quote is locked for 30 minutes; after that the payer gets a fresh quote.
  • Orders in other currencies than USD are converted to US dollars when the payer chooses a coin.

The minimum order for crypto is 1 USD (or its equivalent). Your account may have different limits; the dashboard shows the ones that apply to you.

Underpayments

Wallets and exchanges sometimes deduct a fee from the amount sent. We accept a small shortfall: by default up to 0.5% of the amount, or 0.50 USD, whichever is larger. Such a payment completes the order as paid, and amount_paid shows what actually arrived. Each store can set its own tolerance (0 to 5%), top-up window (0 to 72 hours) and what happens when the window closes short, under Settings ▸ Stores in the dashboard. The 0.50 USD minimum always applies.

If less arrives, the checkout shows what is missing and the payer has 48 hours (or the store's window) to top up to the same address (the charge's shortfall.top_up_until on the order). Meanwhile the order stays processing and nothing is credited yet; the full amount arriving completes it as paid right away. If the top-up window closes with a larger shortfall, what arrived is credited, the order ends as underpaid, you receive order.underpaid, amount_paid shows what arrived and shortfall.amount what is missing. A store set to complete short orders gets order.paid instead: the order is paid at what arrived and shortfall.resolved_by reads store_policy. Otherwise you can also complete the order early, during the window. Then you can:

  • complete it at the amount that arrived, from the dashboard or with POST /orders/:id/complete. The order becomes paid, keeps its original amount, and shortfall.resolution reads completed;
  • ask the payer to pay the rest: the same pay_link takes the remainder until the order expires; after that, create a new order for the difference;
  • or refund what arrived.

Overpayments are credited in full. Refund the extra with a partial refund if you want to give it back.

Late payments

Some payers send after the order expired. We keep watching each address for 7 days after expiry. A late payment that covers the order completes it: you receive order.paid after the order.expired you already got. Volatile coins that arrive late are credited at the lower of the original quote and the current price, so a price drop isn't yours to carry.

So don't treat expired as final for crypto orders: if you released the goods, either refund the late payment or fulfil anyway.

Large payments

Large deposits and deposits from addresses on screening lists are checked before they are credited. The order stays processing during the check and the payer sees that the payment was received. You get order.paid when it clears.

Preset a coin

If you already know how the payer wants to pay (for example they chose "USDT on Tron" in your own checkout), pass crypto when you create the order. The checkout skips the coin picker and shows the address right away.

Shell
curl https://velpay.pro/api/v1/orders \
  -H "Authorization: Bearer $VELPAY_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 2500,
    "currency": "usd",
    "reference": "A-2042",
    "methods": ["crypto"],
    "crypto": { "network": "tron", "asset": "USDT" }
  }'
  • network and asset are a pair from the table above. Case doesn't matter.
  • An unknown pair, or in live mode a network that isn't running, is answered with 400 crypto_unsupported and param set to crypto.network or crypto.asset.
  • If you pass methods, it must include crypto.
  • The order echoes the preset as crypto: { network, asset }.

To only put crypto first without fixing the coin, list it first in methods, e.g. "methods": ["crypto", "card"]: the checkout shows methods in that order and preselects the first.

On-chain details

GET /api/v1/orders/:id returns the payer's crypto charge with a crypto object: network, asset, address, amount_expected, amount_received, amount_remaining (decimal strings in the coin), tx_hashes, explorer_urls, confirmations and expires. Use it to show the payer their transaction or to answer support questions.

Refunds

Crypto payments are refunded on the network the payer used, to an address you pass as destination. Ask the payer for an address they control: refunding to the address they sent from often reaches an exchange that can't attribute it. See POST /orders/:id/refunds.