Create Virtual Account - Afriex Business API
Afriex SDK
TypeScript
const account = await afriex.paymentMethods.createVirtualAccount({
currency: "USD",
label: "SALES",
customerId: "optional-customer-id",
});
curl --request POST \
--url https://sandbox.api.afriex.com/api/v1/payment-method/virtual-account \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"currency": "NGN",
"customerId": "68e6717848e1f632e9686460",
"label": "SALES"
}
'
import requests
url = "https://sandbox.api.afriex.com/api/v1/payment-method/virtual-account"
payload = {
"currency": "NGN",
"customerId": "68e6717848e1f632e9686460",
"label": "SALES"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({currency: 'NGN', customerId: '68e6717848e1f632e9686460', label: 'SALES'})
};
fetch('https://sandbox.api.afriex.com/api/v1/payment-method/virtual-account', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sandbox.api.afriex.com/api/v1/payment-method/virtual-account",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'currency' => 'NGN',
'customerId' => '68e6717848e1f632e9686460',
'label' => 'SALES'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
?>
package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sandbox.api.afriex.com/api/v1/payment-method/virtual-account"
payload := strings.NewReader(`{
"currency": "NGN",
"customerId": "68e6717848e1f632e9686460",
"label": "SALES"
}`)
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}
HttpResponse<String> response = Unirest.post("https://sandbox.api.afriex.com/api/v1/payment-method/virtual-account")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"currency\": \"NGN\",\n \"customerId\": \"68e6717848e1f632e9686460\",\n \"label\": \"SALES\"\n}")
.asString();
require 'uri'
require 'net/http'
url = URI("https://sandbox.api.afriex.com/api/v1/payment-method/virtual-account")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"currency\": \"NGN\",\n \"customerId\": \"68e6717848e1f632e9686460\",\n \"label\": \"SALES\"\n}"
response = http.request(request)
puts response.read_body
Response Example
{
"data": {
"paymentMethodId": "690cc5bbe2a1143ff6070119",
"channel": "VIRTUAL_BANK_ACCOUNT",
"customerId": "68e6717848e1f632e9686460",
"institution": {
"institutionName": "FIDELITY BANK"
},
"accountName": "Lily New",
"accountNumber": "3820404958",
"countryCode": "NG"
}
}
Creates a new virtual account for the resolved customer-or-owner and currency. Pass customerId to mint the virtual account for a specific end-user, or omit it to mint one for the business owner. Important: Virtual accounts are only active in production and do not work on staging/dev.
Static vs dynamic virtual accounts
You choose between two flavours of virtual account by what you pass alongside currency and customerId.
Static (label)
Pass a label to group static virtual accounts by purpose. Static accounts are permanently assigned to the customer and never expire. The same account number remains valid for repeated funding. Allowed labels: SALES, OPERATIONS, PAYROLL, COLLECTIONS, VENDOR_PAYMENTS, TAX, REFUNDS, MARKETING, TREASURY, GENERAL. Use static accounts when you want stable, long-lived account numbers a customer can top up over time, organised by purpose.
Dynamic (amount)
Pass an amount to mint a dynamic (ephemeral) virtual account tied to that specific amount. Dynamic accounts expire after a short window. Use dynamic accounts when you need to collect a specific, known amount within a defined window, like a one-time payment for a particular order.
label and amount are mutually exclusive. Supplying both is rejected at validation.
BVN requirement for NGN static virtual accounts
For NGN static virtual accounts (label-based, Nigeria), the customer must have a Bank Verification Number (BVN) on file. This is a regulatory requirement for permanently assigned accounts in Nigeria. If the BVN is missing, the API returns an error. You can supply a BVN when creating a new customer or add it to an existing customer at any time using the Update Customer KYC endpoint.
NGN static virtual accounts will fail if the customer has not provided their BVN. This requirement does not apply to dynamic virtual accounts or to virtual accounts in other currencies.
Limits
Creation is subject to a per-(business, customer, currency) cap. Requests that would exceed the cap return VIRTUAL_ACCOUNT_LIMIT_REACHED with 400. Call List Virtual Accounts first to check what already exists for the customer.