Skip to content

Transfer

Send cryptocurrency from a customer's wallet to any address on supported blockchain networks.

Endpoint

POST /api/v1/wallet/customer/:customerID/transfer

Authentication

Requires API key authentication via X-API-Key header.

Path Parameters

ParameterTypeDescription
customerIDstringCustomer identifier

Request Body

FieldTypeRequiredDescription
networkstringYesBlockchain network (BTC, ETH, BSC, POL, TRX, SOL, etc.)
currencystringYesCurrency to send (BTC, ETH, USDT, USDC, etc.)
to_addressstringYesRecipient's blockchain address
amountstringYesAmount in smallest unit (satoshis, wei, lamports)
indexintegerNoAddress index to send from (default: 0)

Amount Units by Network

NetworkNative CurrencySmallest UnitDecimalsExample
BitcoinBTCsatoshi81 BTC = 100,000 ,000 satoshis
EthereumETHwei181 ETH = 1,000,000,000,000,000,000 wei
BSCBNBwei181 BNB = 1,000,000,000,000,000,000 wei
PolygonPOLwei181 POL = 1,000,000,000,000,000,000 wei
TronTRXsun61 TRX = 1,000,000 sun
SolanaSOLlamport91 SOL = 1,000,000,000 lamports

Example Request

javascript
// Send 0.01 BTC
const response = await fetch(
  'https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/user_12345/transfer',
  {
    method: 'POST',
    headers: {
      'X-API-Key': 'your-api-key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      network: 'BTC',
      currency: 'BTC',
      to_address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
      amount: '1000000', // 0.01 BTC in satoshis
      index: 0
    })
  }
);

const transfer = await response.json();
console.log('Transaction Hash:', transfer.txn_hash);
console.log('Status:', transfer.status);
python
import requests

# Send 50 USDT on BSC
response = requests.post(
    'https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/user_12345/transfer',
    headers={
        'X-API-Key': 'your-api-key',
        'Content-Type': 'application/json'
    },
    json={
        'network': 'BSC',
        'currency': 'USDT',
        'to_address': '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
        'amount': '50000000',  # 50 USDT (6 decimals)
        'index': 0
    }
)

transfer = response.json()
print(f"Transaction: {transfer['txn_hash']}")
print(f"Gas Fee: {transfer['gas_fee']}")
bash
curl -X POST https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/user_12345/transfer \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "network": "ETH",
    "currency": "ETH",
    "to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "amount": "100000000000000000",
    "index": 0
  }'

Response

Success Response (200 OK)

FieldTypeDescription
txn_hashstringTransaction hash/ID
networkstringBlockchain network
currencystringCurrency sent
from_addressstringSender address
to_addressstringRecipient address
amountstringAmount sent (in smallest unit)
gas_feestringTransaction fee paid
statusstringTransaction status (pending/confirmed/failed)
timestampstringTransaction timestamp
json
{
  "txn_hash": "0x1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p7q8r9s0t1u2v3w4x5y6z7a8b9c0d1e2f",
  "network": "ETH",
  "currency": "ETH",
  "from_address": "0x8B3192f2f0f0D7E4F5C3A1B9E2D7A6C5B4D3E2F1",
  "to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "amount": "100000000000000000",
  "gas_fee": "630000000000000",
  "status": "pending",
  "timestamp": "2026-01-03T04:18:00Z"
}

Error Responses

400 Bad Request

json
{
  "error": "invalid amount: insufficient balance"
}

404 Not Found

json
{
  "error": "Wallet not found"
}

500 Internal Server Error

json
{
  "error": "failed to broadcast transaction: network error"
}

Transaction Status

After initiating a transfer, track its status:

StatusDescriptionAction
pendingBroadcast to network, awaiting confirmationWait for confirmation
confirmedIncluded in block, transfer completeNo action needed
failedTransaction failed (insufficient gas, etc.)Retry or investigate

Use Cases

Withdrawal Flow

Complete withdrawal with validation and confirmation:

javascript
async function processWithdrawal(customerId, withdrawal) {
  // 1. Validate address format
  if (!isValidAddress(withdrawal.to_address, withdrawal.network)) {
    throw new Error('Invalid recipient address');
  }
  
  // 2. Estimate gas
  const estimate = await estimateGas(withdrawal);
  
  // 3. Check balance
  const balance = await getBalance(customerId, withdrawal.network);
  const total = parseFloat(withdrawal.amount) + parseFloat(estimate.estimated_fee);
  
  if (balance < total) {
    throw new Error('Insufficient balance for amount + gas fee');
  }
  
  // 4. Show confirmation
  const confirmed = confirm(
    `Send ${formatAmount(withdrawal.amount)} ${withdrawal.currency}\n` +
    `To: ${withdrawal.to_address}\n` +
    `Fee: ${estimate.estimated_fee}\n` +
    `Total: ${total}\n\n` +
    `Confirm withdrawal?`
  );
  
  if (!confirmed) return null;
  
  // 5. Execute transfer
  const response = await fetch(
    `https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/${customerId}/transfer`,
    {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(withdrawal)
    }
  );
  
  const transfer = await response.json();
  
  // 6. Save to database
  await saveWithdrawal({
    customer_id: customerId,
    txn_hash: transfer.txn_hash,
    amount: withdrawal.amount,
    status: transfer.status
  });
  
  return transfer;
}

Batch Transfers

Send to multiple recipients:

javascript
async function batchTransfer(customerId, recipients, network, currency) {
  const results = [];
  
  for (const recipient of recipients) {
    try {
      const response = await fetch(
        `https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/${customerId}/transfer`,
        {
          method: 'POST',
          headers: {
            'X-API-Key': process.env.API_KEY,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            network,
            currency,
            to_address: recipient.address,
            amount: recipient.amount,
            index: 0
          })
        }
      );
      
      const transfer = await response.json();
      results.push({
        recipient: recipient.address,
        txn_hash: transfer.txn_hash,
        status: 'success'
      });
      
      // Wait 1 second between transfers to avoid nonce conflicts
      await new Promise(resolve => setTimeout(resolve, 1000));
      
    } catch (error) {
      results.push({
        recipient: recipient.address,
        error: error.message,
        status: 'failed'
      });
    }
  }
  
  return results;
}

Best Practices

Transfer Safety

  • Validate addresses: Always validate recipient address format before transfer
  • Estimate first: Use estimate-gas before transfer
  • Check balance: Ensure sufficient balance for amount + gas fee
  • Confirm with user: Show clear confirmation with amount, address, and fees
  • Save txn_hash: Store transaction hash for tracking and support
  • Monitor status: Poll or use webhooks to track transaction confirmation
  • Handle errors: Implement retry logic for network failures
  • Test on testnet: Always test with testnet addresses first

Block Explorers

View transactions on block explorers:

NetworkExplorerURL Format
BitcoinBlockchain.comhttps://www.blockchain.com/btc/tx/{txn_hash}
EthereumEtherscanhttps://etherscan.io/tx/{txn_hash}
BSCBscScanhttps://bscscan.com/tx/{txn_hash}
PolygonPolygonScanhttps://polygonscan.com/tx/{txn_hash}
TronTronscanhttps://tronscan.org/#/transaction/{txn_hash}
SolanaSolscanhttps://solscan.io/tx/{txn_hash}

Built with ❤️ by Rach Finance