Withdraw - Self-Custody Multisig (Simple)
Build, sign, and send withdrawals in one Express call. See the Guide.
-
Build and sign the transaction and send it to BitGo, all in one call using BitGo Express. The simple flow also supports sending to many recipients in 1 transaction using the
sendmanyendpoint.If your withdrawal doesn't require approval, BitGo applies the final signature using the BitGo key and broadcasts the transaction. If you have policy rules requiring approvals, the transaction remains pending until approved.
For UTXO assets, pass
txFormat: "psbt"in the request. -
If your withdrawal requires approval, another admin must approve it — you cannot approve your own transactions. Once approved, BitGo rebuilds the transaction with current fees, applies the final signature, and broadcasts to the blockchain.
// 1. Build, Sign, and Send Transaction
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export WALLET_PASSPHRASE="<YOUR_WALLET_PASSPHRASE>"
export ADDRESS="<DESTINATION_ADDRESS>"
export AMOUNT="<AMOUNT_IN_BASE_UNITS>"
curl -X POST \
http://$BITGO_EXPRESS_HOST/api/v2/$COIN/wallet/$WALLET_ID/sendcoins \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"address": "'"$ADDRESS"'",
"amount": "'"$AMOUNT"'",
"walletPassphrase": "'"$WALLET_PASSPHRASE"'",
"type": "transfer",
"txFormat": "psbt"
}'
// 2. Approve Transaction (Optional)
export APPROVAL_ID="<APPROVAL_ID>"
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"'"
}'
// 1. Build, Sign, and Send Transaction
const tx = await fundedWallet.send({
address: `<DESTINATION_ADDRESS>`,
amount: `<AMOUNT>`,
walletPassphrase: process.env.PASSWORD,
txFormat: `psbt`, // required for UTXO assets
type: `transfer`
});
// 2. Approve Transaction (Optional)
const baseCoin = bitgo.coin(initialPendingApproval.coin);
const pendingApproval = await baseCoin.pendingApprovals().get({ id: initialPendingApproval.id });
const result = await pendingApproval.approve(params);
// 1. Build, Sign, and Send Transaction Response
{
"transfer": {
"id": "6553ee12d5a49ecc9baccdcbe0563448",
"coin": "tbtc4",
"wallet": "6553e933288be490293ae748efafeaaf",
"walletType": "hot",
"txid": "e7648c85edac7f9870e511b4ef95b62b1878556791bd52ac715cb2cd4b466e6f",
"type": "send",
"value": -68581,
"state": "signed"
},
"txid": "e7648c85edac7f9870e511b4ef95b62b1878556791bd52ac715cb2cd4b466e6f",
"status": "signed"
}
// 1. Build, Sign, and Send Transaction Response (pending approval)
{
"error": "triggered all transactions policy",
"pendingApproval": {
"id": "655686880765186f0b3e9e88e1bdd0f4",
"state": "pendingApproval",
"approvalsRequired": 1
}
}
// 2. Approve Transaction Response
{
"id": "655686880765186f0b3e9e88e1bdd0f4",
"state": "approved"
}