Transfer
Send cryptocurrency from a customer's HD wallet to any on-chain address.
Endpoint
POST /api/v1/wallet/:customerID/transferAuthentication
Requires API key in the X-API-Key header. Also requires the wallet:transfer permission on the key.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
customerID | string | Your internal customer identifier |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
network | string | Yes | Blockchain network code |
currency | string | Yes | Token to send |
to_address | string | Yes | Recipient blockchain address |
amount | string | Yes | Amount in base units (see table below) |
index | integer | No | Derivation index to send from (default: 0) |
Amount Units
Always pass amounts as integer strings in the network's smallest unit. Never pass decimals.
| Network | Currency | Unit | Decimals | 1 human unit = |
|---|---|---|---|---|
| BTC | BTC | satoshi | 8 | 100000000 |
| LTC | LTC | satoshi | 8 | 100000000 |
| BCH | BCH | satoshi | 8 | 100000000 |
| ETH | ETH | wei | 18 | 1000000000000000000 |
| BSC | BNB | wei | 18 | 1000000000000000000 |
| POL | MATIC/POL | wei | 18 | 1000000000000000000 |
| ETH | USDT | micro-USDT | 6 | 1000000 |
| ETH | USDC | micro-USDC | 6 | 1000000 |
| BSC | USDT | wei-USDT | 18 | 1000000000000000000 |
| BSC | USDC | wei-USDC | 18 | 1000000000000000000 |
| POL | USDT | wei-USDT | 18 | 1000000000000000000 |
| POL | USDC | wei-USDC | 18 | 1000000000000000000 |
| TRX | TRX | sun | 6 | 1000000 |
| TRX | USDT | sun-USDT | 6 | 1000000 |
| SOL | SOL | lamport | 9 | 1000000000 |
| SOL | USDC | micro-USDC | 6 | 1000000 |
| XRP | XRP | drop | 6 | 1000000 |
BSC/POL USDT and USDC are 18 decimals, not 6. This is correct for BEP-20/ERC-20 on these networks.
Blocked Combinations
The following combinations are rejected with 400 Bad Request:
| Network | Currency | Reason |
|---|---|---|
SOL | USDT | USDT does not exist as a native SPL token on Solana |
TRX | USDC | USDC does not exist as a TRC-20 token on Tron |
Use USDT on ETH, BSC, POL, or TRX. Use USDC on ETH, BSC, POL, or SOL.
Example Requests
// Send 0.01 BTC (= 1,000,000 satoshis)
const response = await fetch(
'https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/user_12345/transfer',
{
method: 'POST',
headers: {
'X-API-Key': 'live_sk_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
network: 'BTC',
currency: 'BTC',
to_address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
amount: '1000000',
index: 0
})
}
);
const transfer = await response.json();
console.log('Transaction Hash:', transfer.tx_hash);
console.log('Status:', transfer.status);// Send 50 USDT on Ethereum (6 decimals → 50,000,000)
const response = await fetch(
'https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/user_12345/transfer',
{
method: 'POST',
headers: { 'X-API-Key': 'live_sk_your_key_here', 'Content-Type': 'application/json' },
body: JSON.stringify({
network: 'ETH',
currency: 'USDT',
to_address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
amount: '50000000', // 50 USDT — ETH USDT is 6 decimals
index: 0
})
}
);
const transfer = await response.json();
console.log('tx_hash:', transfer.tx_hash);// Send 50 USDT on BSC (18 decimals → 50 × 10^18)
const response = await fetch(
'https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/user_12345/transfer',
{
method: 'POST',
headers: { 'X-API-Key': 'live_sk_your_key_here', 'Content-Type': 'application/json' },
body: JSON.stringify({
network: 'BSC',
currency: 'USDT',
to_address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
amount: '50000000000000000000', // 50 USDT — BSC USDT is 18 decimals
index: 0
})
}
);import requests
# Send 100 USDT on Tron (6 decimals)
response = requests.post(
'https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/user_12345/transfer',
headers={
'X-API-Key': 'live_sk_your_key_here',
'Content-Type': 'application/json'
},
json={
'network': 'TRX',
'currency': 'USDT',
'to_address': 'TYourRecipientAddress',
'amount': '100000000', # 100 USDT on TRX (6 decimals)
'index': 0
}
)
transfer = response.json()
print(f"Transaction: {transfer['tx_hash']}")
print(f"Gas Fee: {transfer['gas_fee']}")curl -X POST https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/user_12345/transfer \
-H "X-API-Key: live_sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"network": "SOL",
"currency": "USDC",
"to_address": "YourRecipientSolanaAddress",
"amount": "50000000",
"index": 0
}'Response
Success (200 OK)
| Field | Type | Description |
|---|---|---|
tx_hash | string | Main transaction hash |
from_address | string | Sender address (customer's derived wallet) |
to_address | string | Recipient address |
amount | string | Amount delivered to recipient in base units (gross minus any fee) |
currency | string | Token sent |
network | string | Blockchain network |
gas_fee | string | Network gas fee in base units (native token) |
status | string | pending — transaction is broadcast, awaiting confirmation |
timestamp | string | ISO 8601 timestamp |
fee_amount | string | (optional) Fee collected in base units — omitted if no fee configured |
fee_tx_hash | string | (optional) Fee transaction hash. Empty for BTC/LTC/BCH (fee is part of main tx). Omitted if no fee. |
{
"tx_hash": "0x1a2b3c4d5e6f...",
"from_address": "0x8B3192f2f0f0D7E4F5C3A1B9E2D7A6C5B4D3E2F1",
"to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"amount": "49500000",
"currency": "USDT",
"network": "ETH",
"gas_fee": "2100000000000000",
"status": "pending",
"timestamp": "2026-06-26T12:00:00Z",
"fee_amount": "500000",
"fee_tx_hash": "0xdeadbeef..."
}The
amountin the response is what the recipient receives — gross minus fee. If no fee is configured,amountequals theamountfrom the request.
Error Responses
400 — Blocked combination
{ "error": "USDT is not supported on Solana — use USDT on ETH, BSC, POL, or TRX" }{ "error": "USDC is not supported on Tron — use USDC on ETH, BSC, POL, or SOL" }500 — Broadcast failed
{ "error": "transfer failed: insufficient funds: need 150000 satoshis, have 80000 (fee 12000)" }Transaction Status
The response always returns status: "pending". Track confirmation via webhooks:
| Status | Webhook | Meaning |
|---|---|---|
pending | — | Transaction broadcast, awaiting block inclusion |
confirmed | wallet.transfer.confirmed | Transaction included in block |
failed | wallet.transfer.failed | Transaction rejected |
WaaS Fee Collection
If your business has configured a WaaS fee (see POST /api/v1/settings/waas/fees), the fee is automatically applied to every transfer on networks where you have a receiving address set:
- Gross amount is what the customer initiates (the
amountfield you send) - Net amount goes to the recipient (
amountin the response) - Fee goes directly on-chain to your configured fee address (not through any platform intermediary)
Fee mechanics per chain type:
| Chain | How fee is collected |
|---|---|
| BTC, LTC, BCH | Single transaction with 3 outputs: recipient + your fee address + change |
| SOL (native) | Single transaction with 2 transfer instructions |
| ETH, BSC, POL, TRX, XRP, SOL USDC | Two sequential transactions — main transfer first, then fee |
Block Explorers
| Network | Explorer | URL Format |
|---|---|---|
| Bitcoin | Mempool.space | https://mempool.space/tx/{tx_hash} |
| Litecoin | Blockchair | https://blockchair.com/litecoin/transaction/{tx_hash} |
| Bitcoin Cash | Blockchair | https://blockchair.com/bitcoin-cash/transaction/{tx_hash} |
| Ethereum | Etherscan | https://etherscan.io/tx/{tx_hash} |
| BSC | BscScan | https://bscscan.com/tx/{tx_hash} |
| Polygon | PolygonScan | https://polygonscan.com/tx/{tx_hash} |
| Tron | Tronscan | https://tronscan.org/#/transaction/{tx_hash} |
| Solana | Solscan | https://solscan.io/tx/{tx_hash} |
| XRP | XRPScan | https://xrpscan.com/tx/{tx_hash} |
Related Endpoints
- Estimate Gas — Estimate network fees before transfer (EVM only)
- Get Transactions — View transfer history
- List Addresses — Check on-chain balances
- WaaS Fee Config — Configure your fee collection
