Overview
Virtual accounts provide unique bank account numbers that can receive payments. They can be dedicated (permanent) or dynamic (temporary sessions for specific transactions).
Virtual Account Types
Virtual accounts come in different types based on their lifecycle and usage pattern.
| Type | Description | Use Case |
|---|---|---|
| dedicated | Permanent virtual account tied to a wallet account | Long-term collections, recurring payments, customer funding accounts |
| dynamic | Temporary session-based account number with expiration | One-time payments, invoice-specific collections, time-limited transactions |
| capability | Feature-enabled account for specific integrations | POS settlements, processor integrations, specialized payment flows |
Virtual Account Purposes
Each virtual account is assigned a purpose that determines its behavior and routing.
| Purpose | Description |
|---|---|
| wallet_funding | Receives deposits to fund wallet accounts |
| wallet_payment | Receives payments for wallet-based transactions |
| collections | General-purpose collection account for businesses |
| pos | Settlement account for POS terminal transactions |
Status Definitions
| Status | Description | Can Receive Payments |
|---|---|---|
| active | Virtual account is operational and can receive payments | Yes |
| expired | Dynamic session has passed its expiration time | No |
| closed | Virtual account has been permanently deactivated | No |
Provider Integrations
Virtual accounts are provisioned through various banking partners and payment providers.
| Provider | Banks Supported | Features |
|---|---|---|
| providus | Providus Bank | Dedicated and dynamic VAs, instant notification |
| wema | Wema Bank (ALAT) | Dedicated VAs, corporate collections |
| gtb | GTBank | Dedicated VAs, high-volume collections |
| sterling | Sterling Bank | Dynamic VAs, session-based payments |
List Virtual Accounts
Retrieve virtual accounts across all tenants with comprehensive filtering options.
Endpoint
/api/v1/admin/virtual-accountsList all virtual accounts across the platform. Supports filtering by tenant, provider, status, type, and purpose. Can optionally include active sessions for dynamic accounts.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | No | Filter by tenant UUID |
account_id | string | No | Filter by linked wallet account UUID |
provider | string | No | Filter by banking providerValues: providus, wema, gtb, sterling |
status | string | No | Filter by virtual account statusValues: active, expired, closed |
account_type | string | No | Filter by virtual account typeValues: dynamic, dedicated, capability |
purpose | string | No | Filter by virtual account purposeValues: wallet_funding, wallet_payment, collections, pos |
query | string | No | Search by account name, number, or reference |
number | string | No | Exact match on virtual account number |
sort_by | string | No (default: created_at) | Sort fieldValues: created_at, virtual_account_number |
sort_order | string | No (default: desc) | Sort orderValues: asc, desc |
include_sessions | boolean | No (default: false) | Include active sessions for dynamic virtual accounts |
limit | integer | No (default: 20) | Page size (max 200) |
offset | integer | No (default: 0) | Page offset |
Response- Paginated list of virtual accounts with tenant and linked account details
{
"data": [
{
"virtual_account": {
"id": "va_550e8400-e29b-41d4-a716-446655440000",
"account_id": "acc_660e8400-e29b-41d4-a716-446655440001",
"account_type": "dedicated",
"purpose": "wallet_funding",
"virtual_account_number": "9900123456",
"account_name": "John Doe/WalletCore",
"provider": "providus",
"provider_reference": "PVD-REF-12345",
"bank_name": "Providus Bank",
"bank_code": "101",
"status": "active",
"expires_at": null,
"created_at": "2025-01-10T08:00:00Z",
"metadata": {
"customer_id": "cust_123",
"source": "api"
}
},
"tenant_id": "tenant_770e8400-e29b-41d4-a716-446655440002",
"tenant_name": "Acme Corp",
"account": {
"id": "acc_660e8400-e29b-41d4-a716-446655440001",
"account_code": "ACC-001234",
"account_name": "John Doe Wallet",
"currency": "NGN",
"product_type": "wallet",
"wallet_type": "customer",
"status": "active"
},
"sessions": []
},
{
"virtual_account": {
"id": "va_880e8400-e29b-41d4-a716-446655440003",
"account_id": "acc_990e8400-e29b-41d4-a716-446655440004",
"account_type": "dynamic",
"purpose": "collections",
"virtual_account_number": "9900789012",
"account_name": "Tech Solutions Ltd/Invoice-2025-001",
"provider": "sterling",
"provider_reference": "STL-REF-67890",
"bank_name": "Sterling Bank",
"bank_code": "232",
"status": "active",
"expires_at": "2025-01-15T23:59:59Z",
"created_at": "2025-01-14T09:00:00Z",
"metadata": {
"invoice_id": "INV-2025-001",
"expected_amount": 150000
}
},
"tenant_id": "tenant_770e8400-e29b-41d4-a716-446655440002",
"tenant_name": "Acme Corp",
"account": {
"id": "acc_990e8400-e29b-41d4-a716-446655440004",
"account_code": "ACC-005678",
"account_name": "Tech Solutions Ltd",
"currency": "NGN",
"product_type": "wallet",
"wallet_type": "business",
"status": "active"
},
"sessions": [
{
"id": "sess_110e8400-e29b-41d4-a716-446655440005",
"session_account_number": "9900789012",
"status": "active",
"expected_amount": 150000,
"credited_amount": 0,
"created_at": "2025-01-14T09:00:00Z",
"expires_at": "2025-01-15T23:59:59Z"
}
]
}
],
"pagination": {
"limit": 20,
"offset": 0,
"total_count": 15420
}
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 403 | forbidden | Admin role required |
| 400 | invalid_filter | Invalid filter parameter value |
Query Parameters Reference
| Parameter | Type | Description |
|---|---|---|
| tenant_id | UUID | Filter to specific tenant |
| account_id | UUID | Filter to specific linked wallet account |
| provider | string | Bank provider (providus, wema, gtb, sterling) |
| status | string | Virtual account status |
| account_type | string | Type: dynamic, dedicated, or capability |
| purpose | string | Purpose: wallet_funding, wallet_payment, collections, pos |
| query | string | Free-text search across name, number, reference |
| number | string | Exact virtual account number match |
| include_sessions | boolean | Include active sessions for dynamic VAs |
List Virtual Account Sessions
Retrieve dynamic virtual account sessions across all tenants. Sessions are temporary account numbers created for specific payment expectations.
Endpoint
/api/v1/admin/virtual-account-sessionsList all dynamic virtual account sessions. Sessions track expected payments with amounts, expiration times, and inflow details. Useful for monitoring payment completion rates and reconciliation.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer {admin_access_token} |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tenant_id | string | No | Filter by tenant UUID |
account_id | string | No | Filter by linked wallet account UUID |
virtual_account_id | string | No | Filter by parent virtual account UUID |
provider | string | No | Filter by banking provider |
status | string | No | Filter by session statusValues: active, expired, closed |
number | string | No | Exact match on session account number |
created_from | string | No | Filter sessions created after this date (ISO 8601) |
created_to | string | No | Filter sessions created before this date (ISO 8601) |
expires_from | string | No | Filter sessions expiring after this date (ISO 8601) |
expires_to | string | No | Filter sessions expiring before this date (ISO 8601) |
include_inflow | boolean | No (default: false) | Include inflow transaction details for credited sessions |
limit | integer | No (default: 20) | Page size (max 200) |
offset | integer | No (default: 0) | Page offset |
Response- Paginated list of dynamic sessions with virtual account, tenant, and optional inflow details
{
"data": [
{
"id": "sess_110e8400-e29b-41d4-a716-446655440005",
"virtual_account_id": "va_880e8400-e29b-41d4-a716-446655440003",
"session_account_number": "9900789012",
"status": "active",
"created_at": "2025-01-14T09:00:00Z",
"expires_at": "2025-01-15T23:59:59Z",
"closed_at": null,
"expected_amount": 150000,
"credited_amount": 150000,
"credited_at": "2025-01-14T14:30:00Z",
"tenant_id": "tenant_770e8400-e29b-41d4-a716-446655440002",
"tenant_name": "Acme Corp",
"account": {
"id": "acc_990e8400-e29b-41d4-a716-446655440004",
"account_code": "ACC-005678",
"account_name": "Tech Solutions Ltd",
"currency": "NGN",
"product_type": "wallet",
"wallet_type": "business",
"status": "active"
},
"virtual_account": {
"id": "va_880e8400-e29b-41d4-a716-446655440003",
"account_id": "acc_990e8400-e29b-41d4-a716-446655440004",
"account_type": "dynamic",
"purpose": "collections",
"virtual_account_number": "9900789012",
"account_name": "Tech Solutions Ltd/Invoice-2025-001",
"provider": "sterling",
"provider_reference": "STL-REF-67890",
"bank_name": "Sterling Bank",
"bank_code": "232",
"status": "active",
"expires_at": "2025-01-15T23:59:59Z",
"created_at": "2025-01-14T09:00:00Z",
"metadata": {}
},
"inflow": {
"transaction_id": "txn_220e8400-e29b-41d4-a716-446655440006",
"amount": 150000,
"currency": "NGN",
"status": "completed",
"description": "Payment for Invoice INV-2025-001",
"created_at": "2025-01-14T14:28:00Z",
"completed_at": "2025-01-14T14:30:00Z",
"failed_at": null,
"reversal_of_transaction_id": null,
"reversed_by_transaction_id": null,
"provider_payload": {
"session_id": "STL-SESS-12345",
"sender_account_number": "0123456789",
"sender_account_name": "CUSTOMER ABC",
"sender_bank_code": "058",
"sender_bank_name": "GTBank",
"payment_reference": "PAY-REF-2025-001",
"narration": "Payment for services",
"transaction_date": "2025-01-14T14:28:00Z"
}
}
}
],
"pagination": {
"limit": 20,
"offset": 0,
"total_count": 8540
}
}Error Responses
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid admin JWT |
| 403 | forbidden | Admin role required |
| 400 | invalid_date_range | Invalid date format or range |
Session Lifecycle
Understanding the session lifecycle helps in monitoring payment flows.
| Stage | Status | Description |
|---|---|---|
| Created | active | Session created with expected amount, awaiting payment |
| Credited | active | Payment received, credited_amount > 0, credited_at set |
| Expired | expired | Session passed expires_at without full payment |
| Closed | closed | Session manually closed by admin or system |
Inflow Transaction Status
The inflow object tracks the actual payment received on the session.
| Status | Description |
|---|---|
| pending | Payment notification received, processing in progress |
| completed | Payment successfully credited to the linked account |
| failed | Payment processing failed, no credit applied |
| reversed | Payment was reversed after initial completion |
Provider Payload Fields
The provider_payload contains raw payment details from the banking partner. Common fields include:
| Field | Description |
|---|---|
| session_id | Provider's internal session identifier |
| sender_account_number | Payer's bank account number |
| sender_account_name | Payer's account name as registered with their bank |
| sender_bank_code | CBN code of the payer's bank |
| sender_bank_name | Name of the payer's bank |
| payment_reference | Unique payment reference from provider |
| narration | Payment description provided by the payer |
| transaction_date | Timestamp when payment was processed by the provider |
Data Models
Reference documentation for the data structures returned by virtual account APIs.
VirtualAccountSummary
Core virtual account information.
| Field | Type | Description |
|---|---|---|
| id | string | Unique virtual account identifier |
| account_id | string | UUID of linked wallet account |
| account_type | string | Type: dynamic, dedicated, or capability |
| purpose | string | Purpose: wallet_funding, wallet_payment, collections, pos |
| virtual_account_number | string | 10-digit NUBAN account number |
| account_name | string | Name displayed on bank statements |
| provider | string | Banking provider (providus, wema, etc.) |
| provider_reference | string | null | Provider's internal reference |
| bank_name | string | Full name of the bank |
| bank_code | string | CBN bank code |
| status | string | Current status (active, expired, closed) |
| expires_at | string | null | Expiration timestamp for dynamic VAs |
| created_at | string | Creation timestamp |
| metadata | object | Custom metadata attached to the VA |
AccountSummary
Linked wallet account information.
| Field | Type | Description |
|---|---|---|
| id | string | Unique account identifier |
| account_code | string | Human-readable account code |
| account_name | string | Account holder name |
| currency | string | Account currency (e.g., NGN) |
| product_type | string | Product type (wallet, savings, etc.) |
| wallet_type | string | Wallet type (customer, business, pos) |
| status | string | Account status |
DynamicSession
Session for dynamic virtual accounts.
| Field | Type | Description |
|---|---|---|
| id | string | Unique session identifier |
| virtual_account_id | string | Parent virtual account UUID |
| session_account_number | string | Account number for this session |
| status | string | Session status (active, expired, closed) |
| created_at | string | Session creation timestamp |
| expires_at | string | Session expiration timestamp |
| closed_at | string | null | When session was closed (if applicable) |
| expected_amount | number | Expected payment amount in minor units |
| credited_amount | number | Actual amount credited |
| credited_at | string | null | When payment was credited |
| tenant_id | string | Owning tenant UUID |
| tenant_name | string | Owning tenant name |
| account | AccountSummary | Linked wallet account details |
| virtual_account | VirtualAccountSummary | Parent virtual account details |
| inflow | SessionInflow | null | Payment transaction details (if include_inflow=true) |
SessionInflow
Payment transaction received on a session.
| Field | Type | Description |
|---|---|---|
| transaction_id | string | Unique transaction identifier |
| amount | number | Transaction amount in minor units |
| currency | string | Transaction currency |
| status | string | Transaction status (pending, completed, failed, reversed) |
| description | string | null | Payment description |
| created_at | string | Transaction creation timestamp |
| completed_at | string | null | When transaction completed |
| failed_at | string | null | When transaction failed |
| reversal_of_transaction_id | string | null | If this is a reversal, the original transaction |
| reversed_by_transaction_id | string | null | If reversed, the reversing transaction |
| provider_payload | object | Raw payment details from banking provider |
Common Use Cases
Examples of how to use the virtual account APIs for common scenarios.
Monitor Pending Sessions
Find all sessions awaiting payment that are close to expiration.
# Find active sessions expiring in the next 24 hours with no credit
curl -X GET \
'https://api.walletcore.dev/api/v1/admin/virtual-account-sessions?
status=active&
expires_to=2025-01-15T23:59:59Z&
include_inflow=true' \
-H 'Authorization: Bearer {admin_token}'Find Virtual Accounts by Provider
List all virtual accounts from a specific banking provider.
# List all Providus virtual accounts
curl -X GET \
'https://api.walletcore.dev/api/v1/admin/virtual-accounts?
provider=providus&
status=active&
limit=100' \
-H 'Authorization: Bearer {admin_token}'Reconcile Tenant Payments
Get all sessions with inflows for a specific tenant.
# Get all credited sessions for a tenant
curl -X GET \
'https://api.walletcore.dev/api/v1/admin/virtual-account-sessions?
tenant_id=tenant_770e8400-e29b-41d4-a716-446655440002&
created_from=2025-01-01T00:00:00Z&
include_inflow=true' \
-H 'Authorization: Bearer {admin_token}'Search by Account Number
Find a virtual account by its exact account number.
# Find virtual account by number
curl -X GET \
'https://api.walletcore.dev/api/v1/admin/virtual-accounts?
number=9900123456' \
-H 'Authorization: Bearer {admin_token}'