Create Receive Addresses

Overview

Create unique receive addresses for each individual or entity in your enterprise. Using unique addresses for each customer or transaction improves privacy, simplifies accounting, and makes it easier to track deposits.

In the custody starter architecture, receive addresses are typically created on the deposit/withdraw wallet since this is where customer deposits arrive. However, you can create addresses on any wallet in your architecture.

Prerequisites

Create Receive Address

Create a new receive address on your deposit/withdraw wallet. You can create unlimited addresses for a wallet.

Endpoint: Create Address

export COIN="<ASSET_ID>"
export WALLET_ID="<DEPOSIT_WITHDRAW_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export LABEL="Customer ABC"

curl -X POST \
  "https://app.bitgo.com/api/v2/$COIN/wallet/$WALLET_ID/address" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "label": "'"$LABEL"'"
  }'
const { BitGo } = require('bitgo');

const accessToken = '<YOUR_ACCESS_TOKEN>';

const bitgo = new BitGo({
  accessToken: accessToken,
  env: 'prod',
});

async function createReceiveAddress() {
  const wallet = await bitgo.coin('<ASSET_ID>').wallets().get({
    id: '<DEPOSIT_WITHDRAW_WALLET_ID>'
  });

  const address = await wallet.createAddress({
    label: 'Customer ABC'
  });

  console.log('New Receive Address Created:');
  console.log('Address:', address.address);
  console.log('Label:', address.label);
  console.log('Address ID:', address.id);
}

createReceiveAddress();

Step Result

{
  "id": "631283e10e052800066295e210da142a",
  "address": "bc1q8w3mcwt83tpmmr4reas3xt8t7rcshu7gztszew",
  "chain": 10,
  "index": 2,
  "coin": "btc",
  "wallet": "7849948ac0623f81f74f63dbd8351d5g",
  "label": "Customer ABC",
  "coinSpecific": {
    "redeemScript": "...",
    "witnessScript": "..."
  },
  "addressType": "p2shP2wsh"
}
📘

Note

Some networks, such as Ethereum, do not immediately return a new multisignature address, since creating a new address requires a blockchain transaction. The blockchain must confirm this transaction before you can use the address. The parameter pendingChainInitialization identifies if an address is awaiting confirmation.

Create Multiple Addresses

For bulk onboarding, create multiple addresses programmatically.

const { BitGo } = require('bitgo');

const accessToken = '<YOUR_ACCESS_TOKEN>';

const bitgo = new BitGo({
  accessToken: accessToken,
  env: 'prod',
});

async function createAddressesForCustomers(customerList) {
  const wallet = await bitgo.coin('<ASSET_ID>').wallets().get({
    id: '<DEPOSIT_WITHDRAW_WALLET_ID>'
  });

  const addresses = [];

  for (const customer of customerList) {
    const address = await wallet.createAddress({
      label: `Customer ${customer.id} - ${customer.name}`
    });

    addresses.push({
      customerId: customer.id,
      customerName: customer.name,
      address: address.address,
      addressId: address.id
    });

    console.log(`Created address for ${customer.name}: ${address.address}`);
  }

  return addresses;
}

// Example usage
const customers = [
  { id: '001', name: 'Alice' },
  { id: '002', name: 'Bob' },
  { id: '003', name: 'Charlie' }
];

createAddressesForCustomers(customers);

List Wallet Addresses

View all addresses created for a wallet.

Endpoint: List Addresses

export COIN="<ASSET_ID>"
export WALLET_ID="<WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X GET \
  "https://app.bitgo.com/api/v2/$COIN/wallet/$WALLET_ID/addresses" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
const wallet = await bitgo.coin('<ASSET_ID>').wallets().get({ id: '<WALLET_ID>' });
const addresses = await wallet.addresses();

console.log('Wallet Addresses:');
addresses.addresses.forEach(addr => {
  console.log(`  ${addr.label || 'No label'}: ${addr.address}`);
});

Step Result

{
  "coin": "btc",
  "totalAddressCount": 5,
  "addresses": [
    {
      "id": "631283e10e052800066295e210da142a",
      "address": "bc1q8w3mcwt83tpmmr4reas3xt8t7rcshu7gztszew",
      "chain": 10,
      "index": 0,
      "coin": "btc",
      "wallet": "7849948ac0623f81f74f63dbd8351d5g",
      "label": "Default Receive Address"
    },
    {
      "id": "631283e10e052800066295e210da142b",
      "address": "bc1p...",
      "chain": 10,
      "index": 1,
      "coin": "btc",
      "wallet": "7849948ac0623f81f74f63dbd8351d5g",
      "label": "Customer ABC"
    },
    {
      "id": "631283e10e052800066295e210da142c",
      "address": "bc1q...",
      "chain": 10,
      "index": 2,
      "coin": "btc",
      "wallet": "7849948ac0623f81f74f63dbd8351d5g",
      "label": "Customer 002 - Bob"
    }
  ]
}

Address Considerations

UTXO-Based Assets (BTC, LTC, etc.)

  • Funds received at any address are immediately spendable from the wallet.
  • No consolidation required.
  • Each address can receive unlimited transactions.

Account-Based Assets (ETH, MATIC, etc.)

  • Funds received at sub-addresses must be consolidated to the base address before spending.
  • Consider gas costs when consolidating.
  • See Consolidate Account Balance for details.

Address Labeling Best Practices

  • Use descriptive labels that identify the customer or purpose.
  • Include customer IDs for easy database correlation.
  • Avoid storing sensitive personal information in labels.

Webhooks for Deposit Monitoring

Configure webhooks to receive notifications when deposits arrive at your addresses. This enables automated deposit processing.

For details, see Webhooks Overview.

Architecture Complete

Your custody starter architecture is now set up.

ComponentStatus
Custody Wallet (Cold Storage)Created with strict policies
Standby Wallet (Hot)Created with admin approval policy
Deposit/Withdraw Wallet (Hot)Created with no policies
Custody-Standby WhitelistConfigured
Standby-Deposit WhitelistConfigured
Receive AddressesReady to create for customers

Next Steps

See Also