Crypto-as-a-Service
Withdraw Fiat to Bank Account
Overview
You can build fiat withdrawals from your Go Account by submitting transaction details to BitGo. BitGo uses the data you pass to construct an unsigned transaction that wallet admins can approve. After video verification, a BitGo Bank & Trust operator signs the transaction with the user key. Then a different BitGo Bank & Trust operator downloads and signs the transaction in the BitGo Offline Vault Console (OVC). BitGo then uploads and broadcasts the transaction.
Fiat Withdrawal Methods
You can withdraw fiat from a Go Account to a bank account using either ACH or Wire transfers. The method BitGo uses depends on the destination bank account supported payment rails.
| Feature | ACH Withdrawal | Wire Withdrawal |
|---|---|---|
| Use Case | Low-to-medium value, recurring withdrawals, and settlements that can wait 1–2 business days. | Large or urgent withdrawals, cross-border payouts, and client settlements. |
| Settlement Time | 1–2 business days. | Same day (if submitted before cutoff). |
| Bank Support | US bank accounts only. | US and international bank accounts. |
| Currency | USD to USD only. | Varies by currency and region. |
| Requirements | BitGo-approved recipient bank. | BitGo-approved destination bank. May require a reference/memo ID. |
Note
When transacting from Go Accounts, ensure ticker symbols use the ofc prefix, which denotes the tokenized asset is off chain. To learn more, see Asset Ticker Symbols.
Prerequisites
Cookbook
Need just the steps? Expand the cookbook below to get started:
Withdraw Fiat to Bank AccountOpen Cookbook1. Add Bank Account
Your bank accounts must be approved by BitGo. When you add a bank account to an enterprise it goes through a screening process. BitGo approves most bank accounts within 48 hours.
To ensure BitGo approves your bank account, ensure the following are accurate:
| Requirement | Description |
|---|---|
| Routing Number | For US bank accounts, provide a valid 9-digit ABA routingNumber. BitGo validates routing numbers against the Federal Reserve directory. Invalid routing numbers result in rejection. |
| Owner Name Match | The ownerName must match the name of your end user. For example, if your enterprise is "John Doe", the bank account owner should be "John Doe". |
| Account Type | You must specify the accountType field as checking or saving. This field is required for both ACH and wire transactions to process correctly. |
Endpoint: Add bank account
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export ENTERPRISE_ID="<CHILD_ENTERPRISE_ID>"
curl -X POST \
https://app.bitgo-test.com/api/v2/bankaccounts \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"type": "ach",
"name": "JPMorgan Chase Bank",
"accountNumber": "123456789012",
"routingNumber": "021000021", # This is a valid sample routing number (JPMorgan Chase Bank)
"currency": "tfiatusd",
"enterpriseId": "'"$ENTERPRISE_ID"'",
"ownerName": "John Doe",
"accountType": "checking",
"description": "ACH deposits and withdrawals",
"ownerAddressLine1": "123 Main Street",
"ownerAddressLine2": "Suite 400",
"ownerAddressCityLocality": "New York",
"ownerAddressStateProvince": "NY",
"ownerAddressPostalCode": "10001",
"ownerAddressCountryCode": "US",
"bankAddressLine1": "456 Financial Plaza",
"bankAddressCityLocality": "New York",
"bankAddressStateProvince": "NY",
"bankAddressPostalCode": "10005",
"bankAddressCountryCode": "US"
}'
const BitGoJS = require('bitgo');
const bitgo = new BitGoJS.BitGo({
accessToken: '<SERVICE_USER_ACCESS_TOKEN>',
env: 'test',
});
async function addBankAccount() {
const bankAccount = await bitgo.post('/api/v2/bankaccounts').send({
type: 'ach',
name: 'JPMorgan Chase Bank',
accountNumber: '123456789012',
routingNumber: '021000021', // This is a valid sample routing number (JPMorgan Chase Bank)
currency: 'tfiatusd', // The 'fiat' prefix identifies the asset is held in a bank account
enterpriseId: '<CHILD_ENTERPRISE_ID>',
ownerName: 'John Doe',
accountType: 'checking',
description: 'ACH deposits and withdrawals',
ownerAddressLine1: '123 Main Street',
ownerAddressLine2: 'Suite 400',
ownerAddressCityLocality: 'New York',
ownerAddressStateProvince: 'NY',
ownerAddressPostalCode: '10001',
ownerAddressCountryCode: 'US',
bankAddressLine1: '456 Financial Plaza',
bankAddressCityLocality: 'New York',
bankAddressStateProvince: 'NY',
bankAddressPostalCode: '10005',
bankAddressCountryCode: 'US',
});
console.log('Bank Account Added:', bankAccount);
return bankAccount;
}
addBankAccount().catch(console.error);
Step Result
The response includes the bank account details and the verificationState field indicating the current approval status.
{
"id": "60749ab75f8c4500060f5a8b244dd0cb",
"idHash": "c2f4cf5555a66d77",
"currency": "tfiatusd",
"token": "tusd",
"name": "JPMorgan Chase Bank",
"shortCountryCode": "US",
"accountNumber": "****9012",
"enterpriseId": "1032e75c451052000436831deb797af1",
"ownerName": "John Doe",
"verificationState": "pending",
"createdAt": "2025-01-12T15:30:00.000Z",
"type": "ach",
"routingNumber": "021000021",
"accountType": "checking",
"description": "ACH deposits and withdrawals",
"ownerAddressLine1": "123 Main Street",
"ownerAddressLine2": "Suite 400",
"ownerAddressCityLocality": "New York",
"ownerAddressStateProvince": "NY",
"ownerAddressPostalCode": "10001",
"ownerAddressCountryCode": "US",
"bankAddressLine1": "456 Financial Plaza",
"bankAddressCityLocality": "New York",
"bankAddressStateProvince": "NY",
"bankAddressPostalCode": "10005",
"bankAddressCountryCode": "US",
"virtualDepositOnly": false,
"fee": {
"amount": "1600",
"individualFees": [
{
"type": "static",
"amount": "1600"
}
]
}
}
2. Get Approval Status (Optional)
Before attempting to make a fiat withdrawal from a Go Account, you can check the approval status for the receiving bank account.
Bank accounts include the following verification states:
pending- Bank account is under review. BitGo approves most accounts within 48 hours.approved- Bank account is ready for fiat operations.rejected- Bank account did not pass review. Review the requirements and resubmit.removed- BitGo removed the bank account from the enterprise.
Endpoint: Get bank account
export BANK_ACCOUNT_ID="<BANK_ACCOUNT_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
curl -X GET \
https://app.bitgo-test.com/api/v2/bankaccounts/$BANK_ACCOUNT_ID \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN"
Step Result
Save the memoId.
{
"type": "wire",
"routingNumber": "string",
"accountType": "checking",
"id": "string",
"idHash": "string",
"currency": "fiatusd",
"token": "string",
"name": "string",
"shortCountryCode": "string",
"accountNumber": "string",
"enterpriseId": "string",
"trustOrg": "BitGo Trust",
"ownerName": "string",
"verificationState": "approved",
"createdAt": "string",
"pendingActivity": "flaggedBrokerage",
"fee": {
"amount": "string",
"individualFees": [
{
"type": "static",
"amount": "string"
}
]
},
"feeInfo": {
"coin": "fiatusd",
"bank": "silvergate",
"type": "static",
"amount": "string"
},
"furtherCreditTo": "string",
"intermediaryBankName": "string",
"intermediaryBankId": "string",
"metadata": "string",
"description": "string",
"virtualDepositOnly": true,
"ownerAddressLine1": "string",
"ownerAddressLine2": "string",
"ownerAddressCityLocality": "string",
"ownerAddressStateProvince": "string",
"ownerAddressPostalCode": "string",
"ownerAddressCountryCode": "string",
"bankAddressLine1": "string",
"bankAddressLine2": "string",
"bankAddressCityLocality": "string",
"bankAddressStateProvince": "string",
"bankAddressPostalCode": "string",
"bankAddressCountryCode": "string",
"owner": {
"name": "string",
"address1": "string",
"address2": "string",
"address3": "string"
},
"address": "string",
"ownerAddress": "string",
"address1": "string",
"address2": "string",
"address3": "string"
}
3. Get idHash
BitGo identifies bank accounts with a unique idHash that you can pass as the address value in the following step. You also receive information about the available payment rails and associated bank fees.
Endpoint: List Bank Accounts
export ENTERPRISE_ID="<ENTERPRISE_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
curl -X GET \
https://app.bitgo-test.com/api/v2/bankaccounts?enterpriseId=$ENTERPRISE_ID \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN"
Step Result
{
"bankAccounts": [
{
"type": "wire", // available payment rails vary by bank and region
"accountNumber": "012345678",
"address1": "test",
"address2": "test",
"enterpriseId": "1032e75c451052000436831deb797af1",
"id": "60749ab75f8c4500060f5a8b244dd0cb",
"name": "My Bank",
"owner": {
"name": "test",
"address1": "test",
"address2": "test"
},
"idHash": "c2f4cf5555a66d77",
"routingNumber": "087654321",
"shortCountryCode": "US",
"verificationState": "approved",
"fee": { // fees vary by payment rail and bank
"amount": "string",
"individualFees": [
{
"type": "static",
"amount": "string"
}
]
},
"feeInfo": {
"coin": "fiatusd",
"bank": "silvergate",
"type": "static",
"amount": "string"
},
}
]
}
4. Build Transaction
To withdraw assets from your Go Account to a bank account, you must build a transaction and send the assets.
Endpoint: Build a Transaction
export COIN="<FIAT_ASSET_ID>" # Asset IDs in Go Accounts start with 'ofc' (e.g. ofctusd)
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export AMOUNT="<AMOUNT_IN_BASE_UNITS>"
export ADDRESS="<ID_HASH>" # Use the `idHash`, returned in the prior step
curl -X POST \
https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/tx/build \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"recipients": [
{
"amount": "'"$AMOUNT"'",
"address": "'"$ADDRESS"'"
}
]
}'
let params = {
recipients: [
{
amount: 1000,
address: '<ID_HASH>',
},
],
};
wallet.prebuildTransaction(params).then(function (transaction) {
// print transaction details
console.dir(transaction);
});
Step Result
{
"payload": "{\"coin\":\"ofctusdt\",\"recipients\":[{\"address\":\"tb1q5mwcr2749nnm5c5d6rzx5h92l2u9ex5jzygzd39vfv9qerj5fmjqwlgy4t\",\"amount\":\"1000\"}],\"fromAccount\":\"62c5b1de8a0c5200071c9a603bdbadc5\",\"nonce\":\"d8e5d930-f827-42b1-ad85-40544dad1be6\",\"timestamp\":\"2025-06-25T17:45:56.394Z\",\"feeString\":\"0\",\"shortCircuitBlockchainTransfer\":false,\"isIntraJXTransfer\":false}",
"feeInfo": { "feeString": "0" },
"coin": "ofc",
"token": "ofctusdt"
}
5. Authenticate Transaction
Use your Go Account passphrase to authenticate the transaction. To ensure your passphrase never travels over the Internet, you must use BitGo Express in external-signing mode or the JavaScript SDK. If you're using Express in external-signing mode, configure your Go Account passphrase as the WALLET_<walletId>_PASSPHRASE environment variable.
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export WALLET_ID="<YOUR_WALLET_ID>"
export WALLET_PASSPHRASE="<YOUR_GO_ACCOUNT_PASSPHRASE>"
curl -X POST \
http://$BITGO_EXPRESS_HOST/api/v2/ofc/signPayload \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"walletId": "'"$WALLET_ID"'",
"walletPassphrase": "'"$WALLET_PASSPHRASE"'",
"payload": "{\"coin\":\"ofcusdt\",\"recipients\":[{\"address\":\"tb1q5mwcr2749nnm5c5d6rzx5h92l2u9ex5jzygzd39vfv9qerj5fmjqwlgy4t\",\"amount\":\"1000\"}],\"fromAccount\":\"67ab85b5190bf872e84da2b6e527d9f3\",\"nonce\":\"77d91a11-a7fa-4ad7-91e5-f054328717f9\",\"timestamp\":\"2025-06-26T15:02:06.924Z\",\"feeString\":\"0\",\"shortCircuitBlockchainTransfer\":false,\"isIntraJXTransfer\":false}"
}
// assuming that "bitgo" is an already initialized bitgo instance
const wallet = await bitgo.coin('ofc').wallets().get({ id: goAccountId });
if (wallet === undefined) {
throw new Error(`Could not find OFC wallet ${goAccountId}`);
}
const walletPassphrase = "<YOUR_WALLET_PASSPHRASE>";
const tradingAccount = wallet.toTradingAccount();
const stringifiedPayload = JSON.stringify(<payload_returned_by_tx/build_api>);
const signature = await tradingAccount.signPayload({
payload: stringifiedPayload,
walletPassphrase,
});
Step Result
{
"coin": "ofcusdt",
"recipients": [
{
"address": "tb1q5mwcr2749nnm5c5d6rzx5h92l2u9ex5jzygzd39vfv9qerj5fmjqwlgy4t",
"amount": "1000"
}
],
"fromAccount": "62c5b1de8a0c5200071c9a603bdbadc5",
"nonce": "77d91a11-a7fa-4ad7-91e5-f054328717f9",
"timestamp": "2025-06-26T15:02:06.924Z",
"feeString": "0",
"shortCircuitBlockchainTransfer": false,
"isIntraJXTransfer": false,
"payload": "{\"coin\":\"ofcusdt\",\"recipients\":[{\"address\":\"tb1q5mwcr2749nnm5c5d6rzx5h92l2u9ex5jzygzd39vfv9qerj5fmjqwlgy4t\",\"amount\":\"1\"}],\"fromAccount\":\"62c5b1de8a0c5200071c9a603bdbadc5\",\"nonce\":\"77d91a11-a7fa-4ad7-91e5-f054328717f9\",\"timestamp\":\"2025-06-26T15:02:06.924Z\",\"feeString\":\"0\",\"shortCircuitBlockchainTransfer\":false,\"isIntraJXTransfer\":false}",
"signature": "20dda1e9558adb297f69020f94cbf4955fabec73478506347dbb5ac8e73b506fc908bbc48bde75b339b99f5de808ed34b2017055c9df198fd1f8b4e524899f9583"
}
6. Send Transaction
Endpoint: Send Half-Signed Transaction
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export ADDRESS="<ID_HASH>"
export COIN="<FIAT_ASSET_ID>"
export AMOUNT="<AMOUNT_IN_BASE_UNITS>"
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 '{
"recipients": [
{
"address": "'"$ADDRESS"'",
"amount": "'"$AMOUNT"'"
}
],
"halfSigned": {
"payload": {
"coin": "ofctusd",
"recipients": [
{
"address": "'"$ADDRESS"'",
"amount": "'"$AMOUNT"'"
}
],
"fromAccount": "<WALLET_ID>",
"nonce": "f4af25d0-a037-4afc-8ce6-d7f158d826d1",
"timestamp": "2021-09-10T22:45:20.777Z",
"idfSignedTimestamp": "2021-09-10T22:45:20.113Z",
"idfVersion": 1,
"idfUserId": "<USER_ID>",
"feeString": "1000"
},
"signature": "<signature>"
}
}'
Step Result
{
"transfer": {
"id": "<id>",
"coin": "ofctusd",
"wallet": "<wallet id>",
"walletType": "trading",
"enterprise": "603ca88c44f82002560378421dc7a191",
"txid": "ddd6875812fa59f899a68059ff303bfa6d39fc350ee687c407383d0444b43d2b",
"height": 999999999,
"heightId": "999999999-613be001f3de560006842d52251d5d49",
"date": "2021-09-10T22:45:21.342Z",
"type": "send",
"value": -10000,
"valueString": "-10000",
"baseValue": -10000,
"baseValueString": "-10000",
"feeString": "0",
"payGoFee": 0,
"payGoFeeString": "0",
"usd": -100,
"usdRate": 1,
"state": "signed",
"instant": false,
"isReward": false,
"isFee": false,
"tags": [
"603ca8c01b83cb000656311787dab4cd",
"603ca88c44f82002560378421dc7a191"
],
"history": [
{
"date": "2021-09-10T22:45:21.340Z",
"action": "signed"
},
{
"date": "2021-09-10T22:45:21.216Z",
"user": "5e4ed695ae2e542100336fb16e586019",
"action": "created"
}
],
"signedDate": "2021-09-10T22:45:21.340Z",
"entries": [
{
"address": "address",
"wallet": "603ca8c01b83cb000656311787dab4cd",
"value": -10000,
"valueString": "-10000"
},
{
"address": "bf6cc5252438dc85",
"value": 10000,
"valueString": "10000"
}
],
"signedTime": "2021-09-10T22:45:21.340Z",
"createdTime": "2021-09-10T22:45:21.216Z"
},
"txid": "ddd6875812fa59f899a68059ff303bfa6d39fc350ee687c407383d0444b43d2b",
"tx": {
"transaction": {
"coin": "ofctusd",
"recipients": [
{
"address": "<bank id hash>",
"amount": "10000"
}
],
"fromAccount": "<wallet id>",
"nonce": "f4af25d0-a037-4afc-8ce6-d7f158d826d1",
"timestamp": "2021-09-10T22:45:20.777Z",
"idfSignedTimestamp": "2021-09-10T22:45:20.113Z",
"idfVersion": 1,
"idfUserId": "<user id>",
"feeString": "0"
},
"signature": "<signature>",
"idfVersion": 1,
"idfSignedTimestamp": "2021-09-10T22:45:20.113Z",
"idfUserId": "<user id>"
},
"status": "signed"
}
7. Confirm Withdrawal
You must confirm or reject each fiat withdrawal before BitGo processes the transaction.
You can Create Webhooks to automate confirmations. To automate approvals or denials, you can subscribe to the organization transfer webhook and call the Confirm fiat withdrawal endpoint whenever you receive a fiat withdrawal event (walletType: "trading", transferType: "send", and subType: "ofc_withdrawal").
Note
If you configure a liveness check policy for automatic approvals, withdrawals that pass liveness verification confirm automatically.
Endpoint: Confirm fiat withdrawal
export WALLET_ID="<YOUR_WALLET_ID>"
export TRANSFER_ID="<YOUR_TRANSFER_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export ACTION="<APPROVE_OR_REJECT>"
curl -X PUT \
https://app.bitgo-test.com/api/v2/wallet/$WALLET_ID/fiatwithdrawals/$TRANSFER_ID/confirm \
-H "accept: application/json" \
-H "content-type: application/json" \
-H "authorization: Bearer $ACCESS_TOKEN" \
-d '{
"action":"'"$ACTION"'"
}'
Step Result
{
"entries": [
{
"address": "6967b45a4ffdedb5747d5934e544b94c",
"wallet": "6967b45a4ffdedb5747d5934e544b94c",
"value": -2100,
"valueString": "-2100",
"isPayGo": false,
"backingFeeString": "0",
"token": "ofctusd"
},
{
"address": "c7138929d032c83d",
"value": 2000,
"valueString": "2000",
"isPayGo": false,
"token": "ofctusd"
}
],
"id": "6980dfc5decaa85472a63ce93f0a07a7",
"coin": "tfiatusd",
"wallet": "6967b45a4ffdedb5747d5934e544b94c",
"walletType": "trading",
"enterprise": "6967afd69792fa80c629f22bb52caed6",
"organization": "695d68b362ce13d38fa6a4fe2c7a6a82",
"txid": "a10d7719179b5b6705b10a6bcd2cb492c10cae15564d567d4dd3e8e699718c64",
"txidType": "transactionHash",
"height": 999999999,
"heightId": "999999999-6980dfc5decaa85472a63ce93f0a07a7",
"date": "2026-02-02T17:33:05.285Z",
"type": "send",
"subType": "ofc_withdrawal",
"value": -2100,
"valueString": "-2100",
"intendedValueString": "-2100",
"baseValue": -2100,
"baseValueString": "-2100",
"baseValueWithoutFees": -2100,
"baseValueWithoutFeesString": "-2100",
"feeString": null,
"payGoFee": 0,
"payGoFeeString": "0",
"usd": -21,
"usdRate": 1,
"medianUsdValue": -21,
"medianUsdRate": 1,
"feeUsd": 1,
"feeUsdRate": 1,
"state": "pendingApproval",
"instant": false,
"isReward": false,
"isUnlock": false,
"isFee": false,
"senderInformationVerified": false,
"tags": [
"6967b45a4ffdedb5747d5934e544b94c",
"6967afd69792fa80c629f22bb52caed6"
],
"history": [
{
"date": "2026-02-02T17:33:05.285Z",
"action": "unconfirmed",
"comment": null
},
{
"date": "2026-02-02T17:32:54.213Z",
"action": "signed"
},
{
"date": "2026-02-02T17:32:53.444Z",
"user": "695d68b062ce13d38fa6a3ec72df6e4c",
"action": "created"
}
],
"signedDate": "2026-02-02T17:32:54.213Z",
"buildParams": {
"recipients": [
{
"address": "c7138929d032c83d",
"amount": "2000",
"tokenName": "ofctusd"
}
]
},
"metadata": [],
"unconfirmedTime": "2026-02-02T17:33:05.285Z",
"signedTime": "2026-02-02T17:32:54.213Z",
"createdTime": "2026-02-02T17:32:53.444Z"
}
{
"entries": [
{
"address": "6967b45a4ffdedb5747d5934e544b94c",
"wallet": "6967b45a4ffdedb5747d5934e544b94c",
"value": -2100,
"valueString": "-2100",
"isPayGo": false,
"backingFeeString": "0",
"token": "ofctusd"
},
{
"address": "c7138929d032c83d",
"value": 2000,
"valueString": "2000",
"isPayGo": false,
"token": "ofctusd"
}
],
"id": "6980dfc5decaa85472a63ce93f0a07a7",
"coin": "tfiatusd",
"wallet": "6967b45a4ffdedb5747d5934e544b94c",
"walletType": "trading",
"enterprise": "6967afd69792fa80c629f22bb52caed6",
"organization": "695d68b362ce13d38fa6a4fe2c7a6a82",
"txid": "a10d7719179b5b6705b10a6bcd2cb492c10cae15564d567d4dd3e8e699718c64",
"txidType": "transactionHash",
"height": 999999999,
"heightId": "999999999-6980dfc5decaa85472a63ce93f0a07a7",
"date": "2026-02-02T17:33:05.285Z",
"type": "send",
"subType": "ofc_withdrawal",
"value": -2100,
"valueString": "-2100",
"intendedValueString": "-2100",
"baseValue": -2100,
"baseValueString": "-2100",
"baseValueWithoutFees": -2100,
"baseValueWithoutFeesString": "-2100",
"feeString": null,
"payGoFee": 0,
"payGoFeeString": "0",
"usd": -21,
"usdRate": 1,
"medianUsdValue": -21,
"medianUsdRate": 1,
"feeUsd": 1,
"feeUsdRate": 1,
"state": "rejected",
"instant": false,
"isReward": false,
"isUnlock": false,
"isFee": false,
"senderInformationVerified": false,
"tags": [
"6967b45a4ffdedb5747d5934e544b94c",
"6967afd69792fa80c629f22bb52caed6"
],
"history": [
{
"date": "2026-02-02T17:33:05.285Z",
"action": "rejected",
"comment": null
},
{
"date": "2026-02-02T17:32:54.213Z",
"action": "signed"
},
{
"date": "2026-02-02T17:32:53.444Z",
"user": "695d68b062ce13d38fa6a3ec72df6e4c",
"action": "created"
}
],
"signedDate": "2026-02-02T17:32:54.213Z",
"buildParams": {
"recipients": [
{
"address": "c7138929d032c83d",
"amount": "2000",
"tokenName": "ofctusd"
}
]
},
"metadata": [],
"rejectedTime": "2026-02-02T17:33:05.285Z",
"signedTime": "2026-02-02T17:32:54.213Z",
"createdTime": "2026-02-02T17:32:53.444Z"
}
8. 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
export COIN="<ASSET_ID>"
export APPROVAL_ID="<APPROVAL_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export OTP="<OTP>"
curl -X POST \
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"'"
}'
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 unsigned transaction, applying the most up-to-date fees.
{
"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"
}
]
},
"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"
}
]
}
See Also
- CaaS Overview
- API Reference: Add bank account
- API Reference: Build a Transaction
- API Reference: Confirm fiat withdrawal
- API Reference: Get bank account
- API Reference: Get Enterprise Transfer Limits
- API Reference: List Bank Accounts
- API Reference: Send Half-Signed Transaction
- API Reference: Update Pending Approval