Virtual accounts
Understanding Virtual Accounts
Virtual accounts are dedicated banking deposit addresses assigned to a customer. They allow your customers to receive fiat payments in USD or EUR, which are automatically converted into stablecoins and delivered to the customer's wallet.
Each virtual account is linked to a specific customer and a destination wallet. Once approved, the account exposes banking details (such as account number, routing number, IBAN, etc.) that the customer can use to send fiat funds. The moment a deposit lands, UnblockPay converts it and delivers the stablecoin balance on-chain.
To create a virtual account, you must first create a Customer and a Wallet.
Virtual account statuses
|
Status |
Description |
|---|---|
|
|
The virtual account has been created and is pending approval. Deposit addresses are not yet available. |
|
|
The virtual account is active. Deposit addresses are populated and ready to receive funds. |
|
|
The virtual account was not approved. Contact support for details. |
Deposit addresses (
deposit_addresses) are only populated in the response whenstatusisapproved.
Payment rails by currency
The sender.currency you choose at creation determines which payment rails will be available once the account is approved:
|
Currency |
Available rails |
|---|---|
|
|
ACH, Wire, SWIFT |
|
|
SEPA |
Third-party deposits
Set accepts_third_party_payments: true if the EUR virtual account should accept deposits from senders other than the customer themselves (e.g. a business receiving payments from their own clients). If omitted or set to false, only deposits from the account holder will be accepted.
This field is not sent or returned for USD accounts.
Note: Only one EUR virtual account with
accepts_third_party_payments: truecan exist per customer. Attempting to create a second one will return a422 eur_virtual_account_3pp_existserror.
How to create a Virtual Account
Example for a EUR account
Request
curl --request POST \
--url https://api.unblockpay.com/v1/virtual-accounts \
--header 'Content-Type: application/json' \
--header 'api-key: <your-api-key>' \
--data '{
"customer_id": "019d7904-ec72-7754-b5f5-443defb20da0",
"name": "EUR Receiving Account",
"sender": {
"currency": "EUR"
},
"receiver": {
"currency": "USDC",
"wallet_id": "019d8001-0000-7000-8000-aabbccddeeff"
},
"accepts_third_party_payments": true
}'
Response
{
"id": "019e1234-0000-7000-8000-aabbccddeeff",
"customer_id": "019d7904-ec72-7754-b5f5-443defb20da0",
"name": "EUR Receiving Account",
"status": "under_review",
"sender": {
"currency": "EUR"
},
"receiver": {
"wallet_id": "019d8001-0000-7000-8000-aabbccddeeff",
"currency": "USDC",
"payment_rail": "ethereum",
"address": "0x742d35Cc6634C0532925a3b8D4C9C0B05f0A5E7c"
},
"deposit_addresses": {},
"accepts_third_party_payments": true,
"created_at": "2024-03-15T14:30:00Z",
"updated_at": "2024-03-15T14:30:00Z"
}
Once the virtual account is approved, the deposit_addresses object will be populated with the banking details corresponding to the sender.currency.
{
"deposit_addresses": {
"sepa": {
"iban": "DE89370400440532013000",
"bic": "COBADEFFXXX",
"bank_name": "Example Bank",
"bank_address": "123 Musterstraße, Berlin, 10115",
"beneficiary_name": "John Doe"
}
}
}
Example for a USD account
Request
curl --request POST \
--url https://api.unblockpay.com/v1/virtual-accounts \
--header 'Content-Type: application/json' \
--header 'api-key: <your-api-key>' \
--data '{
"customer_id": "019d7904-ec72-7754-b5f5-443defb20da0",
"name": "My USD Virtual Account",
"sender": {
"currency": "USD"
},
"receiver": {
"currency": "USDC",
"wallet_id": "019d8001-0000-7000-8000-aabbccddeeff"
}
}'
Response
{
"id": "019e1234-0000-7000-8000-aabbccddeeff",
"customer_id": "019d7904-ec72-7754-b5f5-443defb20da0",
"name": "My USD Virtual Account",
"status": "under_review",
"sender": {
"currency": "USD"
},
"receiver": {
"wallet_id": "019d8001-0000-7000-8000-aabbccddeeff",
"currency": "USDC",
"payment_rail": "solana",
"address": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"
},
"deposit_addresses": {},
"created_at": "2024-03-15T14:30:00Z",
"updated_at": "2024-03-15T14:30:00Z"
}
Once the virtual account is approved, the deposit_addresses object will be populated with the banking details corresponding to the sender.currency.
{
"deposit_addresses": {
"ach": {
"bank_account_number": "123456789",
"bank_name": "Example Bank",
"bank_address": "123 Main St, New York, NY 10001",
"routing_number": "987654321",
"beneficiary_name": "John Doe"
},
"wire": {
"bank_account_number": "123456789",
"bank_name": "Example Bank",
"bank_address": "123 Main St, New York, NY 10001",
"routing_number": "987654321",
"beneficiary_name": "John Doe"
},
"swift": {
"bank_account_number": "123456789",
"bank_name": "Example Bank",
"bank_address": "123 Main St, New York, NY 10001",
"bic": "EXAMUS33XXX",
"beneficiary_name": "John Doe"
}
}
}
Sandbox behavior
In the sandbox environment, virtual accounts are automatically approved upon creation. The status in the response will be approved and the deposit_addresses will already be populated with mock banking details matching the sender.currency.
Virtual Accounts API endpoints
|
Method |
Endpoint |
Description |
|---|---|---|
|
|
|
Create a new virtual account for a customer |
|
|
|
List all virtual accounts (supports pagination and filtering by |
|
|
|
Retrieve a virtual account by ID |
For the full schema and request/response details, see the API Reference.

