# Set Up Fiat Reserve

Source: https://developers.bitgo.com/docs/crypto-as-a-service-fiat-reserve

## Overview

BitGo requires you to pre-fund a fiat reserve to cover potential unauthorized return claims (fraud) from your end users. The reserve account uses the Go Account in your parent enterprise in the organization - not the child enterprises of your end users.

Your reserve account must meet the following requirements:

* Minimum balance: $25,000 if no deposit history.
* Standard balance: 25% of the highest 2-day deposit volume in the previous month.
* You must replenish the balance within 5 business days of dropping below the minimum balance.

### Supported Payment Rails

| Jurisdiction | Currency | Payment Rails |
| :----------- | :------- | :------------ |
| United States | USD | ACH debit, domestic and international wire transfers, [Go Network](/docs/go-network-overview) |
| Europe | EUR | SEPA Instant, SEPA, BLINC transfers, [Go Network](/docs/go-network-overview) |
| Singapore | USD, SGD | FAST, International Wire |

## Prerequisites

* [Get Started](/docs/get-started-intro)
* [Create Go Accounts](/docs/crypto-as-a-service-go-accounts)
* Contact your BitGo Customer Success Manager (CSM) to designate an enterprise in your organization to be your parent enterprise.

## Cookbooks

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

<Cookbook slug="caas-fiat-reserve-bank-transfer" title="Set Up Fiat Reserve - Bank Transfer" />

<Cookbook slug="caas-fiat-reserve-go-network" title="Set Up Fiat Reserve - Go Network Transfer" />

<h2 class="no-toc">Fund Reserve Account</h2>

Deposit at least $25,000 into the Go Account of your parent enterprise using either a bank transfer or a Go Network transfer from another Go Account you control.

<Tabs>
<Tab title="Bank Transfer">

## Bank Transfer

### 1. Get Deposit Info

Get deposit information for BitGo bank accounts. Available deposit mehtods vary by Go Account jurisdiction. EU residents have access to a Virtual International Bank Account Number (vIBAN).

>Endpoint: [Get deposit info](/reference/fiatgetdepositinfo)

```shell cURL
export CURRENCY="<FIAT_CURRENCY_ASSET_ID>"
export GO_ACCOUNT_ID="<GO_ACCOUNT_WALLET_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"

curl -X GET \
  https://app.bitgo-test.com/api/v2/bankaccounts/deposit/info?currency=$CURRENCY&goAccountId=$GO_ACCOUNT_ID \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```
```js JavaScript
export type Fee {
  amount: string
  individualFees:
    {
        type: "static" | "variable",
        amount: string
    }[]
}

export type BankAccount {
  id: string;
  description?: string;
  idHash: string;
  currency: string;
  accountNumber: string;
  token: string;
  name: string;
  shortCountryCode: string;
  enterpriseId: string;
  trustOrg: string;
  ownerName: string;
  verificationState: string;
  createdAt: string;
  ownerAddressLine1: string;
  ownerAddressLine2?: string;
  ownerAddressCityLocality?: string;
  ownerAddressStateProvince?: string;
  ownerAddressPostalCode?: string;
  ownerAddressCountryCode: string;
  bankAddressLine1: string;
  bankAddressLine2?: string;
  bankAddressCityLocality?: string;
  bankAddressStateProvince?: string;
  bankAddressPostalCode?: string;
  bankAddressCountryCode: string;
  virtualDepositOnly: boolean;
  type: string;
  routingNumber?: string;
  swiftCode?: string;
  accountType: string;
  fee: Fee
}

export type DepositInfo = {
  memoId: string;
  bankAccounts: BankAccount[];
};
```

#### Step Result

Save the `memoId` if `"virtualDepositOnly": false`. BitGo uses this ID to link deposits to Go Accounts. If `"virtualDepositOnly": true`, then you have access to a vIBAN and a `memoId` isn't required.

```JSON
{
  "bankAccounts": [
    {
      "accountNumber": "123456789",
      "accountType": "checking",
      "address": "Ste 1400, Phoenix, AZ 85004, United States of America",
      "address1": "Ste 1400, Phoenix, AZ 85004, United States of America",
      "bankAddressCityLocality": "Phoenix",
      "bankAddressCountryCode": "US",
      "bankAddressLine1": "Ste 1400",
      "bankAddressPostalCode": "85004",
      "bankAddressStateProvince": "AZ",
      "createdAt": "2026-07-22T19:39:01.484372Z",
      "currency": "tfiatusd",
      "enterpriseId": "68cc07a26b0eb871423ef15781d99121",
      "fee": {
        "amount": "1000",
        "individualFees": [{ "amount": "1000", "type": "static" }]
      },
      "feeInfo": {
        "amount": "1000",
        "bank": "customers_cubix_api",
        "coin": "tfiatusd",
        "type": "static"
      },
      "id": "b23bbce8-dad1-41dd-ac71-4fd9bcd0a58b",
      "idHash": "1d6fd97db569ff2b",
      "name": "WESTERN ALLIANCE BANK",
      "owner": {
        "name": "BitGo Bank & Trust",
        "address1": "2443 Ash Street, Suite 200, Palo Alto, CA 94306, United States of America"
      },
      "ownerAddress": "2443 Ash Street, Suite 200, Palo Alto, CA 94306, United States of America",
      "ownerAddressCityLocality": "Palo Alto",
      "ownerAddressCountryCode": "US",
      "ownerAddressLine1": "2443 Ash Street",
      "ownerAddressLine2": "Suite 200",
      "ownerAddressPostalCode": "94306",
      "ownerAddressStateProvince": "CA",
      "ownerName": "BitGo Bank & Trust",
      "routingNumber": "122105980",
      "shortCountryCode": "US",
      "token": "ofctusd",
      "trustOrg": "BitGo Trust",
      "type": "wire",
      "verificationState": "approved",
      "virtualDepositOnly": false
    }
  ],
  "memoId": "NKNKASPXVH"
}
```

### 2. Deposit Fiat Currency

Initiate the transfer from your bank app or API. Review the documentation provided by your bank or contact them to learn more.

> ❗ **Important**
>
> Ensure your deposit includes the memo ID returned in the previous step.

#### Step Result

The balance of fiat currency in your Go Account updates with the deposited amount. The deposited balance is immediately available for trades.

</Tab>
<Tab title="Go Network Transfer">

## Go Network Transfer

### 1. Build Transaction

Build a transaction from the source Go Account to the destination Go Account. Pass the destination Go Account **wallet ID as the value of the `address` field** in the recipient object — the recipient object uses `address`, not `walletId`.

> Endpoint: [Build a Transaction](/reference/v2wallettxbuild)

```shell cURL
export COIN="<CRYPTO_ASSET_ID>" # Asset IDs in Go Accounts start with 'ofc' (e.g. ofctusd)
export WALLET_ID="<SOURCE_GO_ACCOUNT_WALLET_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export AMOUNT="<AMOUNT_IN_BASE_UNITS>" # Must be $25,000 or more
export DESTINATION_WALLET_ID="<DESTINATION_GO_ACCOUNT_WALLET_ID>"

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": "'"$DESTINATION_WALLET_ID"'"
      }
    ]
}'
```
```javascript JavaScript
let params = {
  recipients: [
    {
      amount: 1000,
      address: '654ec786c07fe6dc0dcfe03916ec4bb0',
    },
  ],
};
wallet.prebuildTransaction(params).then(function (transaction) {
  console.dir(transaction);
});
```

#### Step Result

The response payload contains `shortCircuitBlockchainTransfer: true` and `isIntraJXTransfer: true`, confirming that BitGo recognized this as an off-chain book transfer.

```json JSON
{
  "payload": "{\"coin\":\"ofctusd\",\"recipients\":[{\"address\":\"2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY\",\"amount\":\"250000000\"}],\"fromAccount\":\"63ff43c474598902272894f328452ad7\",\"nonce\":\"80bc93b5-eeec-4c11-afca-f6dae4bba2f2\",\"timestamp\":\"2023-09-28T10:55:39.135Z\",\"feeString\":\"0\",\"shortCircuitBlockchainTransfer\":true,\"isIntraJXTransfer\":true}",
  "feeInfo": { "feeString": "0" },
  "coin": "ofc",
  "token": "ofctusd"
}
```

### 2. Authenticate Transaction

Use your Go Account passphrase to authenticate the transaction. To ensure your passphrase isn't passed over the Internet, you must use BitGo Express in [External-Signing Mode](/docs/wallets-external-signer-mode) or the JavaScript SDK.

```shell cURL (external-signing mode)
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export WALLET_ID="<SOURCE_GO_ACCOUNT_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\":\"ofctusd\",\"recipients\":[{\"address\":\"2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY\",\"amount\":\"250000000\"}],\"fromAccount\":\"63ff43c474598902272894f328452ad7\",\"nonce\":\"80bc93b5-eeec-4c11-afca-f6dae4bba2f2\",\"timestamp\":\"2023-09-28T10:55:39.135Z\",\"feeString\":\"0\",\"shortCircuitBlockchainTransfer\":true,\"isIntraJXTransfer\":true}"
}'
```
```javascript JavaScript
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

```json JSON
{
  "payload": "{\"coin\":\"ofctusd\",\"recipients\":[{\"address\":\"2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY\",\"amount\":\"250000000\"}],\"fromAccount\":\"63ff43c474598902272894f328452ad7\",\"nonce\":\"80bc93b5-eeec-4c11-afca-f6dae4bba2f2\",\"timestamp\":\"2023-09-28T10:55:39.135Z\",\"feeString\":\"0\",\"shortCircuitBlockchainTransfer\":true,\"isIntraJXTransfer\":true}",
  "signature": "1f989926e3fc8ed0138bd0e188e90e2c5321ef86734896886c004005740a005dfd2008142dbc48aee68d1f576c4a9ac558e5b7b4acbd5aa765710ea636aca9d032"
}
```

### 3. Send Transaction

Using the `payload` and the `signature` from the prior step, send the half-signed transaction to BitGo.

> Endpoint: [Send Half-Signed Transaction](/reference/v2wallettxsend)

```shell cURL
export COIN="<FIAT_CURRENCY_ASSET_ID>"
export WALLET_ID="<SOURCE_GO_ACCOUNT_WALLET_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export PAYLOAD="<PAYLOAD_FROM_STEP_2>"
export SIGNATURE="<SIGNATURE_FROM_STEP_2>"

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": {
      "payload": "'"$PAYLOAD"'",
      "signature": "'"$SIGNATURE"'"
    }
  }'
```
```javascript JavaScript
// stringifiedPayload and signature come from Steps 1 and 2
const sendUrl = wallet.baseCoin.url('/wallet/' + wallet.id() + '/tx/send');
await bitgo
  .post(sendUrl)
  .send({ halfSigned: { payload: stringifiedPayload, signature } })
  .result();
```

#### Step Result

The `transactionType` field confirms that BitGo processed this as a `BOOK_TRANSFER`.

```json JSON
{
  "transfer": {
    "id": "65155c4a72fddb000774edbee5fa75fd",
    "coin": "ofctusd",
    "wallet": "63ff43c474598902272894f328452ad7",
    "walletType": "trading",
    "enterprise": "63f31592e277e50837712300495902c7",
    "txid": "ddd6875812fa59f899a68059ff303bfa6d39fc350ee687c407383d0444b43d2b",
    "height": 999999999,
    "heightId": "999999999-65155c4a72fddb000774edbe",
    "date": "2023-09-28T10:58:18.272Z",
    "type": "send",
    "value": -250000000,
    "valueString": "-250000000",
    "baseValue": -250000000,
    "baseValueString": "-250000000",
    "feeString": "0",
    "payGoFee": 0,
    "payGoFeeString": "0",
    "state": "signed",
    "instant": false,
    "isReward": false,
    "isFee": false,
    "tags": [
      "63ff43c474598902272894f328452ad7",
      "63f31592e277e50837712300495902c7"
    ],
    "history": [
      {
        "date": "2023-09-28T10:58:18.340Z",
        "action": "signed"
      },
      {
        "date": "2023-09-28T10:58:18.272Z",
        "user": "628ca09d1b78a6022750254f0777561a",
        "action": "created"
      }
    ],
    "signedDate": "2023-09-28T10:58:18.340Z",
    "entries": [
      {
        "address": "63ff43c474598902272894f328452ad7",
        "wallet": "63ff43c474598902272894f328452ad7",
        "value": -250000000,
        "valueString": "-250000000"
      },
      {
        "address": "2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY",
        "value": 250000000,
        "valueString": "250000000"
      }
    ],
    "signedTime": "2023-09-28T10:58:18.340Z",
    "createdTime": "2023-09-28T10:58:18.272Z"
  },
  "txid": "ddd6875812fa59f899a68059ff303bfa6d39fc350ee687c407383d0444b43d2b",
  "tx": {
    "transaction": {
      "coin": "ofctusd",
      "recipients": [
        {
          "address": "2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY",
          "amount": "250000000"
        }
      ],
      "fromAccount": "63ff43c474598902272894f328452ad7",
      "nonce": "80bc93b5-eeec-4c11-afca-f6dae4bba2f2",
      "timestamp": "2023-09-28T10:55:39.135Z",
      "idfSignedTimestamp": "2023-09-28T10:55:38.732Z",
      "idfVersion": 1,
      "idfUserId": "628ca09d1b78a6022750254f0777561a",
      "feeString": "0",
      "shortCircuitBlockchainTransfer": true,
      "isIntraJXTransfer": true
    },
    "signature": "1f989926e3fc8ed0138bd0e188e90e2c5321ef86734896886c004005740a005dfd2008142dbc48aee68d1f576c4a9ac558e5b7b4acbd5aa765710ea636aca9d032",
    "transactionType": "BOOK_TRANSFER"
  },
  "status": "signed"
}
```

### 4. Approve Transaction (Optional)

> 📘 **Note**
>
> If you configure an approval requirement for transfers, you can't approve your own transactions — another admin must approve them.

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

```shell cURL
export APPROVAL_ID="<APPROVAL_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export OTP="<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"'"
}'
```
```javascript JavaScript
const baseCoin = bitgo.coin(initialPendingApproval.coin);
const pendingApproval = await baseCoin.pendingApprovals().get({ id: initialPendingApproval.id });
const result = await pendingApproval.approve(params);
```

#### Step Result

Once approved, BitGo processes the book transfer and updates the ledger balances for both Go Accounts.

```json JSON
{
  "id": "65155c4a72fddb000774edbee5fa75fd",
  "coin": "ofctusd",
  "wallet": "63ff43c474598902272894f328452ad7",
  "enterprise": "63f31592e277e50837712300495902c7",
  "creator": "628ca09d1b78a6022750254f0777561a",
  "createDate": "2023-09-28T10:58:18.272Z",
  "info": {
    "type": "transactionRequest",
    "transactionRequest": {
      "coinSpecific": {
        "ofctusd": {
          "payload": {
            "coin": "ofctusd",
            "recipients": [
              {
                "address": "2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY",
                "amount": "250000000"
              }
            ],
            "fromAccount": "63ff43c474598902272894f328452ad7",
            "nonce": "80bc93b5-eeec-4c11-afca-f6dae4bba2f2",
            "timestamp": "2023-09-28T10:55:39.135Z",
            "idfSignedTimestamp": "2023-09-28T10:55:38.732Z",
            "idfVersion": 1,
            "idfUserId": "628ca09d1b78a6022750254f0777561a",
            "feeString": "0",
            "shortCircuitBlockchainTransfer": true,
            "isIntraJXTransfer": true
          },
          "signature": "1f989926e3fc8ed0138bd0e188e90e2c5321ef86734896886c004005740a005dfd2008142dbc48aee68d1f576c4a9ac558e5b7b4acbd5aa765710ea636aca9d032",
          "transactionType": "BOOK_TRANSFER"
        }
      },
      "verificationItems": ["2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY"],
      "videoApprovers": [],
      "requestedAmount": "250000000",
      "fee": 0,
      "sourceWallet": "63ff43c474598902272894f328452ad7",
      "recipients": [
        {
          "_id": "65155c4a68fddb000865edbf",
          "address": "2NDBpypweakRZzgbWqxEK42pnxgfYzd5iuY",
          "amount": "250000000"
        }
      ]
    }
  },
  "state": "approved",
  "scope": "wallet",
  "userIds": [
    "628ca09d1b78a6022750254f0777561a",
    "5bd8bdb0925d7c9823d4fc823e9e2fd3"
  ],
  "approvalsRequired": 1,
  "resolvers": [
    {
      "user": "5bd8bdb0925d7c9823d4fc823e9e2fd3",
      "date": "2023-09-28T11:15:24.644Z",
      "resolutionType": "pending"
    }
  ]
}
```

</Tab>
</Tabs>

## Next

If your ACH deposit volume grows, your fiat reserve must grow with it. Each month:

1. Review your ACH deposit transaction history for the prior month.
2. Identify the peak 2-day volume (the 48-hour window with the highest total USD inflow). For example, if you processed $1M in deposits over a Monday and Tuesday, then $1M is your peak 2-day volume.
3. Calculate 25% of the peak amount. Using the prior example, that's $250,000.
4. If 25% of your peak 2-day volume exceeds your current reserve balance, deposit the difference to bring the reserve up to the required level.

If the balance of your reserve account dips due to fraud or unauthorized returns, you must replenish it to the required level within 5 business days.

> 🚧 **Warning**
>
> If your deposit volume increases but you don't maintain the reserve account to meet the 25% requirement, BitGo may suspend ACH access until you restore the reserve balance.

You can verify successful deposits by calling the [Get Account Balance](/reference/tradeaccountsbalances) endpoint.

## See Also

* [API Reference: Build a Transaction](/reference/v2wallettxbuild)
* [API Reference: Get Account Balance](/reference/tradeaccountsbalances)
* [API Reference: Get deposit info](/reference/fiatgetdepositinfo)
* [API Reference: Send Half-Signed Transaction](/reference/v2wallettxsend)
* [API Reference: Update Pending Approval](/reference/v2approvalupdate)
