Skip to main content

What is a Virtual Account?

A virtual account is a real Nigerian bank account number — it can receive transfers from any bank in Nigeria — but it lives inside your master Union Bank account. Think of it like suites in a hotel: each suite has its own room number (the account number your customer sees), but they all share the same hotel address (your master Union Bank account). When a guest pays the hotel, the front desk knows exactly which suite the payment is for. That front desk is your webhook. When money arrives in any virtual account, we notify your server immediately with the full details of who paid and how much.
Virtual accounts are denominated in Nigerian Naira (NGN) only. They carry Union Bank’s sort code: 032.

Two Types of Virtual Accounts

Static Account

Permanent. The account number never expires and is always assigned to the same customer or purpose.Best for: Wallet top-ups, recurring billing, dedicated customer accounts. When your customer wants to fund their wallet, they always transfer to the same number — no need to generate a new one each time.

Dynamic Account

Temporary. The account number expires after a time you set (e.g. 2 hours, 24 hours).Best for: One-time payment links, invoice payments, event ticket orders. Generate the account, share it with your customer, and it disappears once expired — clean and secure.

Create a Virtual Account

Before you start, you need:
  • Your partnerId — visible in the sandbox dashboard
  • An API key — see the API Keys guide
  • An idempotency key — a random unique string you generate for each request (see note below)
What is an idempotency key? It is a unique ID you attach to every create request. If your network drops after you send the request but before you receive a response, you can safely resend the same request with the same idempotency key. We will return the original result instead of creating a duplicate account. Use a UUID — most languages and operating systems have a built-in generator.
curl -X POST https://sandbox.api.unionbank.ng/api/v1/accounts \
  -H "Authorization: ApiKey ubn_sb_your_key_here" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: $(uuidgen)" \
  -d '{
    "partnerId": "your-partner-id",
    "accountType": "STATIC"
  }'
Successful response:
{
  "status": "success",
  "data": {
    "accountNumber": "9023456789",
    "accountName": "UBN / YOUR BUSINESS NAME",
    "bankCode": "032",
    "bankName": "Union Bank of Nigeria",
    "accountType": "STATIC",
    "currency": "NGN",
    "partnerId": "your-partner-id",
    "createdAt": "2026-03-25T10:00:00+01:00"
  }
}

Create a Dynamic (Expiring) Account

To create a temporary account, set accountType to DYNAMIC and pass an expiresAt timestamp in ISO 8601 format:
curl -X POST https://sandbox.api.unionbank.ng/api/v1/accounts \
  -H "Authorization: ApiKey ubn_sb_your_key_here" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: $(uuidgen)" \
  -d '{
    "partnerId": "your-partner-id",
    "accountType": "DYNAMIC",
    "expiresAt": "2026-03-25T12:00:00+01:00",
    "reference": "ORDER-00123"
  }'
Pass your own reference (e.g. an order ID) when creating a dynamic account. It is returned in the webhook payload when money arrives, so you can match the payment to the right order without any extra lookup.

Check Account Balance

curl -X GET https://sandbox.api.unionbank.ng/api/v1/accounts/9023456789/balance \
  -H "Authorization: ApiKey ubn_sb_your_key_here"
Response:
{
  "status": "success",
  "data": {
    "accountNumber": "9023456789",
    "availableBalance": 150000.00,
    "ledgerBalance": 150000.00,
    "currency": "NGN"
  }
}
availableBalance is what your customer can actually spend. ledgerBalance may include funds that are still processing (e.g. a credit still pending confirmation).

Get Account Statement

Pull a list of transactions for a virtual account within a date range. Dates follow the YYYY-MM-DD format.
curl -X GET "https://sandbox.api.unionbank.ng/api/v1/accounts/9023456789/statement?from=2026-03-01&to=2026-03-25&page=1&limit=20" \
  -H "Authorization: ApiKey ubn_sb_your_key_here"
Response:
{
  "status": "success",
  "data": {
    "accountNumber": "9023456789",
    "from": "2026-03-01",
    "to": "2026-03-25",
    "transactions": [
      {
        "transactionRef": "COL-20260325-001",
        "type": "CREDIT",
        "amount": 50000.00,
        "currency": "NGN",
        "narration": "Transfer from ADEBAYO JOHNSON",
        "balanceAfter": 150000.00,
        "timestamp": "2026-03-25T10:00:00+01:00"
      }
    ],
    "pagination": {
      "page": 1,
      "limit": 20,
      "total": 1
    }
  }
}

Receiving Money

When anyone does a bank transfer to a virtual account number — from any Nigerian bank, including mobile apps like GTBank, Access, or First Bank — the money lands in your master Union Bank account. You do not need to do anything to “pull” it in. To be notified the moment a payment arrives, configure a webhook. We will send an HTTP POST to your server with full details of the transaction, including the sender’s name and account number. See the Webhooks guide to set this up.
Do not rely on polling the balance to detect incoming payments. Webhooks are faster, more reliable, and do not count against your rate limit quota. Use webhooks for anything customer-facing.

Limits and Constraints

ConstraintValue
CurrencyNGN only
Maximum static accounts per partner10,000 (contact support to increase)
Maximum dynamic accounts active at once5,000
Minimum dynamic account expiry5 minutes from creation
Maximum dynamic account expiry72 hours from creation
Account number format10-digit NUBAN
If you need higher limits for your use case (e.g. you are building a large-scale savings or lending product), contact baas-support@unionbank.ng with your expected monthly volume.

Frequently Asked Questions

Yes. All virtual accounts issued through this platform carry Union Bank’s sort code: 032. When your customer’s bank displays the destination bank during a transfer, they will see “Union Bank of Nigeria.”
Yes. Your customers will see Union Bank of Nigeria as the receiving bank in their banking app or USSD confirmation screen. The account name will appear as set during account creation (typically your business name or a customer-specific label).
Any transfer sent to an expired dynamic account number is rejected at the network level and returned to the sender’s bank. No money reaches your master account. This usually takes 1–3 business days to reverse to the sender, depending on the sending bank.
No. Each virtual account should be assigned to exactly one customer or one purpose. If two customers share an account number, you cannot tell who made a given payment. The whole point of virtual accounts is pre-sorted, attributable payments.
Yes. Send a DELETE request to /api/v1/accounts/{accountNumber}. Static accounts can be deactivated at any time. Once deactivated, any inbound transfers are rejected and returned to the sender.