Crypto-as-a-Service: Travel Rule
Whitelist withdrawal addresses and submit originator PII for Travel Rule compliance.
-
You query BitGo's VASP registry to identify the custodian for a destination address before whitelisting. BitGo uses TRUST and other sources to attribute addresses to VASPs. The response
vaspIdandsourcetell you which whitelist path to follow. -
You submit the destination address for compliance review. Pass the
vaspIdfrom step 1 for TRUST-verified or known-VASP addresses. For unknown VASPs, omitvaspIdand providenewVaspwith the name and domain.Prerequisites: Look up the VASP first to determine whether a
vaspIdis available. -
You poll the whitelist status until the address reaches
VERIFIEDbefore allowing a withdrawal. BitGo updates status asynchronously as it completes VASP verification or PII exchange. Poll every 30–60 seconds during active verification flows.
// 1. Look Up the Destination VASP
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export ENTERPRISE_ID="<CHILD_ENTERPRISE_ID>"
export WALLET_ADDRESS="<DESTINATION_WALLET_ADDRESS>"
export COIN="<ASSET_ID>" # for example: btc, eth, sol
curl -X GET \
"https://app.bitgo.com/api/travel-rule/v1/vasps/suggestions?walletAddress=$WALLET_ADDRESS&enterpriseId=$ENTERPRISE_ID&coin=$COIN" \
-H "Authorization: Bearer $ACCESS_TOKEN"
// 2. Whitelist the Address (Hosted VASP)
export WALLET_ID="<GO_ACCOUNT_WALLET_ID>"
export VASP_ID="<VASP_ID>"
curl -X POST \
https://app.bitgo.com/api/travel-rule/v1/whitelist \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"enterpriseId": "'"$ENTERPRISE_ID"'",
"walletId": "'"$WALLET_ID"'",
"coin": "'"$COIN"'",
"address": "'"$WALLET_ADDRESS"'",
"custodyType": "hosted",
"vaspId": "'"$VASP_ID"'",
"label": "My exchange account"
}'
// 3. Check Whitelist Status
curl -X GET \
"https://app.bitgo.com/api/travel-rule/v1/whitelist-address-status?address=$WALLET_ADDRESS&walletId=$WALLET_ID&enterpriseId=$ENTERPRISE_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN"
// 1. Look Up the Destination VASP
import superagent from 'superagent';
const ACCESS_TOKEN = '<SERVICE_USER_ACCESS_TOKEN>';
const enterpriseId = '<CHILD_ENTERPRISE_ID>';
const walletAddress = '<DESTINATION_WALLET_ADDRESS>';
const coin = '<ASSET_ID>';
let response = await superagent
.get('https://app.bitgo.com/api/travel-rule/v1/vasps/suggestions')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.query({ walletAddress, enterpriseId, coin });
// 2. Whitelist the Address (Hosted VASP)
const walletId = '<GO_ACCOUNT_WALLET_ID>';
const vaspId = response.body.vaspId;
response = await superagent
.post('https://app.bitgo.com/api/travel-rule/v1/whitelist')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.set('Content-Type', 'application/json')
.send({
enterpriseId,
walletId,
coin,
address: walletAddress,
custodyType: 'hosted',
vaspId,
label: 'My exchange account',
});
// 3. Check Whitelist Status
response = await superagent
.get('https://app.bitgo.com/api/travel-rule/v1/whitelist-address-status')
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.query({ address: walletAddress, walletId, enterpriseId });
// 1. Look Up the Destination VASP Response
{
"vaspId": "BFXUS2NXXX",
"name": "Bitfinex",
"internalVasp": false,
"proofQuality": "SIGNED",
"source": "TRUST_BULLETIN_BOARD"
}
// 2. Whitelist the Address Response
{
"whitelistId": "59cd72485007a239fb00282ed480da1f",
"status": "pending_vasp"
}
// 3. Check Whitelist Status Response
{
"whitelistResponse": [
{
"status": "VERIFIED",
"verifiedSource": "TRUST",
"address": "0xAbCd1234...",
"receiveAddress": "0xAbCd1234...",
"label": "My exchange account",
"coin": "eth",
"walletId": "59cd72485007a239fb00282ed480da1f",
"updatedAt": "2025-06-01T12:00:00.000Z"
}
]
}