Skip to main content
A virtual bank account (VBA) gives an account its own bank coordinates to receive fiat. Incoming credits are automatically converted to a stablecoin and credited to the account’s wallet.

Prerequisites

The account must be verified and have a linked account-holder party.

Lanes

The rail is resolved from the inCurrency you request and your tenant’s enabled pay-in configuration — you don’t pick a provider.

Create a virtual bank account

Provide a display name, the fiat inCurrency, the targetCryptocurrency to convert to, and a unique idempotencyKey:
Response

The fields that matter

Anyone can pay in. Deposits are accepted from any bank account, not only the account holder’s own — a company funding an end user, one person paying for another, or a partner settling on someone’s behalf.
Always surface the referenceCode to the end user and tell them to include it in their transfer. It’s how an incoming credit is routed to the right account.

Summary fields vs. depositRails

The top-level iban/bic/accountNumber/routingNumber fields always describe the primary rail. depositRails lists every rail the account is reachable over. A USD account typically exposes four rails sharing the same account and routing number — except SWIFT, which carries a BIC instead of a routing number: A EUR account exposes a single SEPA rail.
Build your payment-instruction UI from depositRails rather than the summary fields. If you only render iban/accountNumber, a customer sending by wire or SWIFT will be missing the bank address their bank asks for.

PENDING accounts

On the EUR lane, an account can come back status: PENDING with bankAccountType omitted — the provider hasn’t returned the deposit rails yet. Don’t show payment instructions until it reaches ACTIVE and depositRails is populated. Register a webhook to hear about the transition instead of polling.

Proving wallet ownership

On some setups, converted funds settle straight to the customer’s own self-custody wallet. Where that applies, the customer must prove they control that wallet first — Venly can’t sign for a wallet it doesn’t hold the keys for. You don’t need to know up front whether this applies to you. Call prepare: if a proof is required you get the exact message to sign, and if it isn’t you get 400 ownership-proof-not-applicable and can create the account directly.
1

Ask for the message

POST /accounts/{accountId}/virtual-bank-accounts/prepare with the destination walletAddress and blockchain.Nothing is persisted — no preparation id, no expiry. Two calls for the same account and wallet return an equivalent message, so this is safe to repeat.
2

Have the customer sign it verbatim

The customer signs message exactly as returned, blind. It embeds an opaque provider token, so don’t reformat, re-encode, pretty-print, or reconstruct it — the signature is checked against those exact bytes.
3

Submit it with the create call

Include the ownershipProof block — walletAddress, blockchain, message, signature — when creating the virtual bank account.
Where a proof isn’t required the ownershipProof field is ignored, so you can send it unconditionally if that is simpler than branching. Only an externally-owned account can sign: the scheme is EIP-191, and ERC-1271 contract signatures are not supported. Self-custody wallets are single-key wallets only for now.

Verification gates

Provisioning onboards the account holder for verification, so their verification state can block you.
A verified party is not automatically ready. The account holder must also have accepted our partners’ terms themselves — see Partner-terms consent. Until that acceptance is recorded, provisioning is blocked, and the fix is to present the party’s consent link to your end customer rather than to retry.
These states can block you:

Reading them back

Closing a virtual bank account

POST /accounts/{accountId}/virtual-bank-accounts/{virtualBankAccountId}/close moves an ACTIVE account to CLOSED and asks the payment provider to decommission the bank details. There is no request body. The local transition is applied before the provider is contacted, so a provider outage never blocks a closure — but it also means CLOSED alone does not tell you the bank details are dead. Read providerClosureStatus on the response:
Money that still arrives on closed details — after a FAILED closure, or in the window before an in-flight transfer lands — is never lost. It is recorded and can be settled by Venly afterwards, and it stays visible under List pay-ins filtered by the closed virtualBankAccountId.
Closing frees the account’s (currency, targetCryptocurrency) slot immediately, so you can create a replacement straight away. It is also how you resolve duplicate-eur-vba — an account may hold only one active EUR virtual bank account so that incoming credits can be attributed. CLOSED accounts stay visible in list and detail reads.

Next steps

Wallets & balances

Where converted funds land.

Pay-outs

The other direction: crypto out, fiat to a bank beneficiary.

Supported chains & assets

Which fiat currencies and stablecoins are supported.

Webhooks

Hear about deposits and rail population without polling.