Consolidate Unspents - Manual

Build, sign, and send a UTXO consolidation transaction using separate API calls. See the Guide.

  1. Begin the manual flow by building a consolidation transaction. You configure parameters such as minValue, maxValue, minConfirms, and targetAddress to control which unspents the transaction consolidates and where it sends the result.

    Consolidating unspents is only available for self-custody wallets. Consolidation transactions for bitcoin automatically opt-in to acceleration using Replace-By-Fee (RBF).

    Prerequisites: Complete Get Started, Create Wallets, and Create Addresses.

    API Reference

  2. Using the txHex and txInfo returned in the prior call, sign the transaction using your private key. You can use either the standard Express endpoint or the external-signer mode endpoint depending on your signing setup.

    API Reference

  3. Using the txHex returned in the prior step, send the half-signed transaction to BitGo. If your transaction does not require approval, BitGo applies the final signature using the BitGo key and broadcasts the transaction to the blockchain. If you have policy rules requiring approvals, the transaction remains in a pending-approval status until a wallet admin approves it.

    API Reference

  4. If the transaction triggered a policy rule and requires approval, another admin must approve it. First, list pending approvals to get the pending-approval ID, then update the pending approval to approve it. You cannot approve your own transactions.

    Once approved, BitGo rebuilds the half-signed transaction, applying the most up-to-date fees.

    API Reference

// 1. Build Consolidation
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export TARGET_ADDRESS="<DESIRED_TARGET_ADDRESS>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/consolidateUnspents \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "feeRate": null,
    "maxFeeRate": null,
    "maxFeePercentage": 0,
    "feeTxConfirmTarget": 0,
    "bulk": true,
    "minValue": "2000000",
    "maxValue": "2000000",
    "minHeight": 0,
    "minConfirms": 0,
    "enforceMinConfirmsForChange": true,
    "limit": 0,
    "numUnspentsToMake": 0,
    "targetAddress": "'"$TARGET_ADDRESS"'",
    "txFormat": "legacy"
}'
// 2. Sign Consolidation
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export COIN="<ASSET_ID>"
export WALLET="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export PRV="<YOUR_PRIVATE_KEY>"
export USER_PUB="<YOUR_USER_PUBLIC_KEY>"
export BACKUP_PUB="<YOUR_BACKUP_PUBLIC_KEY>"
export BITGO_PUB="<BITGO_PUBLIC_KEY>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/signtx \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "prv": "'"$PRV"'",
    "pubs": [
      "'"$USER_PUB"'",
      "'"$BACKUP_PUB"'",
      "'"$BITGO_PUB"'"
    ],
    "txPrebuild": {
      "wallet": ""'"$WALLET"'"",
      "txHex": "<TX_HEX_FROM_STEP_1>",
      "txInfo": "<TX_INFO_FROM_STEP_1>",
      "feeInfo": "<FEE_INFO_FROM_STEP_1>",
      "coin": "<ASSET_ID>"
    }
  }'
// 3. Send Consolidation
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/tx/send \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "halfSigned": {
    "txHex": "<HALF_SIGNED_TX_HEX_FROM_STEP_2>"
  }
}'
// 4. Approve Consolidation
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X GET \
  https://app.bitgo-test.com/api/v2/pendingApprovals \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

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"'"
  }'
Response
// 1. Build Consolidation Response
{
  "txHex": "01000000000101d58f82d996dd872012675adadf4606734906b25a413f6e2ee535c0c10aef96020000000000ffffffff028de888000000000017a914c91aa24f65827eecec775037d886f2952b73cbe48740420f000000000017a9149304d18497b9bfe9532778a0f06d9fff3b3befaf870500473044022023d7210ba6d8bbd7a28b8af226f40f7235caab79156f93f9c9969fc459ea7f73022050fbdca788fba3de686b66b3501853695ff9d6f375867470207d233b099576e001000069522103d4788cda52f91c1f6c82eb91491ca76108c9c5f0839bc4f02eccc55fedb3311c210391bcef9dcc89570a79ba3c7514e65cd48e766a8868eca2769fa9242fdcc796662102ef3c5ebac4b54df70dea1bb2655126368be10ca0462382fcb730e55cddd2dd6a53aec8b11400",
  "txInfo": {
    "changeAddresses": [
      "2MvrwRYBAuRtPTiZ5MyKg42Ke55W3fZJfZS"
    ],
    "nOutputs": 2,
    "nP2SHInputs": 0,
    "nSegwitInputs": 1,
    "unspents": [
      {
        "id": "003f688cc349f1fca8ac5ffa21671ca911b6ef351085c60733ed8c2ebf162cb8:2",
        "address": "2MsKxhhkDo5WaLaYRGA9Cr3iSQPyXsu6Fi2",
        "value": 0,
        "valueString": "2000000",
        "blockHeight": 0,
        "date": "2017-03-25T23:01:40.248Z",
        "coinbase": true,
        "wallet": "59cd72485007a239fb00282ed480da1f",
        "fromWallet": "59cd72485007a239fb00282ed480da1f",
        "chain": 0,
        "index": 0,
        "redeemScript": "522102f1e990044d2a8be43d5b500bbdcb36277b97a4b07e01c5101ae8ec1568bfd6532103dab7dc82f2fc8c28200c1bdeca9c4cf181e0ca257395829cbd599395048afb57210205422e711827d8356f2fb75334d863941dd7eb45bd5788fa231dc5fa755135b653ae",
        "witnessScript": "52210351311cd81144e6cbdba561d24dfc22644cb02d053339d4beace03231b3be4f372103a8d0c1a375b9ee1a2411f9f8e18373be7f228b18260f63bbfca48809170ed08b2103c3bd8bd074657bbe9ee6714b31a4a54b6fd5b5cda0e1030122f9bf46b5034f6b53ae",
        "isSegwit": true
      }
    ],
    "walletAddressDetails": {
      "id": "string",
      "address": "2MvrwRYBAuRtPTiZ5MyKg42Ke55W3fZJfZS",
      "chain": 1,
      "index": 0,
      "coin": "string",
      "lastNonce": -1,
      "wallet": "59cd72485007a239fb00282ed480da1f",
      "coinSpecific": {
        "xlm": {
          "memoId": "1",
          "rootAddress": "GCTTCPH4IIDK7P72FFAEJ3ZFN6WDHJH6GGMRPHPM56ZWGIQ7B3XTIJAM"
        },
        "txlm": {
          "memoId": "1",
          "rootAddress": "GCTTCPH4IIDK7P72FFAEJ3ZFN6WDHJH6GGMRPHPM56ZWGIQ7B3XTIJAM"
        }
      },
      "balance": {
        "updated": "2019-08-24T14:15:22Z",
        "balance": 50000,
        "balanceString": "50000",
        "totalReceived": 0,
        "totalSent": 0,
        "confirmedBalanceString": "40000",
        "spendableBalanceString": "40000"
      },
      "label": "Bob's Hot Wallet Address",
      "addressType": "p2sh"
    }
  },
  "feeInfo": {
    "size": 776,
    "fee": 38800,
    "feeRate": null,
    "payGoFee": 0,
    "payGoFeeString": "0"
  }
}

// 2. Sign Consolidation Response
{
  "txHex": "010000000001010e4d3af014f9efe311062965d561b67f78a1759e7016605cd506ddd7041762d50000000023220020510ded26d712922bbb61bc68ef6766f836a03527820cbdc8b1551914eb467dafffffffff02102700000000000017a9145a581567fd2a630e61e34a696ab3bb887972886d87ad0f010000000000225120850d0ab466d15cb1565dd528d4d9709f3e46f41d41fe6d94aa01378e626983990500483045022100db45a8d94ee2144f7e29baa855d94a2bf0120707a7ab2fc93734ed94af972c460220558d00b91275aafc7805dfaaf9ab796adbe9f4e66dc467f7eb93b790671a323201000069522103c10ac628c880629ed0fd2a0563a898f4882baca45e15668a4d3064cf1ea379882103e56f84be4460080618ef869bb7b07096880760f748ba23efab533c2359f923bd21020ae81372264b5eac5c9dc7fe0b9a32bad00771c3a2c71f6e2c971823c3182ed653ae00000000"
}

// 3. Send Consolidation Response
{
  "transfer": {
    "entries": [
      {
        "address": "2NAVwU9KtPyE4h3RyHkhbLgQQvrc4EuSXD3",
        "wallet": "654ec786c07fe8dc0dcfe03916ec5bb0",
        "value": -100000,
        "valueString": "-100000"
      },
      {
        "address": "2Mw241n14gJx2PcK2kijidZ2BPGeJBdwp1A",
        "value": 10000,
        "valueString": "10000",
        "isChange": false,
        "isPayGo": false
      },
      {
        "address": "tb1pq9m0lqjg4lfa0rj9wzjjjumk3l6vecndt8wla5756ktre6h6fexqg7z0vq",
        "wallet": "654ec786c07fe8dc0dcfe03916ec5bb0",
        "value": 70013,
        "valueString": "70013",
        "isChange": true,
        "isPayGo": false
      }
    ],
    "id": "65528cde229f765c57a8f4d1eb762908",
    "coin": "tbtc4",
    "wallet": "654ec786c07fe8dc0dcfe03916ec5bb0",
    "walletType": "hot",
    "enterprise": "62c5ae8174ac860007aff138a2d74df7",
    "txid": "c68916ddc1672ec62c474ef0839ec479ad9b2dabc2249177ce6be6247f81dfe7",
    "txidType": "transactionHash",
    "height": 999999999,
    "heightId": "999999999-65528cde229f765c57a8f4d1eb762908",
    "date": "2023-11-13T20:53:51.445Z",
    "type": "send",
    "value": -29987,
    "valueString": "-29987",
    "intendedValueString": "-29987",
    "baseValue": -10000,
    "baseValueString": "-10000",
    "baseValueWithoutFees": -10000,
    "baseValueWithoutFeesString": "-10000",
    "feeString": "19987",
    "payGoFee": 0,
    "payGoFeeString": "0",
    "usd": -11.0275843085,
    "usdRate": 36774.55,
    "state": "signed",
    "instant": false,
    "isReward": false,
    "isFee": false,
    "tags": [
      "654ec786c07fe8dc0dcfe03916ec5bb0",
      "62c5ae8174ac860007aff138a2d74df7"
    ],
    "history": [
      { "date": "2023-11-13T20:53:51.444Z", "action": "signed" },
      {
        "date": "2023-11-13T20:53:50.646Z",
        "user": "62ab90e06dfda30007974f0a52a12995",
        "action": "created"
      }
    ],
    "signedDate": "2023-11-13T20:53:51.444Z",
    "vSize": 225,
    "metadata": [],
    "signedTime": "2023-11-13T20:53:51.444Z",
    "createdTime": "2023-11-13T20:53:50.646Z"
  },
  "txid": "c68916ddc1672ec62c474ef0839ec479ad9b2dabc2249177ce6be6247f81dfe7",
  "tx": "01000000000101c76ddd01e185e12e995c6f4f36bd440867296d3f224751d73432d465be93478100000000232200204fe0358ee98bef039832fa3a4dc96cb4b265448f3d89c4a05a997a3481f3da6effffffff02102700000000000017a9142962c500562c9db56434702a629ff08fcbd5add0877d110100000000002251200176ff8248afd3d78e4570a52973768ff4cce26d59ddfed3d4d5963ceafa4e4c0400483045022100c4db3db14398d5cc4c9a2a3e4a8fa4fa3b8960ad80eb840e51e182f7561cf6c102207a6410e68aaf7327a1daed83838a39b96e37e22783d879a838640035b6059bcc0147304402205888b2863bb8fc296ed51374db2d03c7fdc746fd0d6c5ceebbe2246bb76b67840220730c8b8395285767ef1049c40cd6cbdecfb5ecfefd795ac2053b28b7a6b0790f0169522103a4c6a0aa167ef75fcf4a96c53b2dd20aee3afa19d1bc2ec4354328ae87c0976621022e4d77a9d0fecafc7ad4f9cfd9144082cf146b27de945ba26d22f26438c5784b2103ee2fef2c21d48bbd0d3813c71269fca6e1bff51e676b1f0131aa29afceb08f8853ae00000000",
  "status": "signed"
}

// 4. Approve Consolidation Response
{
  "id": "65529448bd87efe59c3b0156ddfce867",
  "coin": "tbtc4",
  "wallet": "654ec786c07fe8dc0dcfe03916ec5bb0",
  "enterprise": "62c5ae8174ac860007aff138a2d74df7",
  "creator": "62ab90e06dfda30007974f0a52a12995",
  "createDate": "2023-11-13T21:25:28.022Z",
  "info": {
    "type": "transactionRequest",
    "transactionRequest": {
      "requestedAmount": "10000",
      "fee": 20451,
      "sourceWallet": "654ec786c07fe8dc0dcfe03916ec5bb0",
      "policyUniqueId": "654ec786c07fe8dc0dcfe03f",
      "recipients": [
        {
          "address": "2N1UvKhtSHLUa9YomSH7n9YMFCkMG2pbmsQ",
          "amount": "10000",
          "_id": "65529448bd87efe59c3b0158"
        }
      ]
    }
  },
  "state": "approved",
  "scope": "wallet",
  "userIds": [
    "62ab90e06dfda30007974f0a52a12995",
    "621d08a634ad8a0007fcddffd7c429cc"
  ],
  "approvalsRequired": 1,
  "resolvers": [
    {
      "user": "621d08a634ad8a0007fcddffd7c429cc",
      "date": "2023-11-13T21:44:27.794Z",
      "resolutionType": "pending"
    }
  ]
}