Stablecoin virtual accounts explained: from bank transfer to wallet balance
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.
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).
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.
- Verify the customer. KYC for individuals, KYB for businesses. BlindPay:
kyc_statusmust beapprovedbefore you can request an account. - Fill in the compliance profile. Banks review the account holder, not just the identity. BlindPay: businesses need
account_purpose,business_type,business_description, a NAICSbusiness_industrycode,estimated_annual_revenue,source_of_wealth,publicly_traded, and at least one owner withownership_percentageandtitle. Leave a field blank and the request fails withmissing_required_fieldsnaming it. - Link a wallet. Every deposit settles somewhere. BlindPay: the account points to one
blockchain_wallet_idbelonging to the same customer, and you pick thetoken, USDC or USDT. - Request the account. BlindPay: one
POSTto/customers/{customer_id}/virtual-accountswith abanking_partner,token, and wallet (create a virtual account). - Wait for review. BlindPay: the account starts in
pending_review(compliance), moves toverifying(bank), and endsapprovedorrejected. ThevirtualAccount.completewebhook fires on approval, with the rail numbers in the payload. - Share the details. Put the account number in your UI, on invoices, wherever payers look.
- A deposit arrives. BlindPay: each deposit creates a payin and fires
payin.new. When it's converted and the stablecoin lands,payin.completefires.
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.
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
jpmorganpartner 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.
- 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_holdfor 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:
- Whose name is on the account? Named accounts in your customer's name beat pooled accounts with memo codes.
- Which rails does it receive? ACH only, or wire and SWIFT too? Foreign senders need SWIFT.
- How long is approval, in writing? Get the SLA per account type and ask what restarts the clock.
- What does the stablecoin leg look like? Which tokens, which chains, and can you change the destination wallet later? At BlindPay you can update
tokenandblockchain_wallet_idon an existing account. - 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 covers the bank relationships a virtual account quietly depends on. For the flow a virtual account feeds into, see how a stablecoin payment moves. Merchants collecting from customers can compare this with the options in how merchants accept stablecoin payments.
Where does BlindPay fit?
BlindPay 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, then check the account requirements so production review doesn't bounce your first real customer.
To compare providers, the best virtual account providers for stablecoins in 2026 lines up five of them on deposit rails, settlement chains, and custody, with a 30-day test plan.
This article is for general information only and is not legal, tax, or financial advice.
FAQ
More payments articles
See all payments articlesHow to add stablecoin payments to your wallet integration
Connect the wallets you already run to bank deposits and local payouts: register addresses, open virtual accounts, quote, authorize, and track webhooks.
How to send USDC to a bank account in Brazil
Step-by-step: convert USDC to Brazilian reais and deliver them to a bank account over Pix using a stablecoin payout API. Quote, verify, send, settle in minutes.
What is a virtual account? A plain-English guide for fintech teams
A virtual account is a unique set of bank details that routes incoming payments to one customer or purpose. How it works, who uses it, and where it fits.