Overview

You can enhance security for a wallet by whitelisting crypto addresses and wallets. Whitelisting creates a wallet policy. Wallet policies dictate what actions trigger when a withdrawal initiates to a non-whitelisted address or wallet. For example, you can configure a wallet policy to automatically deny transactions to non-whitelisted addresses or require approval from an admin to proceed. Wallet policies are specific to individual wallets.

When you update a wallet policy, BitGo sends an email notification to all wallet users. However, BitGo doesn't send an email notification when you initially create a wallet policy. For your security, new whitelist policies for self-custody wallets lock 48 hours after creation and only BitGo support can unlock them.

Wallet policies differ from enterprise policies. To learn more about enterprise policies, see Policies Overview.

Note: Wallet-policies apply only to transactions that involve the BitGo key. Transactions that use the user key and the backup key bypass wallet policies. For more details about transacting with the backup key, see Set Up Wallet Recovery Wizard.

Prerequisites

Cookbook

Need just the steps? Expand the cookbook below to get started:

Create WhitelistsOpen Cookbook

Steps

1. Create Wallet Policy

Endpoint: Add wallet-policy rule

export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ID="<NAME_OF_WHITELIST>"
export ITEM="<ADDRESS_TO_WHITELIST>"

curl -X POST \
  "https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/policy/rule" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
  "coin": "'"$COIN"'",
  "id": "'"$ID"'",
  "type": "advancedWhitelist",
  "condition": {
    "add": {
      "type": "address",
      "item": "'"$ITEM"'"
    }
  },
  "action": {
    "type": "deny" # this configures what happens to transactions to non-whitelisted addresses
  }
}'

Step Result

If creating the whitelist doesn't require approval, it's now in effect.

{
  "id": "66e9f4bb549f6c3957f8977fe3ed6ab4",
  "users": [
    {
      "user": "62ab90e06dfda30007974f0a52a12995",
      "permissions": ["admin", "spend", "view"]
    }
  ],
  "coin": "tbtc4",
  "label": "Policy Wallet 2",
  "m": 2,
  "n": 3,
  "keys": [
    "66e9f4ac6bfc0956265268311208afd7",
    "66e9f4ac9231837dc9c945a6c4a725d0",
    "66e9f4adbfe06bac12b54a93d22b6dfc"
  ],
  "keySignatures": {
    "backupPub": "3a8f2c7d1e9b4a6f0c5d8e3b2a7f1c4d9e6b3a0f7c2d5e8b1a4f9c6d3e0b7f2a5c8d1e4b9a6f3c0d7e2b5a8f1c4d9e6b3a0f7c2d5e8b1a4f9c6d3e0b7f2a5c8",
    "bitgoPub": "1c4f9b2e7a3d6c0f5b8a1e4c9f2b5a8d3e6a0c3f6b9d2e5a8c1f4b7a0d3e6c9f2b5d8a1e4c7f0b3d6a9e2c5f8b1d4a7e0c3f6b9d2e5a8c1f4b7a0d3e6c9f2b5d8"
  },
  "enterprise": "62c5ae8174ac860007aff138a2d74df7",
  "organization": "5b8c2d7e1f4a9b3c6d0e5f8a",
  "bitgoOrg": "BitGo Trust",
  "tags": [
    "66e9f4bb549f6c3957f8977fe3ed6ab4",
    "62c5ae8174ac860007aff138a2d74df7"
  ],
  "disableTransactionNotifications": false,
  "freeze": {
    "time": "2024-09-17T21:29:31.000Z",
    "expires": "2024-09-17T21:29:31.000Z",
    "reason": "UserRequest",
    "referenceId": "cmrq4n8bk0hj20ez9bfx3m7va",
    "adminOrUserId": "62ab90e06dfda30007974f0a"
  },
  "deleted": false,
  "approvalsRequired": 1,
  "isCold": false,
  "coinSpecific": {},
  "admin": {
    "policy": {
      "date": "2024-09-18T22:05:21.220Z",
      "id": "66e9f4bb549f6c3957f897824915d45f",
      "label": "default",
      "rules": [
        {
          "id": "My First Wallet Policy for a Whitelist",
          "lockDate": "2025-09-18T22:05:21.219Z",
          "coin": "tbtc4",
          "type": "advancedWhitelist",
          "action": { "type": "deny", "userIds": [] },
          "condition": {
            "entries": [
              {
                "item": "2N6CWMMYXdufJyBa16KNorHs8AakXcqyHhf",
                "type": "address",
                "metaData": {
                  "whitelistDate": "2019-08-24T14:15:22Z"
                }
              }
            ]
          }
        }
      ],
      "version": 5,
      "latest": true
    }
  },
  "clientFlags": [],
  "walletFlags": [],
  "allowBackupKeySigning": false,
  "recoverable": true,
  "startDate": "2024-09-17T21:29:31.000Z",
  "type": "hot",
  "buildDefaults": {},
  "customChangeKeySignatures": {},
  "hasLargeNumberOfAddresses": false,
  "multisigType": "onchain",
  "hasReceiveTransferPolicy": false,
  "creator": "62ab90e06dfda30007974f0a",
  "walletFullyCreated": true,
  "config": {},
  "balance": 0,
  "balanceString": "0",
  "rbfBalance": 0,
  "rbfBalanceString": "0",
  "confirmedBalance": 0,
  "confirmedBalanceString": "0",
  "spendableBalance": 0,
  "spendableBalanceString": "0",
  "unspentCount": 0,
  "receiveAddress": {
    "id": "66e9f4bc549f6c3957f897a441904bff",
    "address": "tb1pv2jfqgu2py8unuwrgraegqqw3ds022lvx2f29hg2av504l4rtjhqld35ns",
    "chain": 40,
    "index": 1,
    "coin": "tbtc4",
    "wallet": "66e9f4bb549f6c3957f8977fe3ed6ab4",
    "coinSpecific": {
      "witnessScript": "5221031a4b6c3d9e8f2a5b7c0d1e4f7a2b5c8d3e6f9a0b1c4d7e0f3a6b9c2d5e8f1a4b7c021039d2e7f4a1b8c5d0e3f6a9b2c5d8e1f4a7b0c3d6e9f2a5b8c1d4e7f0a3b6c9d2e5f8a210453f8e2b9c6d3a0f7e4b1c8d5a2f9e6b3c0d7a4f1e8b5c2d9a6f3e0b7c4d1a8f5e2b9c6d3a053ae"
    }
  },
  "pendingApprovals": []
}

2. Approve Whitelist (Optional)

Note: If your new wallet policy requires approval, another admin must approve it.

Endpoint: Update Pending Approval

export APPROVAL_ID="<APPROVAL_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export OTP="<YOUR_OTP>"

curl -X PUT \
  https://app.bitgo-test.com/api/v2/pendingApprovals/$APPROVAL_ID \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "state": "approved",
    "otp": "'"$OTP"'"
  }'

Step Result

The approval completes and your whitelist is now in effect.

{
  "id": "66edb22fbef3fef723292c7b14ae01f3",
  "coin": "tbtc4",
  "wallet": "66e9aba320e050e4334b23285bfe3b2e",
  "wallets": [],
  "enterprise": "62c5ae8174ac860007aff138a2d74df7",
  "bitgoOrg": "BitGo Trust",
  "creator": "62ab90e06dfda30007974f0a52a12995",
  "createDate": "2024-09-20T17:34:39.157Z",
  "approvedDate": "2024-09-20T17:37:57.246Z",
  "info": {
    "type": "policyRuleRequest",
    "policyRuleRequest": {
      "action": "create",
      "update": {
        "id": "My First Wallet Policy for a Whitelist",
        "type": "advancedWhitelist",
        "action": { "type": "deny", "userIds": [] },
        "condition": {
          "add": {
            "type": "address",
            "item": "2N6CWMMYXdufJyBa16KNorHs8AakXcqyHhf"
          }
        },
        "coin": "tbtc4"
      }
    }
  },
  "approvers": [],
  "state": "approved",
  "scope": "wallet",
  "userIds": [
    "62ab90e06dfda30007974f0a52a12995",
    "627ff9325a5c1b0007c05a40d15e1522"
  ],
  "approvalsRequired": 1,
  "singleRunResults": [],
  "resolvers": [
    {
      "user": "627ff9325a5c1b0007c05a40d15e1522",
      "date": "2024-09-20T17:37:55.612Z",
      "resolutionType": "pending",
      "resolutionAction": "approve"
    }
  ],
  "actions": [],
  "resolutionOrder": []
}

Next

You can view whitelists and wallet policies using the Get Wallet by Coin and ID endpoint.

See Also

API Reference: Add Wallet-Policy Rule