Skip to content

BVN Verification

Validate a Bank Verification Number through NIBSS: boolean match without PII, or the full record with subject consent.

View as Markdown

Checks a Bank Verification Number through NIBSS. Use boolean for the common bank flow: you collect the customer's details, send them with the BVN, and get back which ones are correct, without receiving any personal data. Use core only when you need the full BVN record; it requires the customer's consent through the NIBSS Consent Hub.

POST/v1/verify/bvn
Availability
Sandbox and live
Indicative price
₦100.00 per completed check
Consent
boolean: your attestation. core: a consent granted by the data subject (Consent).
MCP tool
verify_bvn (boolean method only)

Methods

Choose a method with the method field. Each one has its own required fields and consent mechanism.

methodDescriptionRequired fields
boolean
Match / no-match against the BVN record. Returns no PII. The cheapest BVN check.
bvn, reason, consent, match
core
Full BVN record. Requires a consent granted by the subject through POST /v1/consents.
bvn, reason, consent_id

Request

Body parameters · method

Match / no-match against the BVN record. Returns no PII. The cheapest BVN check.

  • methodstringrequired

    Always boolean.

  • bvnstringrequired

    Format: 11 digits.

  • reasonstringrequired

    Purpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.

  • consentobjectrequired

    Your attestation that you obtained the data subject's consent for this purpose.

  • consent.obtainedbooleanrequired

    Always true.

  • matchobjectrequired

    Optional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.

  • match.first_namestring

    Must not be empty.

  • match.middle_namestring

    Must not be empty.

  • match.last_namestring

    Must not be empty.

  • match.date_of_birthstring

    Format: date, YYYY-MM-DD.

  • boolean needs at least one field in match. You can send up to six: first_name, middle_name, last_name, date_of_birth, phone and gender. Sending all six gives the strongest check.
  • Each field you send comes back in field_matches as true or false, so you can see exactly what was wrong (often a misspelt middle name). match is true only if all of them agree.
  • core needs a consent_id from POST /v1/consents whose status is granted, for the same BVN, within 24 hours of the grant.

Send an Idempotency-Key header so a retried request is never billed twice. See Idempotency.

curl -X POST http://localhost:4000/v1/verify/bvn \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "method": "boolean",
  "bvn": "22222222221",
  "reason": "financialProducts",
  "consent": {
    "obtained": true
  },
  "match": {
    "first_name": "Clarke",
    "last_name": "Griffin",
    "date_of_birth": "1992-04-18"
  }
}'

Response

A completed check returns 200 with a verification object. status is verified or not_found. If the provider has not answered in time you get 202 with status: "pending"; retrieve it later or wait for the verification.completed webhook.

200 OK · assertion
{
  "reference_id": "spm_8171f3a87cbe221341f7185f",
  "object": "verification",
  "product": "bvn",
  "method": "bvn_boolean",
  "status": "verified",
  "match": true,
  "field_matches": {
    "first_name": true,
    "last_name": true,
    "date_of_birth": true,
    "phone": true
  },
  "field_confidence": null,
  "mode": "sandbox",
  "reason": "financialProducts",
  "subject": "*******2221",
  "summary": {
    "match": true
  },
  "consent": {
    "mechanism": "client_attested",
    "consent_id": null,
    "timestamp": "2026-10-19T09:41:07.512Z"
  },
  "source": "api",
  "error": null,
  "billing": {
    "amount_kobo": 0,
    "currency": "NGN"
  },
  "latency_ms": 268,
  "created_at": "2026-10-19T09:41:07.512Z",
  "updated_at": "2026-10-19T09:41:07.874Z"
}

summary

  • matchboolean

    boolean method: whether every supplied field matched the BVN record. The per-field answers are in field_matches on the verification.

  • first_namestring

    core method: masked first name.

  • last_namestring

    core method: masked last name.

  • watchlistedboolean

    core method: whether the BVN is on the industry watchlist.

Full-tier accounts calling the REST API also receive provider, provider_reference and data, the normalized record. MCP, webhooks, lists and bulk results never include it. See Response shaping.

Full tier only
{
  "provider": "sandbox",
  "provider_reference": "SBX6CB753DB2C",
  "data": {
    "match": true,
    "field_matches": {
      "first_name": true,
      "last_name": true,
      "date_of_birth": true,
      "phone": true
    }
  }
}

Test values

Send these bodies with a sandbox key. More outcome triggers are on the Sandbox page.

Boolean match
{
  "method": "boolean",
  "bvn": "22222222221",
  "reason": "financialProducts",
  "consent": {
    "obtained": true
  },
  "match": {
    "first_name": "Clarke",
    "last_name": "Griffin"
  }
}
Boolean no-match
{
  "method": "boolean",
  "bvn": "22222222222",
  "reason": "financialProducts",
  "consent": {
    "obtained": true
  },
  "match": {
    "last_name": "Smith"
  }
}
Watchlisted BVN (boolean)
{
  "method": "boolean",
  "bvn": "22222222225",
  "reason": "creditBackgroundCheck",
  "consent": {
    "obtained": true
  },
  "match": {
    "last_name": "Murphy"
  }
}

Errors

StatusCodeMeaning
400
invalid_request
The body failed validation. details lists each field.
401
unauthorized
Missing or invalid API key.
402
insufficient_balance
Live only: wallet balance is below the check price.
403
not_entitled
Your workspace is not enabled for this product or method.
409
idempotency_key_reused
The Idempotency-Key was used with a different body.
404
consent_not_found
No consent with that consent_id in this mode.
412
consent_not_granted
The consent is pending, denied, expired or revoked.
412
consent_expired
The grant is older than 24 hours. Request a new consent.
412
consent_subject_mismatch
The consent was granted for a different BVN.
422
provider_rejected_request
The upstream registry rejected the request.
503
verification_unavailable
Temporary failure. Retry, with the same or a new Idempotency-Key.

All errors share one shape. See Errors for the full list.

Questions? Email developers@speedmap.ng. This page is also available as Markdown.