Open an NGN account
Open a naira account with a 10-digit Nigerian account number for a Nigerian customer, using their BVN.
Open a naira account with a 10-digit Nigerian account number for a Nigerian customer. Gravv checks the customer's BVN before it opens the account.
API version: v2.
Who it is for. A Lagos savings or payroll app that gives each customer a Nigerian bank account number to receive naira.
Status. Available for customers in Nigeria. The v2 API opens NGN accounts as fiat-only.
Money example
Chidi's employer pays his salary of 450,000.00 NGN.
- The employer sends 450,000.00 NGN by bank transfer to Chidi's 10-digit account number.
- The bank credits the deposit. Gravv books 450,000.00 NGN and sends
transfer.inflow.completed. - Chidi's balance shows 450,000.00 NGN. NGN deposits carry no deposit fee.
Before you start
- The customer's
basicKYC iscompleted, and the customer's address is in Nigeria. - You have the customer's BVN (Bank Verification Number, 11 digits). Gravv checks it against the national registry, and the names you send must match it.
- Capabilities with
currency=NGN&country=NGshow the NGN option, withtoken_wallets: [].
Find out what is required
Read requirements with customer_type=individual¤cy=NGN&category=sub_account&country=NG. A person and a business use the same short form:
| Field | Required | Notes |
|---|---|---|
first_name, middle_name, last_name |
Yes | Exactly as on the BVN record |
phone |
Yes | |
bank_verification_number |
Yes | Write-only. The API accepts the old name bvn. Never send both |
phone_daytime |
No |
The form has no documents and no parties.
Steps
1. Open the account
Always send category. If you leave it out on a first NGN account, Gravv stores the account with the NGN default, multi_currency, which this option does not list. On a second NGN account, the API refuses a request without category or account_type.
curl --request POST \
--url https://api.gravv.xyz/v2/accounts \
--header 'Api-Key: <API_KEY>' \
--header 'Idempotency-Key: 27146fe8-0cd4-400e-8fc0-b27a5e6e509d' \
--header 'Content-Type: application/json' \
--data '
{
"customer_id": "5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42",
"customer_type": "individual",
"currency": "NGN",
"account_type": "operating",
"category": "sub_account",
"bank_code": "<bank_code>",
"label": "Chidi NGN",
"data": {
"root": {
"first_name": "Chidi",
"middle_name": "Emeka",
"last_name": "Okafor",
"phone": "+2348031234567",
"bank_verification_number": "22123456789"
}
}
}
'
const response = await fetch("https://api.gravv.xyz/v2/accounts", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Idempotency-Key": "27146fe8-0cd4-400e-8fc0-b27a5e6e509d",
"Content-Type": "application/json",
},
body: JSON.stringify({
"customer_id": "5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42",
"customer_type": "individual",
"currency": "NGN",
"account_type": "operating",
"category": "sub_account",
"bank_code": "<bank_code>",
"label": "Chidi NGN",
"data": {
"root": {
"first_name": "Chidi",
"middle_name": "Emeka",
"last_name": "Okafor",
"phone": "+2348031234567",
"bank_verification_number": "22123456789"
}
}
}),
});
console.log(response.status, await response.json());
import os
import requests
response = requests.post(
"https://api.gravv.xyz/v2/accounts",
headers={
"Api-Key": os.environ["GRAVV_API_KEY"],
"Idempotency-Key": "27146fe8-0cd4-400e-8fc0-b27a5e6e509d",
"Content-Type": "application/json",
},
json={
"customer_id": "5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42",
"customer_type": "individual",
"currency": "NGN",
"account_type": "operating",
"category": "sub_account",
"bank_code": "<bank_code>",
"label": "Chidi NGN",
"data": {
"root": {
"first_name": "Chidi",
"middle_name": "Emeka",
"last_name": "Okafor",
"phone": "+2348031234567",
"bank_verification_number": "22123456789",
},
},
},
)
print(response.status_code, response.json())
The API returns {"account_id": "…", "status": "pending"}.
2. Read the account number
Read GET /v2/accounts/{id} until the status is active. Show virtual_account_bank_account_number (10 digits), virtual_account_bank_name and the beneficiary name. NGN accounts have no routing number.
What can go wrong
| Response | Why | Fix |
|---|---|---|
400 details.bank_verification_number: required: is required |
You sent no BVN | Ask the customer for it |
400 details.bank_verification_number: alias_conflict: submitted more than once (as "bvn" and "bank_verification_number") — … |
You sent both names | Send only bank_verification_number |
400 details.middle_name: required: is required |
You sent no middle name | Ask the customer. This bank requires it |
400 the bank verification number does not exist (BVN_NOT_FOUND) |
The BVN is not in the registry | Check the 11 digits with the customer |
400 the bank verification number is invalid (BVN_INVALID) |
The BVN is malformed | Check it with the customer |
400 data.root.first_name does not match the bank verification number record (BVN_IDENTITY_MISMATCH, also returned for the last name, middle name and date of birth) |
A name differs from the record. The check ignores case | Spell the names exactly as on the record |
400 the phone number, date of birth, or name does not match the bank verification number record (BVN_NAME_MISMATCH) |
The registry refused the match | Check every identity field |
5xx there was a problem identifying this BVN; please try again later |
The registry lookup failed. Gravv refuses the request rather than skip the check | Retry later |
400 network is only accepted for account options that support wallet integration |
You sent network |
Remove it |
400 bank_code=<code> does not open accounts for customers resident in GH. … |
The customer is not in Nigeria | Open NGN accounts only for customers in Nigeria |
Webhooks you will receive
Gravv sends applications.accounts.pending, then applications.accounts.completed. For each deposit, Gravv sends transfer.inflow.completed.
Testing in sandbox
Sandbox simulates NGN accounts. The account becomes active at once with a generated 10-digit number. Sandbox skips the BVN registry check, so any 11 digits work. Simulate a deposit with "currency": "NGN", an amount such as "50000.00", and no rail.