Withdraw from Wallet - Self-Custody Multisig Hot (Simple)
Overview
The simple withdrawal flow for self-custody multisignature hot wallets enables you to build, sign, and send transactions, all in 1 call, using BitGo Express. The simple flow suffices for most use cases. If you require more granular control, see the integration guide for the advanced flow.
The simple flow also supports sending to many recipients in 1 transaction, lowering the aggregate amount of blockchain fees when compared to creating multiple transactions. Sending to many aligns with the simple transaction flow, where in 1 call you build, sign, and send a half-signed transaction to BitGo. BitGo then uses the BitGo key to create a fully signed send-to-many transaction.
Just like with the advanced flow, you can configure wallet policies to require approvals on withdrawals. Once the transaction is half signed and approved, you send it to BitGo for final signing and broadcasting to the blockchain.
Prerequisites
- Get Started
- Create Wallets
- Create Whitelists (Optional)
- Deposit assets into your wallet
1. Build, Sign, and Send Transaction
Build and sign the transaction and send it to BitGo, all in 1 call. The following example is shows the minimum required parameters for sending bitcoin.
Endpoints:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
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:3080/api/v2/$COIN/wallet/$WALLET_ID/sendmany \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d '{ "walletPassphrase": "'"$WALLET_PASSPHRASE"'", "recipients": [ { "address": "'"$ADDRESS"'", "amount": "'"$AMOUNT"'" } ], "type": "transfer", "txFormat": "psbt" # required for UTXO assets }'
Note: If you're building transactions for a UTXO asset in quick succession, BitGo recommends reserving unspents by passing the
reservation
andexpireTime
parameters. Reserving unspents avoids errors by ensuring the UTXO aren't included in subsequent builds.
Step Result
BitGo uses the data you pass to build a half-signed transaction. The following example withdrawals 10,000 sats of TBTC4.
If your withdrawal doesn't require approval, BitGo applies the final signature using the BitGo key and broadcasts the transaction to the blockchain. If you Create Policy Rules to require approvals on withdrawals, the transaction remains in a pending-approval status until a wallet admin approves it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
{ "transfer": { "entries": [ { "address": "2N1poiHTi5ur8hz5QBhNoy88bYzqrWYvBbV", "wallet": "6553e933288be490293ae748efafeaaf", "value": -100000, "valueString": "-100000" }, { "address": "2Mz2uycewBnqGbzR74B9zF1dPaZw2PJjjwy", "wallet": "6553e933288be490293ae748efafeaaf", "value": -100000, "valueString": "-100000" }, { "address": "2N2JC4Fv1LWo1efTh8Ei1tGBwcZvonJqH6Z", "wallet": "6553e933288be490293ae748efafeaaf", "value": -100000, "valueString": "-100000" }, { "address": "2N69sUcfB32YFS7Q7KnpysoV4FMSP5RQUb7", "wallet": "6553e933288be490293ae748efafeaaf", "value": -100000, "valueString": "-100000" }, { "address": "2Myx8nY8ReERqUwu9H96Lb2K4yYjs3xY8GH", "value": 10000, "valueString": "10000", "isChange": false, "isPayGo": false }, { "address": "tb1q5xtred89revxp789r6dmvyf74vgecczp2ch2hvhlj8anjkcepqtspu7j7d", "wallet": "6553e933288be490293ae748efafeaaf", "value": 331419, "valueString": "331419", "isChange": true, "isPayGo": false } ], "id": "6553ee12d5a49ecc9baccdcbe0563448", "coin": "tbtc4", "wallet": "6553e933288be490293ae748efafeaaf", "walletType": "hot", "enterprise": "62c5ae8174ac860007aff138a2d74df7", "txid": "e7648c85edac7f9870e511b4ef95b62b1878556791bd52ac715cb2cd4b466e6f", "txidType": "transactionHash", "height": 999999999, "heightId": "999999999-6553ee12d5a49ecc9baccdcbe0563448", "date": "2023-11-14T22:00:51.655Z", "type": "send", "value": -68581, "valueString": "-68581", "intendedValueString": "-68581", "baseValue": -10000, "baseValueString": "-10000", "baseValueWithoutFees": -10000, "baseValueWithoutFeesString": "-10000", "feeString": "58581", "payGoFee": 0, "payGoFeeString": "0", "usd": -24.3138393906, "usdRate": 35452.73383387, "state": "signed", "instant": false, "isReward": false, "isFee": false, "tags": [ "6553e933288be490293ae748efafeaaf", "62c5ae8174ac860007aff138a2d74df7" ], "history": [ { "date": "2023-11-14T22:00:51.654Z", "action": "signed" }, { "date": "2023-11-14T22:00:50.982Z", "user": "62ab90e06dfda30007974f0a52a12995", "action": "created" } ], "signedDate": "2023-11-14T22:00:51.654Z", "vSize": 643, "metadata": [], "signedTime": "2023-11-14T22:00:51.654Z", "createdTime": "2023-11-14T22:00:50.982Z" }, "txid": "e7648c85edac7f9870e511b4ef95b62b1878556791bd52ac715cb2cd4b466e6f", "tx": "01000000000104f79f5a4eb395daa55599afc88cb36413a2e7fe755a575833a7d5044b2edff42900000000232200200310e0ff3cdca1f56a7bfa29b130173041dc37d3a79c185bcd22b91ad214cdf3ffffffffd5c76ddf8e1424dfae9b11027ee81cace9ca2c9f5885ab8b59d527dcf048cdb10000000023220020fe79161f81c6536ffaed66f31d29bd29c8f672e5298bb74794d95aeca191368effffffff1c5e85a0d0f72fa97809aa8fe007b734d2afd510284d24fa7cb63f254061b9bc00000000232200205cdefd195a48e242e7193a7deb99d9c811944a3d0a2a23291263557d72ae9c19ffffffff0a8510e7c8d3e7d25b56c32359d5a5a886d5681e7ed9f960c90acce0c396e4f900000000232200207f311c104e7eedeb3408e0d516a229b212159590fe45180d6203f7423f928e49ffffffff02102700000000000017a914498d775e94669934939d5494a9651401577b1faa879b0e050000000000220020a1963cb4e51e5860f8e51e9bb6113eab119c6041562eabb2ff91fb395b190817040047304402203b783246c3847d07a22de396944842b9fbc1376d4828eb10b0781597cbd1488702202a21bc8a7621cd33f011bd7c1d4ef66ce895c687ad1122f9c2594a498bff774c0147304402202fc02dd0e81ea254b80ece01a8a72371220e7b8c864243b1b04d4bc09c18060b02204259c89fb37a420777acad4b0effdffd9d2f25906ca3f4cb30f3c1c8af880dc00169522103c02e9ce2cbe477702e0d8284a479dc6481d0e3f2f3d11c9d1af0a4854df96eb62102a7318bad55a6dc71ff2efceaadff31bfc223bef8b8509604bbfdbbae77875fda2103dabd87d3efb0028c03d0d3aea1f58294f82cfcfa3ed450872ee4ec8cb146fe4e53ae0400483045022100b535a4d9d2e3bd2d980e8c0cfe936acaa26460c477f8763bafa6bcf095c88db602205f372432e48969a08d844ea49ffc678baa36cccd9d3f62cba3b01b07b1b4415a0147304402201c7caa9a1ccb80d98af2a02341db9ea4b9d1cd2606f78a9d940c222e9fd4b2c10220250a81ed74cf19aa1a4ed263308fb159c569bfd585a39c1803bc20c1ef32e4f6016952210377862047d8848c1a91de4fa78a354e198082bfb174ee8efa4cb697ebe4d96efd21036996a148aa85269cb1fc80d5a6643695bd03b0f23faa8ec51080b5a2b7348ac421028c57ff93d260387ba090fc914122efa62a4ac9e8a1b5abdc5e56399686b421a153ae0400483045022100fcef9fa4481dd9b9176f2b8ac07e56db3ed761adf9f2042bb5e9ab7ffb332f5302207bd4ac4216b41fca47f57778a758bf06a66225e142661ba7e8cf78d003588d6d0147304402201fe2ae51fa4e2488ccd7a2041d5061d8c531708660116287001873951c0e26f20220794a0423672fa88ec5ea196693d561c9ccdf678b1645e7efec83c0189445b02d016952210279e294cb5c7b75b0cd0a4d6fe94fdcbae53dbe12eece3ecc02edefbcffe2b3ab2102ed3a458ad2077b1c5a46646c3a5e2f39b0ada3bd59a3ab7e6bba915d2ce886592103b45bcfd5e06da1fabfab25afde9c3b483ec111c7c22e4478e63be8f6ed12346553ae0400483045022100e69ba5cfbafd28ffd33db6616115c1c8af628b8d7c48cf4dbe67feba2226a347022044b46ba257379680789e9903bf818d3e1cf550d7699037733fa0bf95fe3ad1830147304402207d5a9f93040ed380fe1a41e99991aa6ec8cec458e4da917212b20f9ee89e60dd02206e588bfcb2ff01664cd99092a137e7b3292feea0a8adc3ca0d9efd22b923cd460169522102dcf53d1927f945d7b2ad38d77c9c47affa4fe3018d7be64e9e9a04b4420977f721035e1ad2ff6c207f82b3711a5560ad25f00d1040101eaa072970d662d59ceee99e210216dafba93a02bfce39b7f164e76faa452647698f9aba6528c7594dd4a137d25153ae00000000", "status": "signed" }
2. Approve Transaction (Optional)
Note: If you configure an approval requirement for withdrawals, you can't approve your own transactions - another admin must approve them.
Endpoint: Update Pending Approval
1 2 3 4 5 6 7 8 9 10 11 12
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
Once approved, BitGo rebuilds the half-signed transaction, applying the most up-to-date fees. BitGo then applies the final signature using the BitGo key and broadcasts the transaction to the blockchain.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
{ "id": "655686880765186f0b3e9e88e1bdd0f4", "coin": "tbtc4", "wallet": "6553e933288be490293ae748efafeaaf", "enterprise": "62c5ae8174ac860007aff138a2d74df7", "creator": "62ab90e06dfda30007974f0a52a12995", "createDate": "2023-11-16T21:15:52.703Z", "info": { "type": "transactionRequest", "transactionRequest": { "requestedAmount": "10000", "fee": 45242, "sourceWallet": "6553e933288be490293ae748efafeaaf", "policyUniqueId": "6553e933288be490293ae753", "recipients": [ { "address": "2N3sBpM1RnWRMXnEVoUWnM7xtYzL756JE2Q", "amount": "10000", "_id": "655686880765186f0b3e9e8a" } ], "buildParams": { "recipients": [ { "address": "2N3sBpM1RnWRMXnEVoUWnM7xtYzL756JE2Q", "amount": "10000" } ], "changeAddressType": [ "p2trMusig2", "p2wsh", "p2shP2wsh", "p2sh", "p2tr" ], "txFormat": "psbt" }, "coinSpecific": { "tbtc4": { "txHex": "01000000000101eac5e7d68acfc2349672fb99094e79c2006e5fd663475c8f1eb6f29095970b740100000000ffffffff02102700000000000017a914747e6b7f5db53794b0fc01d95878e0f9b6db96738746c1020000000000220020efb9deaabeab5d62cecc363f24cd6deafcdd14d93d8734f7f01ed3953e732a640500483045022100cd6c221e4cefbb51aa82087d86e7d089b2473eb21ae809dba89eb9f13c4caf19022000f3b7f1b7fec2dc49cbfce35baa69ca37ab9ee8e51c779cde5b98a653f3e142010000695221029bde55661e4f359cf9ca2d1846c235e752f760ed6d65e2018f821253e78b3c722103f2b4a813ab79e4fb46edf3a6a87fb154a85b45810158e949f41a3fce3c9bf574210399a6d766f6d3a3843f8479446ee766b5745dc15c24d1db5149214d27987bd29453ae00000000" } }, "validTransaction": "01000000000101eac5e7d68acfc2349672fb99094e79c2006e5fd663475c8f1eb6f29095970b740100000000ffffffff02102700000000000017a914747e6b7f5db53794b0fc01d95878e0f9b6db96738746c1020000000000220020efb9deaabeab5d62cecc363f24cd6deafcdd14d93d8734f7f01ed3953e732a640400483045022100cd6c221e4cefbb51aa82087d86e7d089b2473eb21ae809dba89eb9f13c4caf19022000f3b7f1b7fec2dc49cbfce35baa69ca37ab9ee8e51c779cde5b98a653f3e14201473044022002b246c43722fec49858caf6b0605a0d01a6b6c13c964b84bf272604fd3951780220324ee44ba3ce8febb154c317e688a5f6ed410ad8e2bd77c5678bf1f7f3eb45f601695221029bde55661e4f359cf9ca2d1846c235e752f760ed6d65e2018f821253e78b3c722103f2b4a813ab79e4fb46edf3a6a87fb154a85b45810158e949f41a3fce3c9bf574210399a6d766f6d3a3843f8479446ee766b5745dc15c24d1db5149214d27987bd29453ae00000000", "validTransactionHash": "ff40ccd5c8ba75ffdce27d8584b6e8ee625cb3f71f7cbb6d072a445a97c2c8c3" } }, "state": "approved", "scope": "wallet", "userIds": [ "62ab90e06dfda30007974f0a52a12995", "627ff9325a5c1b0007c05a40d15e1522" ], "approvalsRequired": 1, "singleRunResults": [ { "ruleId": "Custody Enterprise Transaction ID Verification", "triggered": false, "_id": "655686880765186f0b3e9e89" } ], "resolvers": [ { "user": "627ff9325a5c1b0007c05a40d15e1522", "date": "2023-11-16T21:33:24.644Z", "resolutionType": "pending" } ] }
Next
You can view your completed withdrawal in BitGo or on a blockchain explorer.