Search documentation

Search across BlockBee docs, API endpoints, webhooks and guides.

Self-Custodial Wallet Payouts

View as Markdown

BlockBee's Self-Custodial Wallet system allows you to automate sending cryptocurrency payments to multiple addresses. This system requires API Key V2 and uses TSS cryptography so BlockBee cannot access your funds without your API key.

Overview

Key Concepts

  • Self-Custodial Wallet: Your own cryptocurrency wallet managed by BlockBee with advanced security features
  • Payout Request: Individual payment instruction (address + amount) for a specific cryptocurrency
  • Payout: Collection of Payout Requests that are processed together
  • API Key V2: Required authentication for Self-Custodial Wallet operations

How It Works

  1. Create Payout Requests: Define the addresses and amounts you want to send
  2. Process Payouts: Send the requests to be executed by your Self-Custodial Wallet
  3. Monitor Status: Track the progress and completion of your payouts
  4. Manage Balance: Check your wallet balance and address

Prerequisites

  • API Key V2: You must upgrade from API Key V1 to V2 to use Self-Custodial Wallet
  • Sufficient Balance: Ensure your Self-Custodial Wallet has enough funds for payouts + fees
  • Supported Cryptocurrencies: Check our cryptocurrencies page for supported tickers

Recommended Workflow

1. Create and Process Payouts

You have two approaches for creating payouts:

Option A: Bulk Process (Recommended)

Use the bulk process endpoint to create and send multiple payouts efficiently in one request:

const payoutData = {
  outputs: {
    '0xA6B78B56ee062185E405a1DDDD18cE8fcBC4395d': 0.2,
    '0x18B211A1Ba5880C7d62C250B6441C2400d588589': 0.1
  }
};

const response = await fetch('https://api.blockbee.io/btc/payout/request/bulk/process/?apikey=YOUR_API_KEY_V2', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'apikey': 'YOUR_API_KEY_V2'
  },
  body: JSON.stringify(payoutData)
});

const result = await response.json();
const payoutId = result.payout_info.id;
console.log('Payout ID:', payoutId);

Option B: Individual Requests + Batch Processing (Exchange-style)

Create individual payout requests and then combine them into a single payout for batch processing, similar to how exchanges handle withdrawals. This approach is ideal for platforms that need to:

  1. Create withdrawals when users request them
  2. Create payout requests for each withdrawal
  3. Batch process when enough requests accumulate or after a time period
  4. Create and process payouts to execute all pending withdrawals
// Step 1: Create individual payout requests (when users request withdrawals)
const payoutRequests = [
  {
    address: '0x1234567890123456789012345678901234567890',
    amount: 0.2
  },
  {
    address: '0x0987654321098765432109876543210987654321',
    amount: 0.1
  }
];

// Create multiple payout requests at once
const bulkRequests = {
  requests: payoutRequests
};

const bulkResponse = await fetch('https://api.blockbee.io/btc/payout/request/bulk/?apikey=YOUR_API_KEY_V2', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'apikey': 'YOUR_API_KEY_V2'
  },
  body: JSON.stringify(bulkRequests)
});

const bulkResult = await bulkResponse.json();
const requestIds = bulkResult.request_ids; // Array of request IDs

// Step 2: Create payout from individual requests (batch processing)
const payoutResponse = await fetch('https://api.blockbee.io/payout/create/?apikey=YOUR_API_KEY_V2', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'apikey': 'YOUR_API_KEY_V2'
  },
  body: JSON.stringify({
    payout_request_ids: requestIds.join(',')
  })
});

const payoutResult = await payoutResponse.json();
const payoutId = payoutResult.payout_info.id;
console.log('Payout ID:', payoutId);

// Step 3: Process the payout (execute all withdrawals)
const processResponse = await fetch(`https://api.blockbee.io/payout/process/${payoutId}/?apikey=YOUR_API_KEY_V2`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'apikey': 'YOUR_API_KEY_V2'
  }
});

const processResult = await processResponse.json();
console.log('Payout processed:', processResult.status);

Exchange Workflow Example

Here's how a typical exchange would implement this workflow:

  1. User requests withdrawal → Create payout request immediately
  2. Accumulate requests → Store payout request IDs
  3. Batch processing → When threshold reached or time passed, create payout
  4. Execute withdrawals → Process the payout to send all transactions

Alternative: Create Multiple Requests at Once You can also create multiple payout requests in one call using the bulk endpoint:

JavaScript
// Create multiple payout requests at once
const bulkRequests = {
  requests: [
    { address: '0x1234567890123456789012345678901234567890', amount: 0.2 },
    { address: '0x0987654321098765432109876543210987654321', amount: 0.1 }
  ]
};

const bulkResponse = await fetch('https://api.blockbee.io/btc/payout/request/bulk/?apikey=YOUR_API_KEY_V2', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'apikey': 'YOUR_API_KEY_V2'
  },
  body: JSON.stringify(bulkRequests)
});

const bulkResult = await bulkResponse.json();
const requestIds = bulkResult.request_ids; // Array of request IDs

2. Monitor Payout Status

Track the progress of your payouts using the payout ID:

const statusData = {
  payout_id: payoutId
};

const statusResponse = await fetch('https://api.blockbee.io/payout/status/?apikey=YOUR_API_KEY_V2', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'apikey': 'YOUR_API_KEY_V2'
  },
  body: JSON.stringify(statusData)
});

const status = await statusResponse.json();
console.log('Payout status:', status.payout_info.status);

Payout Statuses

  • Created: Payout has been created and is queued for processing
  • Processing: The settlement transaction is being executed and confirmed on-chain
  • Done: Confirmed on-chain. txid and blockchain_fee are set
  • Rejected: You rejected the payout in your BlockBee dashboard, or it had no valid outputs, so it will not be processed
  • Expired: The settlement transaction was dropped by the network before confirming. No funds left your wallet and the batch is intact. Retry it with the same payout_id (see Expired payouts), or create a new payout
  • Error: The attempt failed with no live transaction remaining. Recovered the same way as expired

Expired Payouts

In rare cases a broadcast transaction is dropped by the network and never confirms. BlockBee monitors every settlement transaction; when one is deemed dead the payout is marked expired, and its error field explains why:

  • Payout expired: transaction not found on any node, please retry or issue a new payout
  • Payout expired: transaction unconfirmed after 72 hours, please retry or issue a new payout

No funds have left your wallet, and the batch is intact. Both expired and error payouts are recovered the same way: call Process Payout by ID again with the same payout_id. There is no deadline, so an expired payout stays retryable indefinitely.

Before re-sending anything, BlockBee verifies every previous attempt on-chain:

  • If an earlier settlement confirmed, nothing is re-sent. The payout completes (done) with its txid and blockchain_fee.
  • If an earlier settlement is still pending in a mempool, nothing is re-sent. The payout resolves when it does.
  • Only when every previous attempt is provably dead is a fresh transaction broadcast.

A retry can never pay the same outputs twice. If you prefer, create a new payout with new requests instead. Both paths are safe.

Error Handling

For detailed information about common errors and their solutions, see our Error Handling Guide.

Security Considerations

  • API Key V2 Security: Use advanced security practices for API Key V2
  • Recovery Key: Safely store your recovery key for emergency access
  • Address Validation: Always verify destination addresses before creating payouts
  • HTTPS Only: Always use HTTPS for API requests in production

Relevant API Endpoints

For detailed information about all payout-related endpoints, see our API Reference. Key endpoints include:

  • Payout Management: Create, process, and monitor payouts
  • Wallet Operations: Check balance, get addresses
  • Request Management: Create and manage payout requests
  • Status Tracking: Monitor payout and request status

Testing

Testing Workflow

  1. Get Test LTC: Add a small amount of Litecoin to your Self-Custodial Wallet
  2. Create Test Payouts: Use the examples above with small amounts (0.001 LTC)
  3. Monitor Results: Check payout status and verify transactions
  4. Scale Up: Once testing is successful, increase amounts gradually

Test with Litecoin

Litecoin is ideal for testing because:

  • Low fees: Minimal transaction costs
  • Fast confirmations: Quick transaction processing
  • Widely supported: Available on most exchanges
  • Stable network: Reliable for testing purposes

Use the ticker ltc in your API calls for Litecoin testing.