Virtual Accounts are currently available for Nigeria (NGN) only.
Key Requirements
Retrieve your API keys from your dashboard by following the steps on our
Authentication page. Use your public API key for
all virtual account requests.
POST requests. See our Webhooks guide for setup instructions.
Dynamic vs Reserved — which type do you need?
Virtual accounts come in two types. Choose based on your use case before integrating.Supported Virtual Account Providers
Three banks are currently available as virtual account providers. Not all features are supported by all providers.Amount validation (
has_amount_validation) is only honoured by 78 Finance
and Globus Bank respectively. Passing these fields with Fidelity Bank will
have no effect.How Virtual Account Collections Work.
Dynamic Virtual Account flow
Dynamic Virtual Account flow
- Your server calls Create Virtual Account with
account_type: "Dynamic", the customer details, amount, and expiry time. - The API returns an
account_numberandbank_name. Display these to your customer along with the exact amount to pay. - The customer makes a bank transfer to the virtual account from their own bank app or USSD.
- Payaza receives the transfer and fires a webhook to your configured URL.
- Your server calls Transaction Status Query (using
account_reference) to confirm the payment, or relies on the webhook.
Reserved Virtual Account flow
Reserved Virtual Account flow
- Validate the customer’s BVN (required for compliance before creating a reserved account).
- Your server calls Create Virtual Account with
account_type: “Reserved”, BVN, and customer details. - The API returns a permanent
account_numberandbank_name. Store these against the customer record — this account does not change. - Display the account number to the customer anywhere they need to top up or make a payment.
- When a payment arrives, Payaza fires a webhook. Use the Get Virtual Account Status (by account number) to check the account’s current state.
Step 1
Create a Virtual Account
A single endpoint handles both Dynamic and Reserved account creation. Theaccount_type field controls which type is created.
Dynamic Virtual Account
Reserved Virtual Account
The customer’s BVN must be validated before creating a Reserved virtual
account. This is a compliance requirement.
Step 2 — Testing: Fund a Test Virtual Account
Use this endpoint to simulate a customer payment during development and test your webhook and status-check logic before going live. For Dynamic accounts, pass theaccount_reference used at creation as initiation_transaction_reference.
For Reserved accounts, leave initiation_transaction_reference as an empty string "".
A successful fund call will trigger a webhook notification to your configured
webhook URL, exactly as a real payment would in production.
Step 3a — Transaction Status Query (Dynamic VAs only)
Use this endpoint to check the payment status of a Dynamic virtual account transaction. Query by theaccount_reference value used when creating the virtual account.
There are only two possible
transaction_status values: "Initialized"
(awaiting payment) and "Completed" (payment received). There is no
“Failed” status — an unpaid Dynamic account simply expires.Step 3b — Get Virtual Account Status (Reserved VAs only)
Use this endpoint to retrieve the current status and summary of a Reserved virtual account by its account number.This endpoint returns the account’s status and lifetime transaction count —
not individual transaction details. For per-payment details on a Reserved
account, rely on webhook events.
Webhooks
Payaza fires webhook events for all successful virtual account payments. Webhooks are the recommended way to be notified of incoming payments in real time.
Sample
Payment Successful payload
Always verify the webhook signature before processing the payload. See the
Webhooks guide for verification steps.
Developer notes
- Always generate a unique
account_referenceper virtual account creation to avoid conflicts when querying transaction status. - For Dynamic accounts, show the customer a countdown timer so they know when the account expires. Minimum expiry is 15 minutes; maximum is 480 minutes.(78 Finance Company Limited/ Bank 78)
- For Reserved accounts, store the
account_numberandbank_namepermanently in your database against the customer record — you should never need to re-create a Reserved account for the same customer. - The
account_namedisplayed to the customer will always be prefixed with"Payaza("by the bank (e.g."Payaza(Acme Checkout)"). This is expected behaviour. - Webhooks are the recommended primary mechanism for payment confirmation. Use Transaction Status Query as a fallback only when a webhook is not received within your expected timeout window.
- Transactions have only two terminal states:
Completed(paid) andInitialized. There is no “Failed” state. - The Fund Test Virtual Account endpoint must only be called with test API Key. It will not work in the live environment and is not a real payment.