---
title: "Stablecoin virtual accounts explained: from bank transfer to wallet balance"
seoTitle: "Stablecoin virtual accounts explained"
description: "A stablecoin virtual account is a bank account in your customer's name whose deposits convert to USDC or USDT. How approval, deposits, and fees work."
date: "2026-07-28"
category: "payments"
author: "BlindPay Team"
faq:
  - q: "What is a stablecoin virtual account?"
    a: "A dedicated bank account issued in your customer's name, with its own routing and account number, whose incoming deposits are converted to a stablecoin like USDC or USDT and delivered to a linked wallet. The payer sends an ordinary bank transfer; the stablecoin conversion happens after the deposit lands."
  - q: "Is a virtual account the same as a crypto wallet?"
    a: "No. A virtual account receives fiat over bank rails like ACH, wire, and SWIFT. A blockchain wallet holds stablecoins. The virtual account is linked to a wallet, and every deposit into the account ends up as stablecoin in that wallet."
  - q: "How long does it take to open a stablecoin virtual account?"
    a: "It depends on the provider and account type. At BlindPay, production accounts go through compliance review and then bank review. The US account for individuals and businesses has a 24-hour SLA; the business accounts for US-only or foreign-only senders take 3 to 5 business days. Approval is not guaranteed at either stage."
  - q: "How much does a virtual account cost at BlindPay?"
    a: "$1.50 per month per account. Each deposit creates a payin with its own fee: below $100.00 the fee accrues to your monthly invoice, and at $100.00 or more it is deducted from the stablecoin delivered at the time of the transaction."
  - q: "Can I test virtual accounts before going live?"
    a: "Yes. On a BlindPay development instance, virtual accounts skip both review stages and are created directly as approved. The routing number is always 110000000 and the account number is a fake 12-digit number derived from the account id, so you can build deposit handling and webhooks before any real bank is involved."
---

A stablecoin virtual account is a real bank account issued in your customer's name, with its own routing and account number, that converts every incoming deposit into USDC or USDT and sends it to a linked wallet. The payer sends a normal ACH, wire, or SWIFT transfer. Your customer ends up with a stablecoin balance. Nobody builds a checkout.

The account number is the integration. That's the whole idea.

## What is a stablecoin virtual account, and what isn't it?

Three things get confused here, and they solve different problems.

| | Virtual account | One-time payment instruction | Blockchain wallet |
| --- | --- | --- | --- |
| What it receives | Fiat over bank rails | Fiat over bank rails | Stablecoins on-chain |
| Reusable? | Yes, same details every time | No, one instruction per payment | Yes |
| Whose name is on it | Your customer's | Usually the provider's pooled account | Nobody's (it's an address) |
| How a deposit is matched | By the account number itself | By a reference or memo code the payer must type | By the address |
| What goes wrong | Approval takes time | Payer forgets the memo, deposit sits unmatched | Wrong network, wrong token |

A virtual account is not a customer-controlled bank account either. Your customer can't write checks from it or log into a bank portal. It exists to receive money and turn it into stablecoin.

In BlindPay's API the difference is visible on the payin itself. Without a virtual account, an ACH or wire payin returns a `memo_code` and BlindPay's shared bank details. With an approved virtual account, the payer sees the customer's own dedicated account details and the memo code is ignored ([payins](/docs/payins)).

## What details does the payer use?

The same ones they'd use for any US bank account: routing number, account number, and for international senders, SWIFT details and the receiving bank's name and address. BlindPay returns ACH and wire numbers once the account is approved, plus SWIFT and receiving-bank details. Before approval, the rail numbers are empty.

So the payer doesn't need to know anything about stablecoins. They're paying a bank account. A foreign client paying a Brazilian freelancer sends a SWIFT wire to a US account number. The freelancer ends up holding USDC.

One detail matters for B2B: when a virtual account is issued to an end user, payouts from it go out under that end user's name, not a pooled account name. The recipient sees who actually paid them.

## What happens from account request to wallet balance?

Walk through one account. Steps marked **BlindPay** follow our documented API; the rest is the generic pattern most providers share.

1. **Verify the customer.** KYC for individuals, KYB for businesses. **BlindPay:** `kyc_status` must be `approved` before you can request an account.
2. **Fill in the compliance profile.** Banks review the account holder, not just the identity. **BlindPay:** businesses need `account_purpose`, `business_type`, `business_description`, a NAICS `business_industry` code, `estimated_annual_revenue`, `source_of_wealth`, `publicly_traded`, and at least one owner with `ownership_percentage` and `title`. Leave a field blank and the request fails with `missing_required_fields` naming it.
3. **Link a wallet.** Every deposit settles somewhere. **BlindPay:** the account points to one `blockchain_wallet_id` belonging to the same customer, and you pick the `token`, USDC or USDT.
4. **Request the account.** **BlindPay:** one `POST` to `/customers/{customer_id}/virtual-accounts` with a `banking_partner`, `token`, and wallet ([create a virtual account](/docs/virtual-accounts-create)).
5. **Wait for review.** **BlindPay:** the account starts in `pending_review` (compliance), moves to `verifying` (bank), and ends `approved` or `rejected`. The `virtualAccount.complete` webhook fires on approval, with the rail numbers in the payload.
6. **Share the details.** Put the account number in your UI, on invoices, wherever payers look.
7. **A deposit arrives.** **BlindPay:** each deposit creates a [payin](/docs/payins) and fires `payin.new`. When it's converted and the stablecoin lands, `payin.complete` fires.

## What should the product show at each state?

Verify the exact status names against your provider's docs before you build this. These are BlindPay's.

| State | What the user should see |
| --- | --- |
| Account `pending_review` | "Your account is being reviewed." No account number yet. |
| Account `verifying` | "Almost ready, the bank is confirming your account." Still no number. |
| Account `approved` | The routing and account number, with copy buttons. |
| Account `rejected` | A clear message and the next step, not a spinner that never ends. |
| Deposit payin `processing` | "Deposit on the way." Show amount and payment method. |
| Deposit payin `on_hold` | "Under review." Don't imply the money is lost. |
| Deposit payin `completed` | Stablecoin balance updated, with the amount actually delivered. |
| Deposit payin `failed` or `refunded` | The deposit didn't go through or went back to the sender. Explain which. |

Show the delivered amount, not the deposited amount. Fees come off in between.

## How do fees and micro-deposits work?

BlindPay charges $1.50 per month per account. Each deposit is its own payin, and where the fee lands depends on size:

| Deposit | Where the BlindPay fee lands | Field on the payin |
| --- | --- | --- |
| Below $100.00 | Accrued to your invoice at the end of the billing cycle | `billing_fee_amount` |
| $100.00 or more | Deducted from the delivered stablecoin at transaction time | `transaction_fee_amount` |

Every deposit is processed, including the $0.01 micro-deposits some platforms send to verify an account, and always delivers at least $0.01 of stablecoin. That's worth knowing when a customer connects the account to a payroll provider or marketplace that tests with pennies. Those tests will show up as payins. Reconcile them, don't flag them as fraud. Full details in [virtual accounts](/docs/virtual-accounts).

## How should you handle rejection, delays, and exceptions?

Plan for these before launch, not after the first support ticket.

- **Rejected account request.** Either review stage can reject. At BlindPay, a customer can't hold two non-deleted, non-rejected accounts on the same banking partner (the `jpmorgan` partner is the exception, since each account is a separate sub-account). After a rejection, fix the underlying issue and request again.
- **Slow approval.** Bank review varies by partner and account type. If the bank asks for more documents, the SLA clock restarts when you submit them. Source of funds and source of wealth documents are the usual ask; the list is in the [virtual account requirements](/docs/kb/virtual-accounts).
- **Delayed funds.** ACH and wire deposits can take up to 5 business days to arrive. Cut-offs push late transfers to the next business day.
- **Deposits under review.** A deposit can land `on_hold` for compliance review. It resumes when cleared.
- **Eligibility.** Some banking partners serve only US customers, others only non-US businesses. Check which partner fits your customer base before you design onboarding around one account type.

## What should you check before choosing a provider?

Five questions that separate a real virtual account from a marketing page:

1. **Whose name is on the account?** Named accounts in your customer's name beat pooled accounts with memo codes.
2. **Which rails does it receive?** ACH only, or wire and SWIFT too? Foreign senders need SWIFT.
3. **How long is approval, in writing?** Get the SLA per account type and ask what restarts the clock.
4. **What does the stablecoin leg look like?** Which tokens, which chains, and can you change the destination wallet later? At BlindPay you can update `token` and `blockchain_wallet_id` on an existing account.
5. **How are fees itemized per deposit?** You want the fee as a field on every deposit, not a surprise on the invoice.

Not every provider supports the same rails or issues accounts at the same speed. Ask for the account types table, not the headline.

If you're deciding whether to run this yourself, [build vs buy](/resources/more/build-vs-buy-stablecoin-payments) covers the bank relationships a virtual account quietly depends on. For the flow a virtual account feeds into, see [how a stablecoin payment moves](/resources/more/how-a-stablecoin-payment-works). Merchants collecting from customers can compare this with the options in [how merchants accept stablecoin payments](/resources/more/how-merchants-accept-stablecoin-payments).

## Where does BlindPay fit?

[BlindPay virtual accounts](/virtual-accounts) give each customer a US bank account in their own name that receives ACH, wire, and SWIFT and settles to USDC or USDT in a linked wallet. The same API pays out over Pix, SPEI, ACH, RTP, SEPA, and SWIFT (POBO/COBO) to 100+ countries with no pre-funding, and runs KYC, KYB, and sanctions screening inside the flow.

## What to do next

Create a virtual account on a free development instance today. It's approved instantly, with routing number `110000000`, so you can wire up `virtualAccount.complete` and `payin.complete` handling in an afternoon. Start with [create a virtual account](/docs/virtual-accounts-create), then check the [account requirements](/docs/kb/virtual-accounts) so production review doesn't bounce your first real customer.

*This article is for general information only and is not legal, tax, or financial advice.*
