What is the Payments Product?
The payments product lets you send money from your virtual accounts to any bank account in Nigeria — programmatically, from your application. No branch visits, no manual transfers. You can send money instantly (via NIP) or schedule a standard electronic transfer (via NEFT). Both routes reach any Nigerian bank: GTBank, Access, Zenith, First Bank, Kuda, Opay, and hundreds more.NIP vs NEFT — Which Should You Use?
NIP — Instant Payment
Nigeria’s instant payment network. Like sending a WhatsApp message — arrives in seconds, 24 hours a day, 7 days a week, including public holidays.Use NIP when: Speed matters to your customer. Salary payments, bill payments, P2P transfers — anything where a delay would be noticeable or harmful.Limit: Up to ₦10,000,000 per single transaction.
NEFT — Electronic Funds Transfer
Standard electronic transfer. Processed in batches during banking hours. Can take a few hours on business days.Use NEFT when: You are moving large amounts and do not need instant delivery. Good for treasury operations, payroll runs scheduled in advance, or vendor settlements.Limit: No hard per-transaction cap (subject to your partner agreement).
When in doubt, use NIP. It is the default for most BaaS use cases and your customers will have a better experience.
The 3-Step Payment Flow
Every payment you initiate must follow these three steps in order. Skipping step 1 is the most common cause of failed or misdirected payments.Account Enquiry — Verify the destination first
Before sending any money, confirm that the destination account exists and fetch the account holder’s name. Show this name to your user so they can confirm they are sending to the right person.This protects your users from typos and protects you from fraud claims.Response:
- cURL
- JavaScript (fetch)
Initiate Transfer — Send the payment
Once your user confirms the recipient, send the transfer request. You will receive a Response:
transactionRef immediately — this is your tracking ID. You will NOT get the final result at this point. Payments are processed asynchronously (in the background), which is why there is a step 3.- cURL
- JavaScript (fetch)
Store the
transactionRef in your database immediately. You will need it in step 3 to fetch the final result, and for any future dispute resolution.Poll for Status — Check the result
Poll the status endpoint using the Response:
transactionRef from step 2. Most NIP payments complete within 30 seconds. Poll every 5–10 seconds, up to a maximum of 12 attempts (2 minutes total), before marking the transaction as “pending review.”- cURL
- JavaScript (fetch)
Request Security
HMAC Signature
For payment requests, you must include anX-Signature header. This signature proves two things:
- The request genuinely came from your server (not an impersonator)
- The request body has not been modified in transit (no tampering)
Mutual TLS (mTLS) — Production Only
In production, payment requests must also use mutual TLS (mTLS). Standard HTTPS proves the server is who it claims to be (you trust the server). Mutual TLS goes one step further — the server also proves your server is who it claims to be. Think of it like a company ID badge for your server: just as a security guard checks your badge at the door, our servers check your server’s certificate before accepting any payment instruction. You receive your client certificate during the production onboarding process. Pass it in your HTTPS requests using the--cert flag (cURL) or the equivalent in your language’s HTTP client.
mTLS is not required in the sandbox environment. Build and test without it, then configure it as part of your go-live checklist.
Fee Modes
Every payment has a transaction fee plus VAT on that fee. You control how those charges are structured using thefeeMode field.
Using a real example: you want to send ₦50,000. The fee is ₦50 and VAT on the fee is ₦2.50.
feeMode | What happens | Amount debited from source account |
|---|---|---|
LUMP_ALL | Principal + fee + VAT in one debit | ₦50,052.50 (single debit) |
LUMP_FEE_VAT (default) | Principal in one debit, then fee + VAT together | ₦50,000 then ₦52.50 |
SPLIT_FEE_VAT | Principal, fee, and VAT as three separate debits | ₦50,000 then ₦50 then ₦2.50 |
Idempotency
Idempotency means: if you send the same request twice, you only get one result — not two payments. Why this matters: Imagine your server sends a transfer request, the payment is processed, but your internet drops before you receive the response. You don’t know if the payment went through. Without idempotency, retrying would create a duplicate payment. With idempotency, retrying is safe — we detect the duplicate and return the original result. How to use it: Generate a UUID and send it as theX-Idempotency-Key header. Store this key alongside your transaction in your database. If you need to retry, send the same key. If it is a genuinely new payment, generate a new key.
Transaction Status Reference
| Status | Meaning | What to do |
|---|---|---|
PENDING | The payment has been received and is queued for processing | Keep polling |
PROCESSING | The payment has been sent to the destination bank and is awaiting confirmation | Keep polling |
SUCCESSFUL | The destination bank confirmed receipt | Update your records, notify your user |
FAILED | The payment was rejected — see failureReason in the response | Notify your user, check failureReason, do not retry without fixing the root cause |
REVERSED | A previously successful payment was reversed (returned to sender) | Notify your user, update balance, investigate via support |
PENDING and PROCESSING are both in-progress states. Only SUCCESSFUL, FAILED, and REVERSED are terminal states — once a transaction reaches one of these, its status will not change again.