Virtual accounts
A virtual account is a bank account that you make for one of your customers. Money that comes into that account becomes USD at the current rate. We then add the USD to your balance.
Thus you can give each customer one permanent account number. The customer does not start a new collection for each payment.
Which one to use. A collection is one request for one amount. A virtual account is permanent, and the same account number accepts many payments.
Use a virtual account when a customer pays you again and again. Examples are subscriptions, wallet top-ups, and marketplace sellers. Use a collection for a single payment.
Availability. NGN (Nigeria) and GHS (Ghana). More corridors follow — the shape below stays the same.
Create a virtual account
POST /v1/virtual-accounts
A virtual account belongs to a person. You give that customer's KYC data one time. The currency controls which KYC fields you must give. See the table below.
curl -X POST {BASE_URL}/v1/virtual-accounts \
-H "x-api-key: sk_test_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cus_123",
"first_name": "Ada",
"last_name": "Obi",
"bvn": "22212345678",
"date_of_birth": "1996-04-12",
"email": "ada@example.com",
"phone": "+2348012345678"
}'
| Field | Required | Description |
|---|---|---|
first_name |
yes | The account holder's first name. |
last_name |
yes | The account holder's last name. |
email |
yes | The customer's email. |
phone |
yes | The customer's phone, E.164 (e.g. +2348012345678). |
bvn |
NGN only | The customer's Bank Verification Number. Naira accounts are verified against it; not used for GHS. |
date_of_birth |
NGN only | YYYY-MM-DD. Not used for GHS. |
customer_id |
recommended | Link to an existing customer so payments tie back to them. |
currency |
no | NGN (default) or GHS. |
A Ghana account needs no BVN or date of birth:
curl -X POST {BASE_URL}/v1/virtual-accounts \
-H "x-api-key: sk_test_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cus_456",
"currency": "GHS",
"first_name": "Kwame",
"last_name": "Mensah",
"email": "kwame@example.com",
"phone": "+233201234567"
}'
Response
{
"code": 201,
"message": "Virtual account created",
"data": {
"id": "va_…",
"customer_id": "cus_123",
"account_name": "Ada Obi",
"account_number": "9900112233",
"bank_name": "Providus Bank",
"currency": "NGN",
"status": "active",
"created_at": "2026-06-25T08:44:25.000Z"
}
}
Give account_number, account_name, and bank_name to your customer. Each
transfer into the account adds USD to your balance. It also makes a deposit
transaction. Use customer_id to reconcile. For an
immediate message, subscribe to webhooks.
List virtual accounts
GET /v1/virtual-accounts
This endpoint gives every virtual account that you made. The newest is first.
{
"code": 200,
"message": "Virtual accounts fetched",
"data": [
{
"id": "va_…",
"customer_id": "cus_123",
"account_name": "Ada Obi",
"account_number": "9900112233",
"bank_name": "Providus Bank",
"currency": "NGN",
"status": "active",
"created_at": "2026-06-25T08:44:25.000Z"
}
]
}
Lifecycle
A virtual account becomes active immediately, and you can use it again and
again.
Each payment into the account is a separate transaction. It moves through three
stages: payment received, credit to your balance, and settled. To follow
it, use the transaction timeline or webhooks. This is the same as a
collection.