Virtual Accounts
Receive and send USD, EUR, and other local currencies through dedicated bank accounts.
Overview
Our Virtual Accounts product provides partners with dedicated bank accounts for sending and receiving funds in USD, EUR, and local currencies. Once onboarded, virtual accounts are automatically created for your business in each supported market. Funds received into your virtual account are credited to your balance, giving you immediate access. You can also send funds directly from your virtual accounts using either the Treasury Portal or the API.
How it works:
- Contact our team to get onboarded.
- Virtual accounts are created for your business in onboarded markets.
- Share your virtual account details with customers/clients.
- Funds received are automatically credited to your balance.
- Send funds from your virtual account using the treasury portal or API.
Key Features:
- Automatic account provisioning: Virtual accounts are created for your business upon successful onboarding in each market
- Receive funds: Funds received into your virtual account are automatically credited to your balance
- Send funds: Send payments directly from your virtual accounts via the treasury portal or payments API
- Multi-currency support: Operate across USD, EUR, and local currency markets (NGN, KES, etc)
- Multiple payment rails: USD accounts support ACH, Wire, and SWIFT transfers
- Custom wallets: Create additional virtual accounts linked to custom wallets for segregated fund management
Who This Is For
- Payment platforms that need to send and receive funds across emerging markets
- Marketplaces managing payments to sellers and receiving funds from buyers
- Remittance services sending and receiving local currency
- Businesses that need dedicated accounts per market for sending and receiving funds
- Treasury teams managing payments across multiple currencies
Step-by-Step Guide
Step 1: Get Onboarded
Contact our team to initiate the virtual bank onboarding process for your business. Once onboarding is complete, virtual accounts are automatically created for your business in the onboarded markets.
You can check your onboarding status across different markets at any time by calling the Get Onboarding Status endpoint:
{
"onboardings": [
{
"provider": "erebor",
"currencies": ["USD"],
"status": "SUCCESSFUL",
"type": "business",
"onboardedAt": "2025-01-20T14:00:00.000Z"
}
]
}Onboarding statuses:
- SUCCESSFUL: Onboarding is complete, virtual accounts have been created in the supported currencies
- PENDING: Onboarding is in progress
- INACTIVE Onboarding has been deactivated
Step 2: View Your Virtual Accounts
After successful onboarding, List Virtual Accounts to see the accounts that have been created for your business in each onboarded market.
{
"virtualAccounts": [
{
"id": "f9e8d7c6-b5a4-3210-fedc-ba0987654321",
"currency": "USD",
"accountNumber": "0123456789",
"routingNumber": "058",
"swiftCode": "FVBKPRSX",
"accountName": "YC / Acme Corp",
"bankName": "Erebor",
"bankAddress": "",
"status": "ACTIVE",
"createdAt": "2025-01-20T14:00:00.000Z",
"updatedAt": "2025-01-20T14:00:00.000Z"
},
{
"id": "a2b3c4d5-e6f7-8901-bcde-f12345678901",
"userId": "9ecf5248-17e7-4a2b-b5a8-3bd58ff0fe01",
"currency": "NGN",
"accountNumber": "9876543210",
"routingNumber": "",
"accountName": "YC / Acme Corp",
"bankName": "UBA",
"bankAddress": "",
"status": "ACTIVE",
"createdAt": "2025-01-15T10:30:00.000Z",
"updatedAt": "2025-01-15T10:30:00.000Z"
}
],
"pagination": {
"pageSize": 15,
"total": 2
}
}You can filter your virtual accounts using the following query parameters:
currency— filter by currency code (e.g.,NGN,USD,KES)status— filter by account status (PENDING,ACTIVE,CLOSED,FROZEN)pageSize— number of results per page (default: 15, max: 100)cursor— pagination cursor returned asnextCursorin a previous response
Share the accountNumber, bankName, and accountName. Funds received into these accounts are automatically credited to your balance.
Supported Payment Rails
| Currency | Payment Rails |
|---|---|
| USD | ACH, Wire, SWIFT |
| EUR (coming soon) | SEPA, SWIFT |
| Local currencies (NGN, KES, ZAR, UGX) | Local bank transfer |
Step 3: Receive Funds
When someone sends funds to your virtual account, the payment is automatically processed and credited to your balance. No additional API calls are required to receive funds.
- Primary virtual accounts: Received funds are credited to your main balance
- Custom wallet virtual accounts: Received funds are credited to the custom wallet balance
Step 4: Create Additional Virtual Accounts (Optional)
You can create additional virtual accounts by creating a custom wallet with createVirtualAccount set to true. This is useful when you need segregated accounts for different clients, use cases, or business units.
POST /sub-wallets
{
"name": "Merchant Collection - Acme Corp",
"sequenceId": "merchant-acme-001",
"currency": "NGN",
"createVirtualAccount": true
}{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"partnerId": "9ecf5248-17e7-4a2b-b5a8-3bd58ff0fe01",
"sequenceId": "merchant-acme-001",
"name": "Merchant Collection - Acme Corp",
"currency": "NGN",
"status": "active",
"availableBalance": 0,
"createdAt": "2025-02-10T12:00:00.000Z",
"updatedAt": "2025-02-10T12:00:00.000Z",
"virtualAccount": {
"id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
"userId": "9ecf5248-17e7-4a2b-b5a8-3bd58ff0fe01",
"subwalletId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"currency": "NGN",
"accountNumber": "1122334455",
"routingNumber": "",
"accountName": "YC / Acme Corp",
"bankName": "GTBank",
"bankAddress": "",
"status": "ACTIVE",
"createdAt": "2025-02-10T12:00:00.000Z",
"updatedAt": "2025-02-10T12:00:00.000Z"
}
}You can also list your custom wallets with their linked virtual accounts using the withVirtualAccount query parameter:
GET /sub-wallets?withVirtualAccount=trueStep 5: Send Funds
Send funds from your primary wallet or from a custom wallet using the Submit Payment Request. Pass the channelId of the virtual bank provider in the request alongside the destination details.
POST /business/payments
{
"source": {
"accountType": "bank"
},
"channelId": "af944f0c-ba70-47c7-86dc-1bad5a6ab4e4",
"sequenceId": "payout-001",
"sender": {
"name": "Acme Corp",
"country": "Nigeria",
"address": "123 Business Ave, Lagos",
"dob": "01/01/1990",
"email": "[email protected]",
"idNumber": "RC123456",
"idType": "passport"
},
"destination": {
"accountNumber": "0400440532013000",
"networkId": "0400440532013000",
"accountType": "bank",
"accountName": "Acme GmbH",
"outboundTransactionType": "SWIFT",
"swiftCode": "COBADEFFXXX",
"iban": "DE89370400440532013000",
"city": "Berlin",
"postalCode": "10115",
"country": "DE",
"address": "Friedrichstraße 100"
},
"amount": 50,
"reason": "services"
}The
channelIdidentifies the virtual bank provider channel. Use the channels endpoint to retrieve the appropriatechannelIdfor virtual bank sends in your market.
Step 6: Get a Specific Virtual Account
Retrieve the details for a specific virtual account by its ID.
GET /virtual-accounts/f9e8d7c6-b5a4-3210-fedc-ba0987654321{
"id": "f9e8d7c6-b5a4-3210-fedc-ba0987654321",
"userId": "9ecf5248-17e7-4a2b-b5a8-3bd58ff0fe01",
"currency": "NGN",
"accountNumber": "0123456789",
"routingNumber": "058",
"accountName": "YC / Acme Corp",
"bankName": "GTBank",
"bankAddress": "Lagos, Nigeria",
"status": "ACTIVE",
"createdAt": "2025-01-20T14:00:00.000Z",
"updatedAt": "2025-01-20T14:00:00.000Z"
}Virtual Account Statuses
| Status | Description |
|---|---|
PENDING | Account has been requested but is not yet open |
ACTIVE | Account is active and ready to receive and send payments |
FROZEN | Account is temporarily frozen for compliance review |
CLOSED | Account is closed |
Virtual Account Object
| Field | Type | Description |
|---|---|---|
id | string | Virtual account unique identifier |
userId | string | Partner identifier who owns the account |
subwalletId | string | Associated custom wallet identifier (only for custom wallet virtual accounts) |
currency | string | Account currency code (e.g., NGN, USD, KES) |
accountNumber | string | Bank account number |
routingNumber | string | Bank routing number |
accountName | string | Account holder name |
bankName | string | Bank name |
bankAddress | string | Bank physical address |
swiftCode | string | SWIFT code (if applicable, typically for USD accounts) |
status | string | Account status: PENDING, ACTIVE, CLOSED, FROZEN |
createdAt | string | ISO 8601 timestamp when the account was created |
updatedAt | string | ISO 8601 timestamp when the account was last updated |
- For more information on creating additional virtual accounts, visit Create Virtual Accounts
- For a guide on how to send funds from virtual accounts, visit Send Funds
- For understanding virtual account webhooks and events, visit Webhooks
Updated 21 days ago
