Skip to Content
👋 Welcome to 100Pay Developers
DocsCustomersVirtual Bank Accounts

Create a Virtual Bank Account

Issue a dedicated NGN account number for a customer. Three steps: create the customer, verify their BVN, then create the account.

BVN verification must complete with an eligible result (exact name match) before account creation. The raw BVN is encrypted at the KYC boundary and never echoed, logged, or returned.

Full Workflow

Create the Customer

import { Pay100 } from "@100pay-hq/100pay.js"; const client = new Pay100({ publicKey: "your_public_key", secretKey: "your_secret_key", }); const customer = await client.customer.create( { externalReference: "user-8f2c1a", // your stable user ID, unique per app firstName: "Ada", lastName: "Obi", email: "ada@example.com", phone: "+2348012345678", // +234 phone required for VBAs }, { idempotencyKey: crypto.randomUUID() } );

Verify Their Identity (BVN)

const verification = await client.customer.identityVerification.create( customer.data.id, { method: "bvn", bvn: "12345678901" }, { idempotencyKey: crypto.randomUUID() } ); // Processing is asynchronous — poll until terminal const result = await client.customer.identityVerification.get( customer.data.id, verification.data.id ); // result.data.status → "verified", result.data.eligibility.status → "eligible"

Create the Virtual Bank Account

const vba = await client.customer.virtualBankAccount.create( customer.data.id, { identityVerificationId: verification.data.id, externalReference: "vba-user-8f2c1a", // Optional overrides (defaults come from your app settings): // sweepDestination: "platform" | "merchant_settlement" | "merchant_vba" | "none" // depositFeeBearer: "customer" | "merchant" }, { idempotencyKey: crypto.randomUUID() } ); // Provisioning is asynchronous — 202 means poll the account const account = await client.customer.virtualBankAccount.get( customer.data.id, vba.data.id ); console.log(account.data.account?.number); // "5013195013" console.log(account.data.walletId); // the dedicated ledger wallet

Sweep Destination & Fee Bearer

Both are captured immutably when the account is created. Later changes to your app settings only affect new accounts.

SettingOptionsDefault
sweepDestinationplatform · merchant_settlement · merchant_vba · noneplatform
depositFeeBearercustomer · merchantcustomer
  • platform keeps physical custody aligned with the account that pays withdrawals — the recommended default.
  • merchant fee bearer sponsors deposit fees from your main NGN wallet. If your balance can’t cover a fee, the configured fallback applies (charge_customer, deferred receivable, or held deposit).

Manage the app-level defaults with client.customer.bankingSettings.get() / .update(data, { ifMatch }).

One operational VBA per customer per app. Failed provisioning can be retried with client.customer.virtualBankAccount.retry(...) once automatic attempts are exhausted.

Last updated on