> ## Documentation Index
> Fetch the complete documentation index at: https://bkey.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# USD — virtual bank account

> Provision a USD virtual bank account so incoming ACH and wire deposits are credited to the smart wallet in USD, and track its lifecycle status.

<div className="bmoni-spine">
  <span>Lifecycle</span>
  <a data-stage="1" href="/lifecycle#1-create-the-user">User</a>
  <a data-stage="2" href="/lifecycle#2-provision-the-smart-wallet">Wallet</a>
  <a data-stage="3" href="/lifecycle#3-verify-identity-kyc">KYC</a>
  <a data-stage="4" href="/lifecycle#4-activate-the-rail">Rail</a>
  <a data-stage="5" href="/lifecycle#5-fund-the-wallet">Fund</a>
  <a data-stage="6" href="/lifecycle#6-move-money">Move money</a>
</div>

The USD rail is deposit-only: the user gets real US bank account details (account number, ABA routing number), and USD arriving by ACH or wire is converted to `USDB` and credited to their smart wallet. Available to international users on the [USD](/api-reference/kyc-usd-requirements) and [rest-of-world](/api-reference/kyc-row-requirements) paths, and to [Nigerian](/api-reference/kyc-nga-requirements) users as their second stage.

***

## 1. Gate on USD readiness

USD has its own readiness check, separate from `/kyc/readiness`:

```http theme={null}
GET /v1/users/{userId}/kyc/usd-readiness
```

```json theme={null}
{ "ready": false, "missing": ["employment.employmentStatus", "sourceOfFunds"] }
```

Only provision once `ready` is `true`. Render `missing` back into your KYC form rather than retrying blindly — the field names match the `PATCH /kyc` payload.

## 2. Provision the account

```http theme={null}
POST /v1/users/{userId}/onboarding/start-usa
{ "smartWalletId": "7f4d6b88-80a0-4d3f-9538-9a4dfabc1234" }
```

```json theme={null}
{ "workflowId": "usa-onboarding-abc123" }
```

`smartWalletId` is the destination — the wallet credited with `USDB` when USD lands in the account. This one call both provisions the account and binds it, so there is no separate linking step.

Idempotent: repeated calls do not create duplicate accounts, so a retry after a network failure is safe.

## 3. Poll for the account details

```http theme={null}
GET /v1/users/{userId}/vba/usd
```

```json theme={null}
{
  "status": "active",
  "account": {
    "id": "ba_usd_123",
    "accountName": "John Doe",
    "accountNumber": "123456789",
    "routingNumber": "021000021",
    "bankName": "Lead Bank",
    "bankAddress": "1801 Main St, Kansas City, MO 64108",
    "swiftCode": "LEADUS44",
    "currency": "USD",
    "accountType": "checking",
    "depositMessage": null
  },
  "reason": null
}
```

| `status`       | What to show                                              |
| -------------- | --------------------------------------------------------- |
| `none`         | No account yet — show the provision call to action        |
| `provisioning` | The workflow is running; keep polling                     |
| `pending`      | Issued, awaiting bank backfill; keep polling              |
| `active`       | Ready — `account` is populated, show the deposit details  |
| `rejected`     | Declined — `reason` is populated; do not retry            |
| `failed`       | Provisioning did not complete — safe to retry `start-usa` |

`account` is only populated on `active`. Treat `rejected` and `failed` differently: one is terminal, the other is a retry.

<Note>
  When `depositMessage` is non-null, the account requires that reference on incoming transfers. Show it alongside the account number — deposits without it can be delayed or returned.
</Note>

***

## Re-routing deposits later

Only needed if you want an already-issued account to credit a *different* smart wallet than the one passed to `start-usa`:

```http theme={null}
POST   /v1/users/{userId}/smart-wallets/{smartWalletId}/onramp/vba/usd
DELETE /v1/users/{userId}/smart-wallets/{smartWalletId}/onramp/vba/usd
```

The account must belong to the calling user, who must be an active admin of the target wallet.

***

## Withdrawing USD

There is no USD bank payout rail. To get value out, either swap `USDB` into a currency that has one, or use a crypto offramp:

| Route                                          | Endpoint                                                                                                                |
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Swap to another wallet currency                | `POST /v1/users/{userId}/exchange/convert`                                                                              |
| Withdraw to a Nigerian bank (via `USDB` → NGN) | [NGN withdrawals](/api-reference/ngn-rails#withdrawals-cngn--usdb--nigerian-bank)                                       |
| Withdraw to an external crypto address         | `GET /v1/users/{userId}/wallets/crypto-offramp/supported/{currency}` → `POST /v1/users/{userId}/wallets/crypto-offramp` |

***

## Related

* [KYC — USD requirements](/api-reference/kyc-usd-requirements) — the profile fields `usd-readiness` gates on
* [KYC — Rest of world](/api-reference/kyc-row-requirements) — same rail, country-specific extras
* [Integration flow](/api-reference/integration-flow#wallet-home-operations) — every wallet-home endpoint in one table
