# Withdraw from Wallet - Self-Custody MPC (Manual)

Source: https://developers.bitgo.com/docs/withdraw-wallet-type-self-custody-mpc-manual

## Overview

You withdraw from self-custody MPC wallets by submitting transaction-request details to BitGo. BitGo uses the data you pass to construct an unsigned transaction that wallet admins can approve or wallet co-signers can sign if there are no approvals needed. After wallet admins approve the transaction, the parties complete the signing stages and broadcast it to the blockchain.

If you don't need this level of granular control for your withdrawals, see the integration guide for the [Express](/docs/withdraw-wallet-type-self-custody-mpc-simple) flow.

## Prerequisites

* [Get Started](/docs/get-started-intro)
* [Create Wallets](/docs/wallets-create-wallets)
* [Create Whitelists](/docs/wallets-whitelists-create)
* [Set Up External-Signer Mode](/docs/wallets-external-signer-mode) (Optional)
* [Deposit Assets](/docs/deposit-assets)

## Cookbook

Need just the steps? Expand the cookbook below to get started:

<Cookbook slug="withdraw-self-custody-mpc-manual" title="Withdraw - Self-Custody MPC (Manual)" />

## 1. Request Transaction

Request the transaction by specifying the transaction details and sending them to BitGo.

>Endpoint: [Create transaction request](/reference/v2wallettxrequestcreate)

```shell cURL
export WALLET_ID="<WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/wallet/$WALLET_ID/txrequests \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "idempotencyKey": "string",
    "intent": {
      "intentType": "payment",
      "sequenceId": "abc123",
      "comment": "string",
      "nonce": "string",
      "recipients": [
        {
          "address": {
            "address": "string",
            "options": {}
          },
          "amount": {
            "value": "100",
            "symbol": "gteth"
          },
          "data": "string"
        }
      ]
    },
    "apiVersion": "full",
    "preview": false
  }'
```
```js JavaScript
let params = {
  recipients: [
    {
      amount: 0.01 * 1e8,
      address: '2NFfxvXpAWjKng7enFougtvtxxCJ2hQEMo4',
    },
  ],
};
wallet.prebuildTransaction(params).then(function (transaction) {
  // print transaction details
  console.dir(transaction);
});
// This creates and stores a transaction request. If you don't want to store this data, pass the `preview` flag.
```

#### Step Result

BitGo uses the data you pass to build an unsigned transaction.

```json JSON
{
  "txRequestId": "string",
  "version": 0,
  "latest": true,
  "walletId": "string",
  "walletType": "cold",
  "enterpriseId": "string",
  "state": "initialized",
  "date": "2018-05-05T19:46:22.019Z",
  "userId": "string",
  "intent": {
    "nonce": "string",
    "memo": "string",
    "intentType": "claim",
    "sequenceId": "abc123",
    "comment": "string",
    "stakingRequestId": "string",
    "stakingAddress": "string",
    "amount": {
      "value": "100",
      "symbol": "usdc"
    }
  },
  "pendingApprovalId": "string",
  "transactions": [
    {
      "state": "initialized",
      "unsignedTx": {
        "serializedTxHex": "string",
        "signableHex": "string",
        "derivationPath": "string",
        "feeInfo": {
          "feeString": "string",
          "fee": 0
        }
      },
      "signatureShares": [
        {
          "from": "user",
          "to": "user",
          "share": "string"
        }
      ],
      "txHash": "string"
    }
  ]
}
```

## 2. Approve Transaction (Optional)

> 📘 **Note**
>
> You can't approve your own transactions - another admin must approve them.

>Endpoint: [Update Pending Approval](/reference/v2approvalupdate)

```shell cURL (Simple)
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export COIN="<ASSET_ID>"
export APPROVAL_ID="<APPROVAL_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export WALLET_PASSPHRASE="<YOUR_WALLET_PASSPHRASE>"

curl -X PUT \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/pendingApprovals/$APPROVAL_ID \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "state": "approved",
    "walletPassphrase": "'"$WALLET_PASSPHRASE"'"
  }'
```
```js JavaScript
const baseCoin = this.bitgoSDK.coin(initialPendingApproval.coin);
const pendingApproval = await baseCoin.pendingApprovals().get({ id: initialPendingApproval.id });
const result = await pendingApproval.approve(params);
```

#### Step Result

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

```json JSON
{
  "id": "66b66201c45ab3125fc2d8a77b541d12",
  "coin": "tsol",
  "wallet": "669569464cec3c82c9b524faf0d42087",
  "wallets": [],
  "enterprise": "6672220dd9e61ce3d62e9e2d710cbd6f",
  "organization": "66722210d9e61ce3d62e9e997100b40a",
  "bitgoOrg": "BitGo Trust",
  "creator": "6672175d79369c8ad556deaca06abeea",
  "createDate": "2024-08-09T18:37:53.078Z",
  "approvedDate": "2024-08-09T18:38:47.371Z",
  "info": {
    "type": "transactionRequestFull",
    "transactionRequestFull": {
      "txRequestId": "0b259f23-d5a8-47d0-8666-47a3df07e244",
      "videoApprovers": [],
      "intent": {
        "intentType": "payment",
        "recipients": [
          {
            "address": {
              "address": "ESda41265eU4typ7Q7MFnBuaYUvV3rYsJyrGQzqo6YZn"
            },
            "amount": {
              "value": "500000",
              "symbol": "tsol"
            }
          }
        ]
      }
    }
  },
  "approvers": [],
  "state": "approved",
  "scope": "wallet",
  "userIds": [
    "6672175d79369c8ad556deaca06abeea",
    "6672292d89bd038e41cfb93b6ee482f1"
  ],
  "approvalsRequired": 1,
  "singleRunResults": [],
  "txRequestId": "0b259f23-d5a8-47d0-8666-47a3df07e244",
  "resolvers": [
    {
      "user": "6672292d89bd038e41cfb93b6ee482f1",
      "date": "2024-08-09T18:38:45.245Z",
      "resolutionType": "pending",
      "resolutionAction": "approve"
    }
  ],
  "policyEvaluationId": "8dc3ffdd-50ea-4ab6-9742-963a12eb4f6c",
  "actions": [
    {
      "id": "d0bcc3af-b341-4b1c-9c7e-723ff4bc7259",
      "status": "COMPLETE",
      "name": "approvals.customer.walletAdmin",
      "parameters": {
        "minRequired": "1",
        "userIds": []
      },
      "resolvers": [
        {
          "user": "6672292d89bd038e41cfb93b6ee482f1",
          "date": "2024-08-09T18:38:45.245Z",
          "resolutionType": "pending",
          "resolutionAction": "approve"
        }
      ],
      "approvers": []
    }
  ],
  "resolutionOrder": [
    {
      "actions": [
        "d0bcc3af-b341-4b1c-9c7e-723ff4bc7259"
      ]
    }
  ]
}
```

## 3. Sign and Send Transaction

>Endpoint: [Sign MPC transaction](/reference/expresswalletsigntxtss)

```shell cURL
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export TX_REQUEST_ID="<TX_REQUEST_ID>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/wallet/$WALLET_ID/signtxtss \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "txRequestId": "'"$TX_REQUEST_ID"'",
    "prv": "string, # Either pass just your `prv` or pass your `walletPassphrase`, `keychain`, and `encryptedPrv`
    "walletPassphrase": "string",
    "keychain": {
      "encryptedPrv": "string"
    }
  }'
```
```shell cURL (External-Signer Mode)
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export TX_REQUEST_ID="<TX_REQUEST_ID>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/wallet/$WALLET_ID/signtxtss \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "txRequestId": "e2f0f3fc-8704-4c9c-946b-601e889175c1"
  }'
```
```js JavaScript
import dotenv from "dotenv";
dotenv.config();
import { BitGoAPI } from "@bitgo/sdk-api";
import { Tsol } from "@bitgo/sdk-coin-sol";
import { z } from "zod";

const env = z
  .object({
    USERNAME: z.string().min(1),
    PASSWORD: z.string().min(1),
    ENV: z.union([z.literal("test"), z.literal("staging"), z.literal("prod")]),
    OTP: z.string().optional(),
    WALLET_ID: z.string(),
  })
  .parse(process.env);

const bitgo = new BitGoAPI({ env: env.ENV });
bitgo.register("tsol", Tsol.createInstance);
const coin = bitgo.coin("tsol");

async function auth() {
  await bitgo.authenticate({
    username: env.USERNAME,
    password: env.PASSWORD,
    otp: env.OTP,
  });
  await bitgo.lock();
  await bitgo.unlock({ otp: "000000", duration: 3600 });
}

async function main() {
  await auth();

  const wallet = await coin.wallets().get({ id: env.WALLET_ID });

const params = {
  txRequestId: "string", // previously created txRequestId
  // one of:
  prv: "un-encrypted prv",
  // or
  keychain: {
    encryptedPrv: "encrypted prv"
    },
  walletPassphrase: "password to decrypt the encryptedPrv
};
wallet.signTransaction(params).then(function (result) {
  // print result details
  console.dir(result);
});
```

#### Step Result

```json JSON
{
  "apiVersion": "full",
  "txRequestId": "ed50bf41-cbc2-454e-81f5-840a024f802e",
  "walletId": "6695838af64d6e4dadf93838d29e78d3",
  "walletType": "hot",
  "version": 10,
  "enterpriseId": "6672220dd9e61ce3d62e9e2d710cbd6f",
  "organizationId": "66722210d9e61ce3d62e9e997100b40a",
  "userId": "6672175d79369c8ad556deaca06abeea",
  "initiatedBy": "6672175d79369c8ad556deaca06abeea",
  "updatedBy": "6672175d79369c8ad556deaca06abeea",
  "policiesChecked": true,
  "date": "2024-08-09T18:14:00.230Z",
  "createdDate": "2024-08-09T18:13:51.175Z",
  "intent": {
    "intentType": "payment",
    "recipients": [
      {
        "address": {
          "address": "ALUiFg9sduhfBibcsg3yNYpbAwJrTZtfyTDtia99VGbb"
        },
        "amount": {
          "value": "500000",
          "symbol": "tsol"
        }
      }
    ]
  },
  "intents": [
    {
      "intentType": "payment",
      "recipients": [
        {
          "address": {
            "address": "ALUiFg9sduhfBibcsg3yNYpbAwJrTZtfyTDtia99VGbb"
          },
          "amount": {
            "value": "500000",
            "symbol": "tsol"
          }
        }
      ]
    }
  ],
  "state": "delivered",
  "latest": true,
  "transactions": [
    {
      "state": "delivered",
      "signatureShares": [],
      "commitmentShares": [],
      "unsignedTx": {
        "parsedTx": {
          "minerFee": "10000",
          "spendAmount": "500000",
          "spendAmounts": [
            {
              "coinName": "tsol",
              "amountString": "500000"
            }
          ],
          "payGoFee": "0",
          "outputs": [
            {
              "address": "ALUiFg9sduhfBibcsg3yNYpbAwJrTZtfyTDtia99VGbb",
              "value": 500000,
              "wallet": "669569464cec3c82c9b524fa",
              "wallets": [
                "669569464cec3c82c9b524fa"
              ],
              "enterprise": "6672220dd9e61ce3d62e9e2d",
              "enterprises": [
                "6672220dd9e61ce3d62e9e2d"
              ],
              "valueString": "500000",
              "coinName": "tsol"
            }
          ],
          "inputs": [
            {
              "value": 500000,
              "address": "ESda41265eU4typ7Q7MFnBuaYUvV3rYsJyrGQzqo6YZn",
              "valueString": "500000"
            },
            {
              "value": 10000,
              "address": "ESda41265eU4typ7Q7MFnBuaYUvV3rYsJyrGQzqo6YZn",
              "valueString": "10000"
            }
          ],
          "type": "Send"
        },
        "serializedTxHex": "0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000da55307ce377d830dae26978d9ab29748267e7df4b84468d506ffbee8c97fab1e7a8b11c0258570216cc983f7ebbab5343137d819ea9253cfec951b5ca89bd0202010206c7b8ccc8ce4ba1bd0da19d7b714d84cf5084fd792dcba22c37a2cb5337008f311c96172044f1217c3784e8f02f49e2c8fc3591e81294ab54394f9d22fd7b7a8f5c9e29dd1e4640be4b7fa5bf8398571af71a77e2211e606bb739b40f03b787758ab68d09bf05bc4c43e5916c87b4662e6c293ed7038edfa99a207594980bee92000000000000000000000000000000000000000000000000000000000000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c07ca0341fb97d933ed85fa37b9ce126ad37bd608f45e8801653f7cc626e3b800204030205010404000000040200030c0200000020a1070000000000",
        "signableHex": "02010206c7b8ccc8ce4ba1bd0da19d7b714d84cf5084fd792dcba22c37a2cb5337008f311c96172044f1217c3784e8f02f49e2c8fc3591e81294ab54394f9d22fd7b7a8f5c9e29dd1e4640be4b7fa5bf8398571af71a77e2211e606bb739b40f03b787758ab68d09bf05bc4c43e5916c87b4662e6c293ed7038edfa99a207594980bee92000000000000000000000000000000000000000000000000000000000000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea9400000c07ca0341fb97d933ed85fa37b9ce126ad37bd608f45e8801653f7cc626e3b800204030205010404000000040200030c0200000020a1070000000000",
        "feeInfo": {
          "fee": 10000,
          "feeString": "10000"
        },
        "derivationPath": "m/0",
        "coinSpecific": {
          "nonceAddress": "7EYPYzqLd7MCzb6MjGiG2TmnJRAfDiEYbQMfLHFqY1Qg"
        }
      },
      "txHash": "5K5k73S8hCZhMMzEMkxoVwMefB7JYgEtb8bGvDx5uSt5bc6ZP9CbnDiFLDfpePhUrDCLvQGq7sCD4t9Pe5rJKCVY",
      "signedTx": {
        "id": "5K5k73S8hCZhMMzEMkxoVwMefB7JYgEtb8bGvDx5uSt5bc6ZP9CbnDiFLDfpePhUrDCLvQGq7sCD4t9Pe5rJKCVY",
        "tx": "AtepOXok+RemB6Q7Kne41m08yrSDx6Y3Zc6KoWw6wocNKrsiK6JiIUE8UY/5h+4hgxVj4wjJaMQHJlCCoe7FFwPaVTB843fYMNriaXjZqyl0gmfn30uERo1Qb/vujJf6seeosRwCWFcCFsyYP367q1NDE32BnqklPP7JUbXKib0CAgECBse4zMjOS6G9DaGde3FNhM9QhP15LcuiLDeiy1M3AI8xHJYXIETxIXw3hOjwL0niyPw1kegSlKtUOU+dIv17eo9cnindHkZAvkt/pb+DmFca9xp34iEeYGu3ObQPA7eHdYq2jQm/BbxMQ+WRbIe0Zi5sKT7XA47fqZogdZSYC+6SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGp9UXGSxWjuCKhF9z0peIzwNcMUWyGrNE2AYuqUAAAMB8oDQfuX2TPthfo3uc4SatN71gj0XogBZT98xibjuAAgQDAgUBBAQAAAAEAgADDAIAAAAgoQcAAAAAAA=="
      },
      "updatedDate": "2024-08-09T18:14:00.241Z",
      "createdDate": "2024-08-09T18:13:51.182Z"
    }
  ],
  "messages": [],
  "isCanceled": false
}

```

## Next

You can view your completed withdrawal in BitGo or on a blockchain explorer.

## See Also

* [MPC Error Recovery](/docs/withdraw-mpc-error-recovery)
* [API Reference: Create a signature share for the transaction request](/reference/v2wallettxrequestsignaturesharecreate)
* [API Reference: Create transaction request](/reference/v2wallettxrequestcreate)
* [API Reference: Get transaction requests by wallet](/reference/v2wallettxrequestget)
* [API Reference: Send Half-Signed Transaction](/reference/v2wallettxsend)
* [API Reference: Sign MPC transaction](/reference/expresswalletsigntxtss)
* [API Reference: Update Pending Approval](/reference/v2approvalupdate)
