Skip to main content
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.
Set the following headers on every request:
Make sure your webhook URL is saved on the dashboard and configured to accept 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.
Always ensure you are using the correct account type for your use case. Using a Dynamic account where a Reserved account is needed (or vice versa) will cause integration issues that are difficult to debug.

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.

  1. Your server calls Create Virtual Account with account_type: "Dynamic", the customer details, amount, and expiry time.
  2. The API returns an account_number and bank_name. Display these to your customer along with the exact amount to pay.
  3. The customer makes a bank transfer to the virtual account from their own bank app or USSD.
  4. Payaza receives the transfer and fires a webhook to your configured URL.
  5. Your server calls Transaction Status Query (using account_reference) to confirm the payment, or relies on the webhook.
Dynamic accounts expire. If the customer does not pay before the account expires, you must create a new virtual account and show the updated details. Never reuse an expired account_reference.
  1. Validate the customer’s BVN (required for compliance before creating a reserved account).
  2. Your server calls Create Virtual Account with account_type: “Reserved”, BVN, and customer details.
  3. The API returns a permanent account_number and bank_name. Store these against the customer record — this account does not change.
  4. Display the account number to the customer anywhere they need to top up or make a payment.
  5. 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. The account_type field controls which type is created.

Dynamic Virtual Account

Sample response
Always show the customer the exact transaction_amount_payable from the response. If has_amount_validation is true, payments of a different amount will be rejected by the bank.

Reserved Virtual Account

The customer’s BVN must be validated before creating a Reserved virtual account. This is a compliance requirement.
Sample response
API reference: Create Reserved/Dynamic Virtual Account

Step 2 — Testing: Fund a Test Virtual Account

This endpoint is available in the test environment only. Do not call it in production. In the live environment, customers fund virtual accounts by making real bank transfers.
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 the account_reference used at creation as initiation_transaction_reference. For Reserved accounts, leave initiation_transaction_reference as an empty string "".
Sample response
A successful fund call will trigger a webhook notification to your configured webhook URL, exactly as a real payment would in production.
API reference: Fund Test Virtual Account

Step 3a — Transaction Status Query (Dynamic VAs only)

Use this endpoint to check the payment status of a Dynamic virtual account transaction. Query by the account_reference value used when creating the virtual account.
Sample response Before Payment
Sample response After Payment
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.
API reference: Transaction Status Query

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.
Sample response
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.
API reference: Get Virtual Account Status

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_reference per 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_number and bank_name permanently in your database against the customer record — you should never need to re-create a Reserved account for the same customer.
  • The account_name displayed 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) and Initialized . 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.