Fund Go Accounts

Overview

Crypto-as-a-Service (CaaS) enables you and your clients to move fiat between bank accounts and Go Accounts. BitGo supports multiple fiat payments rails to accommodate different client preferences, use cases, and regulatory environments.

Fiat Support

JurisdictionCurrencyPayment Rails
United StatesUSDACH debit, domestic and international wire transfers, CUBIX transfers, Go Network
EuropeEUROSEPA Instant, SEPA, BLINC transfers, Go Network

Prerequisites

Deposit Instructions

You can fetch your enterprise deposit instructions using the Get deposit info endpoint which returns the memo ID and available deposit bank accounts based on your enterprise jurisdiction. This information is useful when depositing with any of the payment rails we support. Some funding rails require memo ID and bank account details to match your deposit.

BitGo-Approved Bank Accounts

Fiat withdrawals to bank accounts require the use of BitGo-approved bank accounts. You can use the Add bank account endpoint to add a bank account.

When you add a bank account to an enterprise it goes through a screening process. BitGo approves most bank accounts within 48 hours and they can be used for fiat operations immediately after approval. You can see the status of the bank account by calling the Get bank account endpoint and checking the verificationState field.

Approval Requirements

To ensure your bank account is approved, verify the following requirements are met:

RequirementDescription
Valid Routing NumberFor US bank accounts, provide a valid 9-digit ABA routing number. BitGo validates routing numbers against the Federal Reserve's directory. Invalid routing numbers result in rejection.
Owner Name MatchThe 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 TypeYou must specify the accountType field as checking or saving. This field is required for both ACH and wire transactions to process correctly.

(Optional) Add Bank Account

Endpoint: Add bank account

export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export ENTERPRISE_ID="<CHILD_ENTERPRISE_ID>"

# Note: 021000021 is a valid sample routing number (JPMorgan Chase Bank)
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",
    "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',
});

// Note: 021000021 is a valid sample routing number (JPMorgan Chase Bank)
async function addBankAccount() {
  const bankAccount = await bitgo.post('/api/v2/bankaccounts').send({
    type: 'ach',
    name: 'JPMorgan Chase Bank',
    accountNumber: '123456789012',
    routingNumber: '021000021',
    currency: 'tfiatusd',
    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"
      }
    ]
  }
}

Verification States

One of the following verification states is returned:

  • pending - Bank account is under review. Most accounts are approved within 48 hours.
  • approved - Bank account is approved and ready for fiat operations.
  • rejected - Bank account is rejected. Review the requirements and resubmit.
  • revise - Bank account requires corrections. Update the account and resubmit.
  • removed - Bank account is removed from the enterprise.
📘

Note

Use the Get bank account endpoint to check the current verification status before initiating fiat operations.

Steps

Select a funding rail to deposit or withdraw from your Go Accounts.

ACH Deposits

ACH deposits enable USD transfers from BitGo-approved US bank accounts to Go Accounts and are well suited for B2B2C platforms where your users initiate funding through your frontend. ACH deposits are best used for:

  • Small-to-medium size deposits.
  • User experiences that demand a “pull” model.
  • Settlements that can wait 1–2 business days to settle.

Before initiating ACH deposits, your platform must fund a reserve account that meets the following requirements:

  • Minimum account balance: $25,000 if no deposit history.
  • Standard account balance: 25% of the highest 2-day deposit volume in the previous month.
  • Must be replenished within 5 business days if funds are withdrawn.

In addition, to comply with Nacha rules, your ACH unauthorized returns must stay below 0.5% of total debits. If you exceed these thresholds, BitGo may suspend your ACH access.

Plaid Integration

ACH deposits require bank accounts linked through Plaid. Your enterprise must have Plaid credentials configured by BitGo before you can proceed. Contact your Customer Success Manager (CSM) if you have not completed Plaid setup.

1. Set Up Reserve

ACH deposits take 1–2 business days to settle, while digital assets can transfer almost instantly. Therefore, BitGo requires you to pre-fund a fiat reserve to cover potential unauthorized return claims (fraud) from your end-users. You set up your reserve account using the Go Account in the parent enterprise - not the child enterprises.

1.1 Designate Parent Enterprise

Contact your BitGo Customer Success Manager (CSM) to designate an enterprise in your organization your parent enterprise. Your CSM coordinates the set up and account configuration.

1.2 Fund Reserve Account

Deposit a minimum of $25,000 into the Go Account. This serves as your reserve account. ACH functionality isn't enabled until these funds fully settle. You can fund the Go Account using a wire transfer or a Go Network transfer.

1.3 Maintain Reserve

As your ACH deposit volume grows, your 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 busy Monday and Tuesday, that $1M is your peak 2-day volume.
  3. Calculate 25% of that peak amount. Using the example above, 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.

1.4 Replenish Reserve

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 top up your reserve account to meet the 25% requirement, BitGo may suspend ACH access until you restore the reserve balance.

2. Get Transfer Limit

The transfer limit is the amount you can deposit using ACH per calendar day and resets every day at 12am EST.

Endpoint: Get Enterprise Transfer Limits

📘

Note

The test environment caps ACH deposits at $2,500/day and $10,000/week per enterprise. Use reasonable amounts and check remaining limits to avoid exceeding these thresholds during testing.

export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"

curl -X GET \
  https://app.bitgo-test.com/api/tradfi/v1/enterprise-transfer-limits/$ENTERPRISE_ID/usd/ach-us/in \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
      "id": "01982d49-9f0d-7c50-847a-e04ea8a63165",
      "maximumTransferAllowed": "2500.00",
      "maximumTransferAllowedBase": 250000,
      "noLimit": false,
      "transferDirection": "in",
      "transferType": "ach-us"
}'

Step Result

{
  "id": "string",
  "maximumTransferAllowed": "string",
  "maximumTransferAllowedBase": 0,
  "noLimit": true,
  "transferDirection": "in",
  "transferType": "ach-us"
}

3. Create Plaid Link Token

Create Plaid Link token for the enterprise. Use this token to initialize the Plaid Link widget in your application. If your application runs on a mobile device, include the androidPackageName or redirectUri parameters to support OAuth redirect flows.

Endpoint: Create Plaid Link token

export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export ANDROID_PACKAGE_NAME="<YOUR_ANDROID_PACKAGE_NAME>" # Required for Android OAuth flows
export REDIRECT_URI="<YOUR_REDIRECT_URI>" # Required for mobile and web OAuth flows

curl -X POST https://app.bitgo-test.com/api/tradfi/v1/plaid/link/token \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enterpriseId": "'"$ENTERPRISE_ID"'",
    "androidPackageName": "'"$ANDROID_PACKAGE_NAME"'", # Required for Android OAuth flows
    "redirectUri": "'"$REDIRECT_URI"'" # Required for mobile and web OAuth flows
  }'
📘

Note

If you haven't configured your Plaid credentials, the server responds with 428 Precondition Required. Contact your BitGo Customer Success Manager (CSM) to get your Plaid credentials set up.

Use the returned link token to render the Plaid Link widget in your application. Refer to the official Plaid documentation for rendering guidance, but use the BitGo APIs (described in this guide) for creating and exchanging tokens.


4. Exchange the Plaid Public Token

Once you finish selecting the bank accounts in the Plaid widget, Plaid returns a public token to your application. Exchange this token with BitGo to complete the bank account linking process.

Endpoint: Exchange Plaid Public Token

export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export LINK_TOKEN="<LINK_TOKEN_FROM_STEP_1>"
export PUBLIC_TOKEN="<PUBLIC_TOKEN_FROM_PLAID>"
export ACCESS_TOKEN="<ACCESS_TOKEN>"
export IP_ADDRESS="<IP_ADDRESS>"

curl -X POST https://app.bitgo-test.com/api/tradfi/v1/plaid/link/token/exchange \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enterpriseId": "'"$ENTERPRISE_ID"'",
    "linkToken": "'"$LINK_TOKEN"'",
    "publicToken": "'"$PUBLIC_TOKEN"'",
    "ipAddress": "'"$IP_ADDRESS"'" # IP address of the end user who completed Plaid Link. Optional, but provide this value to improve the users Instant Credit trust score.
  }'

BitGo fetches the bank accounts selected by the user asynchronously. BitGo adds them to the user's account within a few seconds.

5. Get Bank Account

Retrieve the linked bank account to obtain the bankAccountId needed to initiate the ACH deposit. You can list all bank accounts or get a specific one by ID.

Endpoint: Get Deposit Info

export BANK_ACCOUNT_ID="<BANK_ACCOUNT_ID>"
export ACCESS_TOKEN="<ACCESS_TOKEN>"

curl -X GET \
  https://app.bitgo-test.com/api/v2/bankaccounts/deposit/info?currency=fiatusd \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Step Result

{
  "memoId": "string",
  "bankAccounts": [
    {
      "type": "ach",
      "routingNumber": "string",
      "accountType": "checking", 
      "id": "string", // Bank account id used for the next step,
      "description": "Nickname for Bank Acount", // User-provided description of the account.
      "name": "Bank Name"
    }
  ]
}

6. Create Bank Transfer

Initiate a new bank transfer using the walletId and bankAccountId as counterparties. The system infers most details from the bankAccountId. The same enterpriseId must own both the walletId and bankAccountId.

📘

Note

This endpoint is only available in the test environment.

Endpoint: Create a Bank Transfer

export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export AMOUNT="<AMOUNT_TO_DEPOSIT>"
export BANK_ACCOUNT_ID="<BANK_ACCOUNT_ID>" # ID from previous step. 
export WALLET_ID="<WALLET_ID>"

curl -X POST https://app.bitgo-test.com/api/tradfi/v1/bank-transfers \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "'"$AMOUNT_TO_DEPOSIT"'",
    "bankAccountId": "'"$BANK_ACCOUNT_ID"'",
    "transferDirection": "in",
    "walletId": "'"$WALLET_ID"'"
  }'

Step Result

{
  "amount": "string",
  "applyInstantCredit": true,
  "bankAccountId": "string",
  "createdAt": "2026-04-09T17:17:30.615Z",
  "enterpriseId": "string",
  "estimatedEffectiveOn": "2026-04-09",
  "id": "string",
  "instantCreditLiability": true,
  "memoId": "string",
  "settledAt": "2026-04-09T17:17:30.615Z",
  "status": "initiated",
  "transferDirection": "in",
  "transferType": "ach-us",
  "txid": "string",
  "walletId": "string"
}

7. Get Bank Transfer

Use this call to check the transfer's current status, settlement timestamps, and other details.

📘

Note

This endpoint is only available in the test environment.

Endpoint: Get Bank Transfer

export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export TRANSACTION_ID="<TX_ID>"

curl -X GET https://app.bitgo-test.com/api/tradfi/v1/bank-transfers/$TX_ID \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Accept: application/json" \

Step Result

{
  "amount": "string",
  "applyInstantCredit": true,
  "bankAccountId": "string",
  "createdAt": "2026-04-10T15:31:57.502Z",
  "enterpriseId": "string",
  "estimatedEffectiveOn": "2026-04-10",
  "id": "string",
  "instantCreditLiability": true,
  "memoId": "string",
  "settledAt": "2026-04-10T15:31:57.502Z",
  "status": "initiated",
  "transferDirection": "in",
  "transferType": "ach-us",
  "txid": "string",
  "walletId": "string"
}

The API automatically enforces daily transfer limits. If the deposit would exceed the allowed amount, the request returns an error. You can check remaining limits at any time using the List Enterprise Transfer Limits endpoint.

ACH deposits typically settle within 1–2 business days.


Instant Credit (Optional)

Instant Credit allows your users to receive funds in their Go Account immediately after initiating an ACH deposit, rather than waiting for settlement.

How It Works

  1. When an account initiates a deposit with Instant Credit enabled, BitGo performs a risk analysis using data from the linked Plaid account (such as the current bank balance).
  2. The risk provider returns a timeline assessment — either T+1 (low risk, advances credit) or T+4 (higher risk, does not advance credit).
  3. If approved, the Go Account ledger credits immediately and the funds become spendable, even though ACH settlement is still pending.
  4. Once the ACH transfer fully settles, the instant credit transaction reconciles automatically.

Requirements

For Instant Credit to be applied, all of the following must be true:

  • The enterprise integrates with Plaid.
  • The reserve account holds enough funds to cover instant credit above the minimum threshold.
  • The deposit request sets the applyInstantCredit flag to true.
  • The indexed ledger allows Instant Credit.
  • The transfer type and direction qualify for instant credit (currently ACH pulls only).
  • The enterprise (and optionally the wallet) meets the risk criteria.

Monitoring Instant Credit Liability

Transfers with active Instant Credit count against your reserve account balance. You can check the instantCreditLiability field on individual transfers to determine how much of your reserve is currently committed.

📘

Important

Instant Credit is not guaranteed. If the risk analysis returns an unfavorable result, the deposit proceeds normally with standard settlement timing.

See Also