Virtual accounts
Create account
Issues a virtual account and returns the details your customer pays into. Choose a static account that stays with the customer, a dynamic account that expires after one hour, or a checkout account that gives you a hosted payment link instead of raw account details.
POST
/v2/create_account
Account types
| Type | Behaviour |
|---|---|
static |
A permanent account. Each customer (email) gets one per bank. Calling again for the same customer and bank returns the existing account. Requires bvn. |
dynamic |
A short-lived account for a single payment, valid for 1 hour. Requires amount and amounttype. While a customer still has a live dynamic account with a bank, calling again returns that account instead of creating a new one. Returns the account details directly. |
checkout |
A short-lived account for a single payment, provisioned the same way as dynamic (same 1-hour expiry, same amount / amounttype requirements). Instead of account details, the response gives you a hosted checkout_url — send your customer there and Volboo shows them the bank details, counts down to expiry, and lets them share the link with whoever is making the payment. |
Headers
| Header | Value |
|---|---|
| Content-Type | application/json |
| api-key | Your business API key |
| secret-key | Your business secret key |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
| type | string | Yes | static, dynamic or checkout. |
| string | Yes | The customer this account belongs to. Must be a valid email address. | |
| ref | string | Yes | Your own reference, 3 to 100 characters: letters, numbers, hyphens, underscores and dots. Each ref can only be used once per business. Returned as client_reference everywhere the account appears. |
| fname | string | Yes | First name, 2 to 60 characters. Letters, spaces, hyphens and apostrophes only. |
| lname | string | Yes | Last name, same rules as fname. |
| phone | number | Yes | Customer phone number, 10 to 15 digits. |
| banks | array | Yes | Which partner banks to issue with. Currently ["9PSB"]. |
| bvn | number | Static only | Customer's 11-digit BVN. Required when type is static; ignored for dynamic and checkout accounts. |
| amount | number | Dynamic & checkout | Amount in NGN. Must be greater than 0. |
| amounttype | string | Dynamic & checkout | EXACT accepts only the exact amount. ANY accepts any amount paid into the account. |
Request
Static account
curl -X POST /v2/create_account \ -H "Content-Type: application/json" \ -H "api-key: <your api key>" \ -H "secret-key: <your secret key>" \ -d '{ "type": "static", "email": "customer@example.com", "ref": "order_10432", "fname": "Amanda", "lname": "Elumelu", "phone": 8060082079, "bvn": 22222222222, "banks": ["9PSB"] }'
Dynamic account
curl -X POST /v2/create_account \ -H "Content-Type: application/json" \ -H "api-key: <your api key>" \ -H "secret-key: <your secret key>" \ -d '{ "type": "dynamic", "email": "customer@example.com", "ref": "order_10433", "fname": "Amanda", "lname": "Elumelu", "phone": 8060082079, "amount": 5000, "amounttype": "EXACT", "banks": ["9PSB"] }'
Checkout account
curl -X POST /v2/create_account \ -H "Content-Type: application/json" \ -H "api-key: <your api key>" \ -H "secret-key: <your secret key>" \ -d '{ "type": "checkout", "email": "customer@example.com", "ref": "order_10434", "fname": "Amanda", "lname": "Elumelu", "phone": 8060082079, "amount": 5000, "amounttype": "EXACT", "banks": ["9PSB"] }'
Response
| Field | Type | Notes |
|---|---|---|
| status | string | success when at least one account was issued or already existed. error when every requested bank failed. |
| results | array | One entry per requested bank. |
| results[].vol_reference | string | Volboo's identifier for the account. Not present when status is failed. |
| results[].account_name | string | Name the account is held in. Not present for checkout accounts — use the hosted page instead. |
| results[].account_number | string | The number your customer pays into. Not present for checkout accounts — use the hosted page instead. |
| results[].checkout_url | string | checkout accounts only. Link to the hosted payment page — send your customer here to see the bank details and pay. |
| results[].bank_name | string | Partner bank holding the account. |
| results[].account_type | string | static, dynamic or checkout. |
| results[].expires_at | string | Dynamic and checkout accounts only. When the account stops accepting payments, formatted YYYY-MM-DD HH:MM:SS. |
| results[].status | string | created, existing or failed. |
| results[].message | string | Only when status is failed. Says why that bank could not issue an account. |
| request_ref | string | Your ref, echoed back. |
200 Success (static)
{
"status": "success",
"results": [
{
"vol_reference": "VOL-695E0C5DA6A9A-9PS",
"account_name": "VOLBOO/AMANDA ELUMELU",
"account_number": "9060132960",
"bank_name": "9PSB",
"account_type": "static",
"status": "created" //created or existing
}
],
"request_ref": "order_10432"
}
200 Success (dynamic)
{
"status": "success",
"results": [
{
"vol_reference": "VOL-DY-695E0C5DA6A9A-9PS",
"account_name": "VOLBOO/AMANDA ELUMELU",
"account_number": "9060132961",
"bank_name": "9PSB",
"account_type": "dynamic",
"expires_at": "2026-09-28 15:02:00",
"status": "created" //created or existing
}
],
"request_ref": "order_10433"
}
200 Success (checkout)
{
"status": "success",
"results": [
{
"vol_reference": "VOL-CK-695E0C5DA6A9A-9PS",
"bank_name": "9PSB",
"account_type": "checkout",
"status": "created", //created or existing
"expires_at": "2026-09-28 15:02:00",
"checkout_url": "https://volboo.com/checkout/checkout?acct_vol_reference=VOL-CK-695E0C5DA6A9A-9PS"
}
],
"request_ref": "order_10434"
}
200 Bank failure
{
"status": "error",
"results": [
{
"bank_name": "9PSB",
"account_type": "static",
"status": "failed",
"message": "9PSB API Failure"
}
],
"request_ref": "order_10432"
}
Store
vol_reference against your own customer record. It is
what ties a later payment or webhook event back to the account you issued.
For dynamic and checkout accounts, also keep expires_at so
you know when to stop showing the account — or the checkout link — to
your customer.
Checkout accounts are provisioned at the bank exactly like dynamic
accounts — same expiry, same amount rules — the only difference is what
you get back. Use
checkout when you want to hand your
customer a single link rather than displaying bank details yourself; use
dynamic when you want the account details to build your own
payment UI.
Errors
A rejected call answers with status: "error" and the reason in
message. The HTTP code is still 200, so check
status in the body. See Errors for
the shape.
| Message | Cause |
|---|---|
type must be 'static', 'dynamic' or 'checkout' | type is missing or not one of the three values. |
<field> is required | A required field for that account type is missing, including bvn for static and amount / amounttype for dynamic and checkout. |
BVN must be exactly 11 digits | bvn is not 11 digits. |
amounttype must be either 'ANY' or 'EXACT' | Invalid amounttype on a dynamic or checkout request. |
amount must be greater than zero | amount is zero or negative. |
'<bank>' is not a supported bank | An entry in banks is not supported. The message lists the supported banks. |
Invalid API keys | api-key or secret-key is wrong. |
The reference '<ref>' has already been used for this business. | You have already used this ref. Send a new one for each request. |
Volboo