Create Wallets
Overview
You can generate or manually create multisignature and MPC wallets with BitGo. Once created, you can configure security policies for your wallets, dictating how transactions can occur.
Generate Wallets
Create a self-custody hot wallet and keys all in one step. When you generate a wallet, BitGo does the following:
- Creates a user keychain locally on your machine and uploads an encrypted key, using the provided passphrase (skipped if
userKey
is provided). - Creates a backup keychain locally on your machine and uploads the public key.
- Creates a BitGo keychain on a BitGo hardware-security module (HSM) and a backup key if
backupXpubProvider
is set to true. - Creates a wallet on the blockchain with these 3 public keys.
Manually Create Wallets
Create a custody wallet or a self-custody, hot or cold, wallet. You must create your own keys prior to manually creating a self-custody wallet.
Prerequisites
- Get Started
- If manually creating self-custody wallets, Create MPC Keys or Create Multisignature Keys, depending on the wallet type.
Create Wallet
Endpoints:
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export COIN="<ASSET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ENTERPRISE="<YOUR_ENTERPRISE_ID>"
export PASSPHRASE="<YOUR_BITGO_LOGIN_PASSPHRASE>"
export LABEL="<YOUR_WALLET_NAME>"
curl -X POST \
http://$BITGO_EXPRESS_HOST/api/v2/$COIN/wallet/generate \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"enterprise": "'"$ENTERPRISE"'",
"passphrase": "'"$PASSPHRASE"'",
"label": "'"$LABEL"'",
"multisigType": "onchain",
"type": "hot"
}'
export COIN="<ASSET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ENTERPRISE="<YOUR_ENTERPRISE_ID>"
export LABEL="<YOUR_WALLET_NAME>"
export USER_KEY_ID="<USER_KEY_ID>"
export BACKUP_KEY_ID="<BACKUP_KEY_ID>"
export BITGO_KEY_ID="<BITGO_KEY_ID>"
curl -X POST \
https://app.bitgo-test.com/api/v2/$COIN/wallet/add \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"enterprise": "'"$ENTERPRISE"'",
"label": "'"$LABEL"'",
"multisigType": "onchain",
"type": "cold",
"m": 2,
"n": 3,
"keys": [
"'"$USER_KEY_ID"'",
"'"$BACKUP_KEY_ID"'",
"'"$BITGO_KEY_ID"'"
]
}'
const { BitGo } = require('bitgo');
// Fill in with actual access token
const accessToken = '<YOUR_ACCESS_TOKEN>';
// Initialize the SDK
const bitgo = new BitGo({
accessToken: accessToken,
env: 'test',
});
// Generate hot wallet
async function createHotWalletSimple() {
const newWallet = await bitgo.coin('tbtc4').wallets().generateWallet({
label: '<YOUR_WALLET_NAME>',
passphrase: '<YOUR_BITGO_LOGIN_PASSPHRASE>',
enterprise: '<YOUR_ENTERPRISE_ID>'
});
console.log(JSON.stringify(newWallet, undefined, 2));
}
const { BitGo } = require('bitgo');
// Fill in with actual access token
const accessToken = '<YOUR_ACCESS_TOKEN>';
// Initialize the SDK
const bitgo = new BitGo({
accessToken: accessToken,
env: 'test',
});
// Manually create hot wallet
async function createHotWalletAdvanced() {
const options = {
label: '<YOUR_WALLET_NAME>',
m: 2,
n: 3,
// prerequisite is to create keys before hand
keys: ['<USER_KEY_ID>', '<BACKUP_KEY_ID>', '<BITGO_KEY_ID>'],
};
const newWallet = await bitgo.coin('tbtc4').wallets().add(options);
console.log(JSON.stringify(newWallet, undefined, 2));
}
console.log(JSON.stringify(newWallet, undefined, 2));
}
// Manually create cold wallet
async function createColdWalletAdvanced() {
const options = {
label: '<YOUR_WALLET_NAME>',
isCold: true,
m: 2,
n: 3,
// prerequisite is to create keys before hand
keys: ['<USER_KEY_ID>', '<BACKUP_KEY_ID>', '<BITGO_KEY_ID>'],
};
const newWallet = await bitgo.coin('tbtc4').wallets().add(options);
console.log(JSON.stringify(newWallet, undefined, 2));
}
// Manually create custody wallet
async function createCustodyWalletAdvanced() {
const options = {
label: '<YOUR_WALLET_NAME>',
isCustodial: true,
};
const newWallet = await bitgo.coin('tbtc4').wallets().add(options);
console.log(JSON.stringify(newWallet, undefined, 2));
}
Step Result
Note: This response contains critical key material. Save it in a secure place.
{
"wallet": {
"id": "6849948ac0623f81f74f63dbd8351d4f",
"users": [
{
"user": "62ab90e06dfda30007974f0a52a12995",
"permissions": ["admin", "spend", "view"]
}
],
"coin": "tbtc4",
"label": "TBTC4 Self-Custody Hot Wallet",
"m": 2,
"n": 3,
"keys": [
"68499487e6c77351bd3bbf04281fa8bb",
"68499487cd07fc57de18f6481baa1903",
"6849948902be620840a384c148d19979"
],
"keySignatures": {
"backupPub": "204119cfa9a1d0a00bd0e30b2c43d535dff36af557d1846385df7d47dc1a0092cc1eefbdc41b9f619f6d89d3597656c5e3f6b1ccc4b1f4331861c6b0993296eab9",
"bitgoPub": "20784ad236269cd93ba6b922831cc102fdfba193e6be5e88ba6234de1e5232b4ba65db1a0e47f1fd8d038bd23878632e4c376b475b36e4a0d9516797c12630963b"
},
"enterprise": "62c5ae8174ac860007aff138a2d74df7",
"organization": "62c5ae8174ac860007aff1555ffb960d",
"bitgoOrg": "BitGo Trust",
"tags": [
"6849948ac0623f81f74f63dbd8351d4f",
"62c5ae8174ac860007aff138a2d74df7"
],
"disableTransactionNotifications": false,
"freeze": {},
"deleted": false,
"approvalsRequired": 1,
"isCold": false,
"coinSpecific": {},
"admin": {},
"clientFlags": [],
"walletFlags": [],
"allowBackupKeySigning": false,
"recoverable": false,
"startDate": "2025-06-11T14:36:58.000Z",
"type": "hot",
"buildDefaults": {},
"customChangeKeySignatures": {},
"hasLargeNumberOfAddresses": false,
"multisigType": "onchain",
"hasReceiveTransferPolicy": false,
"creator": "62ab90e06dfda30007974f0a52a12995",
"config": {},
"balance": 0,
"balanceString": "0",
"rbfBalance": 0,
"rbfBalanceString": "0",
"confirmedBalance": 0,
"confirmedBalanceString": "0",
"spendableBalance": 0,
"spendableBalanceString": "0",
"unspentCount": 0,
"receiveAddress": {
"id": "6849948ac0623f81f74f63ead377af97",
"address": "tb1pz65k93su0vdccm9tewv5c00nxjytmxxqwxjn6lcn4pu7d9fa5jtqvg0glr",
"chain": 40,
"index": 0,
"coin": "tbtc4",
"wallet": "6849948ac0623f81f74f63dbd8351d4f",
"coinSpecific": { "_requestId": "54b5f74006db93a38ab7-0000" }
},
"pendingApprovals": []
},
"userKeychain": {
"id": "68499487e6c77351bd3bbf04281fa8bb",
"pub": "xpub661MyMwAqRbcEst4tb4F36AfvoFtAy7U9viB7zapRqNnXhPknsPwNqhxpD1CqMGSGhq3hDMKQR1Br8gGxYygoR6SGic3XdJoTEzM5v9wyFy",
"ethAddress": "0x944b592f950d24dd12dc405527e355d3d3922856",
"source": "user",
"type": "independent",
"encryptedPrv": "{\"iv\":\"9sYzOP14H+eAN16iN40RLA==\",\"v\":1,\"iter\":10000,\"ks\":256,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"P5CWbEjWcu0=\",\"ct\":\"yTNEuBHcOjrZAeqSeGSgxu1Anls6zuC7W6AcwNuL4dwGbc3A6OSs68fpzN2ZpFj4EP1BazjiuT0iwZXIaEY/aYsGLNF/DMkTa16sngzx16Az20sBroYdvcfqXoroTZR63N6hoeepQst19nTuPYp/By/NYR/nhxo=\"}",
"prv": "xprv9s21ZrQH143K2PobnZXEfxDwNmRPmWPcnhnaKcBCsVqoeu4cFL5gq3PUxv8jZXassaVMAxdrZAi91kyY2RVRkoNW2x5JKSBnozsB4Nc4m5H"
},
"backupKeychain": {
"id": "68499487cd07fc57de18f6481baa1903",
"pub": "xpub661MyMwAqRbcEfnfBkVRk9BB1SrYaFR884ndYpmNXnci6U2wrAQCsFiD21c49Aq7EvtK6QFzDzMwmFKVqi1bTL7kmuCEJ78bFn9Rq6NyLDV",
"ethAddress": "0x1907355a7022491140d0e7e3447303c94c2be0f1",
"source": "backup",
"type": "independent",
"encryptedPrv": "{\"iv\":\"EHdXHSWtgxzMhys9XAK9kg==\",\"v\":1,\"iter\":10000,\"ks\":256,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"oAQFS3LUV38=\",\"ct\":\"za2qiPkBjSkxD6XJBYvCyLfFtZMjZG00eUOKMfuzKNODp5/zDnRSPhMj28nMxayWowf8XLyyN7lMxJXBYxohuZ95ii5XWK6sw4SxKrD6+cejiMawWFIFTCNc0WhrcnTsYpyMYL1U5Ncpcd2/5sPUNOBWaK5XAdA=\"}",
"prv": "xprv9s21ZrQH143K2BiC5ixRP1ESTR24AnhGkqs2kSMkyT5jDfhoJd5xKTPjAkMwgvkHDmvBTMq6ck679XNTtdd1fz1DmxifzPi8HkkP7GjKyfj"
},
"bitgoKeychain": {
"id": "6849948902be620840a384c148d19979",
"pub": "xpub661MyMwAqRbcGCXsEAmctkLstGa92f5ugiD3hvCL3Wyt8BqHYGCVsL2x6PgNgJeq8Aabtz92sMzq4Ezac459QkDmxowKqoL35gNJXEJDdeo",
"ethAddress": "0x92f48893ab51470c2253a97aea8071da70bbd461",
"source": "bitgo",
"type": "independent",
"isBitGo": true,
"isTrust": false,
"hsmType": "institutional"
},
"responseType": "WalletWithKeychains",
"warning": "Be sure to backup the backup keychain -- it is not stored anywhere else!"
}
{
"id": "68499ba3df2bb455ecae0cf2bf0639a9",
"users": [
{
"user": "62ab90e06dfda30007974f0a52a12995",
"permissions": ["admin", "spend", "view"]
}
],
"coin": "tbtc4",
"label": "TBTC4 Self-Custody Cold Wallet",
"m": 2,
"n": 3,
"keys": [
"68499a2877a6825438c3339f769ee77a",
"68499a6402be620840a448139781826f",
"68499a86c0623f81f750411c0f625b03"
],
"keySignatures": {},
"enterprise": "62c5ae8174ac860007aff138a2d74df7",
"organization": "62c5ae8174ac860007aff1555ffb960d",
"bitgoOrg": "BitGo Trust",
"tags": [
"68499ba3df2bb455ecae0cf2bf0639a9",
"62c5ae8174ac860007aff138a2d74df7"
],
"disableTransactionNotifications": false,
"freeze": {},
"deleted": false,
"approvalsRequired": 1,
"isCold": true,
"coinSpecific": {},
"admin": {},
"clientFlags": [],
"walletFlags": [],
"allowBackupKeySigning": false,
"recoverable": false,
"startDate": "2025-06-11T15:07:15.000Z",
"type": "cold",
"buildDefaults": {},
"customChangeKeySignatures": {},
"hasLargeNumberOfAddresses": false,
"multisigType": "onchain",
"hasReceiveTransferPolicy": false,
"creator": "62ab90e06dfda30007974f0a52a12995",
"config": {},
"balance": 0,
"balanceString": "0",
"rbfBalance": 0,
"rbfBalanceString": "0",
"confirmedBalance": 0,
"confirmedBalanceString": "0",
"spendableBalance": 0,
"spendableBalanceString": "0",
"unspentCount": 0,
"receiveAddress": {
"id": "68499ba3df2bb455ecae0d0b3d0df225",
"address": "tb1q8w3mcwt83tpmmr4reas3xt8t7rcshu7gztszewpcw4qvda9nf9fssxxdz2",
"chain": 20,
"index": 0,
"coin": "tbtc4",
"wallet": "68499ba3df2bb455ecae0cf2bf0639a9",
"coinSpecific": {
"witnessScript": "52210373af0b03d8d67ec6a4d35dac1d6a5e0f4266da68edc5101924d1129cadca9a1a2102641338f685cc6955c3f1798bd9fcf319b1fe27cc926c620b355cd598d764401c2102d080f5ee11112938a2af311445aca38a0d8957406f5e07e0be3515893ad084dd53ae",
"_requestId": "cmbs32qec0paa0f4qccunhmkz"
}
},
"pendingApprovals": []
}
Note: Some networks, such as Ethereum, don't 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.You can save the wallet ID in the response, then wait for the blockchain to confirm the address before using it.
Next
See Also
Updated 22 days ago