API reference
Every Speedmap endpoint with parameters, request and response examples, and a Try it panel for sandbox keys.
Generated from the OpenAPI description (OpenAPI 3.0.3, API version 1.0.0). All requests go to http://localhost:4000 and authenticate with Authorization: Bearer sk_test_... or sk_live_.... Bodies are JSON.
Each operation has a Try it panel. Paste a sandbox key (sk_test_) to send real requests from this page and see the live response; sandbox calls use test data and are free. Live keys are not accepted here.
NIN and phone.
Verify a National Identity Number against the NIMC record by raw NIN, in-person selfie, or NINAuth share code.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body · method
Raw NIN lookup. Restricted by NIMC to financial institutions and government agencies.
methodstringrequiredAlways
nin.ninstringrequiredFormat: 11 digits.
reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
consentobjectrequiredYour attestation that you obtained the data subject's consent for this purpose.
consent.obtainedbooleanrequiredAlways
true.matchobjectOptional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.
match.first_namestringMust not be empty.
match.middle_namestringMust not be empty.
match.last_namestringMust not be empty.
match.date_of_birthstringFormat: date,
YYYY-MM-DD.
NIN plus a live selfie. The selfie is the consent. Available to all business types.
methodstringrequiredAlways
in_person.ninstringrequiredFormat: 11 digits.
selfie_imagestringrequiredBase64-encoded JPEG selfie. At least 100 characters.
reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
matchobjectOptional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.
match.first_namestringMust not be empty.
match.middle_namestringMust not be empty.
match.last_namestringMust not be empty.
match.date_of_birthstringFormat: date,
YYYY-MM-DD.
6-character code the subject generates in the NINAuth app. The code is the consent.
methodstringrequiredAlways
share_code.share_codestringrequiredFormat: 5 or 6 letters or digits.
reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
matchobjectOptional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.
match.first_namestringMust not be empty.
match.middle_namestringMust not be empty.
match.last_namestringMust not be empty.
match.date_of_birthstringFormat: date,
YYYY-MM-DD.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
curl -X POST http://localhost:4000/v1/verify/nin \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"method": "nin",
"nin": "98765432109",
"reason": "financialProducts",
"consent": {
"obtained": true
},
"match": {
"last_name": "Griffin"
}
}'{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "nin",
"method": "nin_raw",
"status": "verified",
"match": true,
"field_matches": {
"last_name": true
},
"field_confidence": {
"last_name": 100
},
"mode": "sandbox",
"reason": "financialProducts",
"subject": "*******2109",
"summary": {
"first_name": "A*****",
"last_name": "O*****"
},
"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": 412,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}Resolve a mobile number to the name and date of birth on its ICAD/BVN record. For corroboration and fraud signal, not as standalone identity.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body
phonestringrequiredFormat: Nigerian mobile number,
0803…or+234803….reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
consentobjectrequiredYour attestation that you obtained the data subject's consent for this purpose.
consent.obtainedbooleanrequiredAlways
true.matchobjectOptional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.
match.first_namestringMust not be empty.
match.middle_namestringMust not be empty.
match.last_namestringMust not be empty.
match.date_of_birthstringFormat: date,
YYYY-MM-DD.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
curl -X POST http://localhost:4000/v1/verify/phone \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"phone": "08031234567",
"reason": "financialProducts",
"consent": {
"obtained": true
},
"match": {
"last_name": "Griffin"
}
}'{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "phone",
"method": "phone_lookup",
"status": "verified",
"match": true,
"field_matches": {
"last_name": true
},
"field_confidence": {
"last_name": 100
},
"mode": "sandbox",
"reason": "financialProducts",
"subject": "*******4567",
"summary": {
"first_name": "A*****",
"last_name": "O*****"
},
"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": 233,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}BVN and bank accounts.
Validate a Bank Verification Number through NIBSS: boolean match without PII, or the full record with subject consent.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body · method
Match / no-match against the BVN record. Returns no PII. The cheapest BVN check.
methodstringrequiredAlways
boolean.bvnstringrequiredFormat: 11 digits.
reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
consentobjectrequiredYour attestation that you obtained the data subject's consent for this purpose.
consent.obtainedbooleanrequiredAlways
true.matchobjectrequiredOptional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.
match.first_namestringMust not be empty.
match.middle_namestringMust not be empty.
match.last_namestringMust not be empty.
match.date_of_birthstringFormat: date,
YYYY-MM-DD.
Full BVN record. Requires a consent granted by the subject through POST /v1/consents.
methodstringrequiredAlways
core.bvnstringrequiredFormat: 11 digits.
reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
consent_idstringrequiredFormat: starts_with.
matchobjectOptional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.
match.first_namestringMust not be empty.
match.middle_namestringMust not be empty.
match.last_namestringMust not be empty.
match.date_of_birthstringFormat: date,
YYYY-MM-DD.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
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"
}
}'{
"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"
}Resolve and verify the holder name on a Nigerian bank account via NIBSS ICAD Name Enquiry. Batch-capable.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body
account_numberstringrequiredFormat: 10 digits.
bank_codestringrequiredFormat: 3 to 6 digits.
matchobjectmatch.namestringrequiredExpected account holder name; compared token by token, order-insensitive. At least 2 characters.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
curl -X POST http://localhost:4000/v1/verify/account \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"account_number": "0123456789",
"bank_code": "058",
"match": {
"name": "Clarke Griffin"
}
}'{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "account",
"method": "account_name_enquiry",
"status": "verified",
"match": true,
"field_matches": null,
"field_confidence": null,
"mode": "sandbox",
"reason": null,
"subject": "******6789",
"summary": {
"account_name_masked": "A***** C***** O*****",
"bank_name": "Guaranty Trust Bank",
"name_match": true
},
"consent": {
"mechanism": "not_required",
"consent_id": null,
"timestamp": "2026-10-19T09:41:07.512Z"
},
"source": "api",
"error": null,
"billing": {
"amount_kobo": 0,
"currency": "NGN"
},
"latency_ms": 190,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}Face liveness and match.
Passive liveness detection and face comparison against the BVN photo in one call, via NIBSS N-Face.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body
imagestringrequiredSelfie as base64 JPEG/PNG, or an https URL when image_type is url. At least 20 characters.
image_typestringOne of:
base64,url. Defaults tobase64.bvnstringCompare the selfie against the photo on this BVN. Omit for liveness only. Format: 11 digits.
liveness_thresholdnumberBetween 0 and 1. Defaults to
0.6.face_match_thresholdnumberBetween 0 and 1. Defaults to
0.9.orderstringLiveness first, comparison first, or both in parallel. One of:
pl_fc_serial,fc_pl_serial,fc_pl_parallel. Defaults topl_fc_serial.os_typestringOne of:
ios,android,desktop,unknown. Defaults tounknown.reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
curl -X POST http://localhost:4000/v1/verify/face \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"image": "<base64 selfie>",
"bvn": "22222222221",
"reason": "financialProducts"
}'{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "face",
"method": "face_liveness_match",
"status": "verified",
"match": true,
"field_matches": null,
"field_confidence": null,
"mode": "sandbox",
"reason": "financialProducts",
"subject": "*******2221",
"summary": {
"liveness_passed": true,
"liveness_confidence": 0.885,
"liveness_quality": 0.885,
"face_match_passed": true,
"face_match_confidence": 0.988,
"face_match_quality": 0.902,
"session_code": "11b004ce-9f2f-43df-858e-79eacf50af07",
"thresholds": {
"liveness": 0.6,
"face_match": 0.9
}
},
"consent": {
"mechanism": "in_person_selfie",
"consent_id": null,
"timestamp": "2026-10-19T09:41:07.512Z"
},
"source": "api",
"error": null,
"billing": {
"amount_kobo": 0,
"currency": "NGN"
},
"latency_ms": 1180,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}CAC company verification (KYB).
CAC company verification through NIBSS CIV: status, registration, directors, shareholders, share capital and winding-up.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body
rc_numberstringCAC RC or BN number, e.g. RC1234567. At least 3 characters.
tinstringAt least 5 characters.
company_namestringAt least 2 characters.
includearray of stringsEach one of:
directors,shareholders,share_capital,line_of_business,affiliates,status_report,winding_up,certificate. Defaults to["directors","shareholders","share_capital","status_report"].reasonstringPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
matchobjectmatch.company_namestringAt least 2 characters.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
curl -X POST http://localhost:4000/v1/verify/business \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"rc_number": "RC1234567",
"include": [
"directors",
"shareholders",
"share_capital",
"status_report"
]
}'{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "business",
"method": "cac_rc",
"status": "verified",
"match": true,
"field_matches": null,
"field_confidence": null,
"mode": "sandbox",
"reason": null,
"subject": null,
"summary": {
"company_name": "SPEEDILY SERVICES LIMITED",
"rc_number": "RC1234567",
"status": "ACTIVE",
"active": true,
"type": "Private Company Limited by Shares",
"registered_at": "2016-05-12",
"state": "FCT",
"name_match": null
},
"consent": {
"mechanism": "public_registry",
"consent_id": null,
"timestamp": "2026-10-19T09:41:07.512Z"
},
"source": "api",
"error": null,
"billing": {
"amount_kobo": 0,
"currency": "NGN"
},
"latency_ms": 640,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}Risk signals.
One risk score from SIM-swap recency, BVN demographic changes and watchlist status. Built for account-takeover and onboarding fraud.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body
phonestringFormat: Nigerian mobile number,
0803…or+234803….bvnstringFormat: 11 digits.
reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
consentobjectrequiredYour attestation that you obtained the data subject's consent for this purpose.
consent.obtainedbooleanrequiredAlways
true.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
curl -X POST http://localhost:4000/v1/signals \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"phone": "08099990000",
"bvn": "22222222225",
"reason": "financialProducts",
"consent": {
"obtained": true
}
}'{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "signals",
"method": "risk_signals",
"status": "verified",
"match": null,
"field_matches": null,
"field_confidence": null,
"mode": "sandbox",
"reason": "financialProducts",
"subject": "*******2225",
"summary": {
"risk_score": 100,
"risk_level": "high",
"factors": [
{
"code": "watchlisted",
"weight": 60,
"detail": "BVN is on the industry watchlist"
},
{
"code": "sim_swap_7d",
"weight": 35,
"detail": "SIM swapped 2 day(s) ago"
},
{
"code": "bvn_name_change_30d",
"weight": 20,
"detail": "Name changed on the BVN in the last 30 days"
},
{
"code": "bvn_phone_change_30d",
"weight": 10,
"detail": "Phone number changed on the BVN in the last 30 days"
}
],
"sim_swap_recent": true,
"days_since_sim_swap": 2,
"bvn_demographic_changes": 2,
"bvn_demographic_changes_30d": 2,
"watchlisted": 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": 520,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}Passport, driver's licence, voter's card.
Verify a international passport against the Nigeria Immigration Service record. Sandbox only until the Nigeria Immigration Service data agreement is live.
Preview: available with sandbox keys; live access follows the provider agreement.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body
passport_numberstringrequiredFormat: a letter followed by 8 digits, e.g.
A12345678.reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
consentobjectrequiredYour attestation that you obtained the data subject's consent for this purpose.
consent.obtainedbooleanrequiredAlways
true.matchobjectOptional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.
match.first_namestringMust not be empty.
match.middle_namestringMust not be empty.
match.last_namestringMust not be empty.
match.date_of_birthstringFormat: date,
YYYY-MM-DD.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
curl -X POST http://localhost:4000/v1/verify/passport \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"passport_number": "A12345678",
"reason": "financialProducts",
"consent": {
"obtained": true
}
}'{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "passport",
"method": "passport",
"status": "verified",
"match": true,
"field_matches": null,
"field_confidence": null,
"mode": "sandbox",
"reason": "financialProducts",
"subject": "*****5678",
"summary": {
"first_name": "A*****",
"last_name": "O*****",
"document_type": "passport",
"expired": false,
"expires_at": "2031-06-09"
},
"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": 350,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}Verify a driver's licence against the FRSC record. Sandbox only until the FRSC data agreement is live.
Preview: available with sandbox keys; live access follows the provider agreement.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body
license_numberstringrequiredFormat: FRSC format, e.g.
LAG12345AA01.reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
consentobjectrequiredYour attestation that you obtained the data subject's consent for this purpose.
consent.obtainedbooleanrequiredAlways
true.matchobjectOptional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.
match.first_namestringMust not be empty.
match.middle_namestringMust not be empty.
match.last_namestringMust not be empty.
match.date_of_birthstringFormat: date,
YYYY-MM-DD.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
curl -X POST http://localhost:4000/v1/verify/drivers-license \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"license_number": "LAG12345AA01",
"reason": "financialProducts",
"consent": {
"obtained": true
}
}'{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "drivers_license",
"method": "drivers_license",
"status": "verified",
"match": true,
"field_matches": null,
"field_confidence": null,
"mode": "sandbox",
"reason": "financialProducts",
"subject": "********AA01",
"summary": {
"first_name": "A*****",
"last_name": "O*****",
"document_type": "drivers_license",
"expired": false,
"expires_at": "2027-01-31"
},
"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": 340,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}Verify a voter's card against the INEC record. Sandbox only until the INEC data agreement is live.
Preview: available with sandbox keys; live access follows the provider agreement.
Headers
Idempotency-KeystringRetries with the same key and body return the original result and are never billed twice. 8 to 128 characters.
Body
vinstringrequiredFormat: 19 letters or digits.
reasonstringrequiredPurpose of the check. One of the 38 NIMC purpose codes. See the purpose code list.
consentobjectrequiredYour attestation that you obtained the data subject's consent for this purpose.
consent.obtainedbooleanrequiredAlways
true.matchobjectOptional values to compare against the record. Each comparison is returned in field_matches; match is true only if all of them agree.
match.first_namestringMust not be empty.
match.middle_namestringMust not be empty.
match.last_namestringMust not be empty.
match.date_of_birthstringFormat: date,
YYYY-MM-DD.
Responses
- 200Completed (verified or not_found)Verification
- 202Pending: the provider did not answer in time. Poll GET /v1/verifications/{reference_id}.Verification
- 400Invalid requestError
- 401Missing or invalid API keyError
- 402Wallet balance too low (live)Error
- 403Not entitled, or live access not enabledError
- 409Idempotency-Key reused with a different bodyError
- 412Consent missing, pending or mismatchedError
- 422Provider rejected the requestError
- 503Temporarily unavailable; safe to retryError
curl -X POST http://localhost:4000/v1/verify/voters-card \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"vin": "90F5B1A2C3D4E5F6071",
"reason": "financialProducts",
"consent": {
"obtained": true
}
}'{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "voters_card",
"method": "voters_card",
"status": "verified",
"match": true,
"field_matches": null,
"field_confidence": null,
"mode": "sandbox",
"reason": "financialProducts",
"subject": "***************6071",
"summary": {
"first_name": "A*****",
"last_name": "O*****",
"document_type": "voters_card",
"expired": false,
"expires_at": null
},
"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": 330,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}Retrieve and list the results of earlier checks. See Verifications.
Query parameters
limitintegerMaximum 100. Defaults to
20.productstringstatusstringbeforestringCursor: created_at of the last item ISO 8601 timestamp.
Responses
- 200Assertion-only list
curl "http://localhost:4000/v1/verifications" \
-H "Authorization: Bearer sk_test_..."{
"object": "list",
"data": [
{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "nin",
"method": "nin_raw",
"status": "verified",
"match": true,
"field_matches": {
"last_name": true
},
"field_confidence": {
"last_name": 100
},
"mode": "sandbox",
"reason": "financialProducts",
"subject": "*******2109",
"summary": {
"first_name": "A*****",
"last_name": "O*****"
},
"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": 412,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
},
{
"reference_id": "spm_5b0e2c9d1f7a3e6b8c4d2a10",
"object": "verification",
"product": "account",
"method": "account_name_enquiry",
"status": "verified",
"match": true,
"field_matches": null,
"field_confidence": null,
"mode": "sandbox",
"reason": null,
"subject": "******6789",
"summary": {
"account_name_masked": "A***** C***** O*****",
"bank_name": "Guaranty Trust Bank",
"name_match": true
},
"consent": {
"mechanism": "not_required",
"consent_id": null,
"timestamp": "2026-10-19T09:41:07.512Z"
},
"source": "api",
"error": null,
"billing": {
"amount_kobo": 0,
"currency": "NGN"
},
"latency_ms": 190,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}
],
"has_more": true
}Pending verifications are re-queried with the provider on read.
Path parameters
reference_idstringrequired
Responses
- 200ResultVerification
- 202Still pending
- 401Missing or invalid API keyError
- 404Not foundError
curl "http://localhost:4000/v1/verifications/spm_8171f3a87cbe221341f7185f" \
-H "Authorization: Bearer sk_test_..."{
"reference_id": "spm_8171f3a87cbe221341f7185f",
"object": "verification",
"product": "nin",
"method": "nin_raw",
"status": "verified",
"match": true,
"field_matches": {
"last_name": true
},
"field_confidence": {
"last_name": 100
},
"mode": "sandbox",
"reason": "financialProducts",
"subject": "*******2109",
"summary": {
"first_name": "A*****",
"last_name": "O*****"
},
"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": 412,
"created_at": "2026-10-19T09:41:07.512Z",
"updated_at": "2026-10-19T09:41:07.874Z"
}Consent requests the data subject approves by link, email or USSD. See Consent.
Creates a consent request the data subject approves by link, email or USSD. Required before BVN core lookups.
Body
identifier_typestringrequiredOne of:
bvn,nin.identifierstringrequiredFormat: 11 digits.
categoriesstringY/N mask over personal identification, contact, demographic, geographic data. Format: 4-character Y/N mask, e.g.
YYNN. Defaults toYYNN.channelstringOne of:
redirect,email,ussd. Defaults toredirect.reasonstringDefaults to
financialProducts.emailstringFormat: email.
redirect_urlstringFormat: uri.
Responses
- 201Consent request created
- 400Invalid requestError
- 401Missing or invalid API keyError
curl -X POST "http://localhost:4000/v1/consents" \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"identifier_type": "bvn",
"identifier": "22222222221",
"categories": "YYNN",
"channel": "redirect",
"reason": "financialProducts"
}'{
"id": "cns_423a8f143e7f2f8ffe7dda3344d36710",
"object": "consent",
"identifier_type": "bvn",
"subject": "*******2221",
"categories": "YYNN",
"category_labels": [
"Personal identification",
"Contact information"
],
"channel": "ussd",
"status": "pending",
"reason": "financialProducts",
"authorization_url": "https://speedmap-delta.vercel.app/consent/cns_423a8f143e7f2f8ffe7dda3344d36710",
"ussd_code": "*565*1*7*70205378#",
"redirect_url": null,
"granted_at": null,
"expires_at": "2026-10-20T09:41:07.512Z",
"created_at": "2026-10-19T09:41:07.512Z",
"mode": "sandbox"
}curl "http://localhost:4000/v1/consents" \
-H "Authorization: Bearer sk_test_..."{
"object": "list",
"data": [
{
"id": "cns_423a8f143e7f2f8ffe7dda3344d36710",
"object": "consent",
"identifier_type": "bvn",
"subject": "*******2221",
"categories": "YYNN",
"category_labels": [
"Personal identification",
"Contact information"
],
"channel": "ussd",
"status": "granted",
"reason": "financialProducts",
"authorization_url": "https://speedmap-delta.vercel.app/consent/cns_423a8f143e7f2f8ffe7dda3344d36710",
"ussd_code": "*565*1*7*70205378#",
"redirect_url": null,
"granted_at": "2026-10-19T09:43:52.004Z",
"expires_at": "2026-10-20T09:43:52.004Z",
"created_at": "2026-10-19T09:41:07.512Z",
"mode": "sandbox"
}
],
"has_more": false
}Path parameters
idstringrequired
Responses
- 200Consent
- 404Not foundError
curl "http://localhost:4000/v1/consents/cns_423a8f143e7f2f8ffe7dda3344d36710" \
-H "Authorization: Bearer sk_test_..."{
"id": "cns_423a8f143e7f2f8ffe7dda3344d36710",
"object": "consent",
"identifier_type": "bvn",
"subject": "*******2221",
"categories": "YYNN",
"category_labels": [
"Personal identification",
"Contact information"
],
"channel": "ussd",
"status": "granted",
"reason": "financialProducts",
"authorization_url": "https://speedmap-delta.vercel.app/consent/cns_423a8f143e7f2f8ffe7dda3344d36710",
"ussd_code": "*565*1*7*70205378#",
"redirect_url": null,
"granted_at": "2026-10-19T09:43:52.004Z",
"expires_at": "2026-10-20T09:43:52.004Z",
"created_at": "2026-10-19T09:41:07.512Z",
"mode": "sandbox"
}curl -X POST "http://localhost:4000/v1/consents/cns_423a8f143e7f2f8ffe7dda3344d36710/revoke" \
-H "Authorization: Bearer sk_test_..."{
"id": "cns_423a8f143e7f2f8ffe7dda3344d36710",
"object": "consent",
"identifier_type": "bvn",
"subject": "*******2221",
"categories": "YYNN",
"category_labels": [
"Personal identification",
"Contact information"
],
"channel": "ussd",
"status": "revoked",
"reason": "financialProducts",
"authorization_url": "https://speedmap-delta.vercel.app/consent/cns_423a8f143e7f2f8ffe7dda3344d36710",
"ussd_code": "*565*1*7*70205378#",
"redirect_url": null,
"granted_at": "2026-10-19T09:43:52.004Z",
"expires_at": "2026-10-20T09:43:52.004Z",
"created_at": "2026-10-19T09:41:07.512Z",
"mode": "sandbox"
}Acts as the data subject. Sandbox keys only.
Path parameters
idstringrequireddecisionstringrequiredOne of:
approve,deny.
Responses
- 200Updated consent
curl -X POST "http://localhost:4000/v1/sandbox/consents/cns_423a8f143e7f2f8ffe7dda3344d36710/approve" \
-H "Authorization: Bearer sk_test_..."{
"id": "cns_423a8f143e7f2f8ffe7dda3344d36710",
"object": "consent",
"identifier_type": "bvn",
"subject": "*******2221",
"categories": "YYNN",
"category_labels": [
"Personal identification",
"Contact information"
],
"channel": "ussd",
"status": "granted",
"reason": "financialProducts",
"authorization_url": "https://speedmap-delta.vercel.app/consent/cns_423a8f143e7f2f8ffe7dda3344d36710",
"ussd_code": "*565*1*7*70205378#",
"redirect_url": null,
"granted_at": "2026-10-19T09:43:52.004Z",
"expires_at": "2026-10-20T09:43:52.004Z",
"created_at": "2026-10-19T09:41:07.512Z",
"mode": "sandbox"
}Up to 10,000 checks per job; results are read from the job, never returned inline. See Bulk verification.
Up to 10,000 items of one product. Returns a job handle; results are read from the job, never inline.
Body
productstringrequiredOne of:
nin,bvn,phone,business,account,signals,passport,drivers_license,voters_card.itemsarray of objectsrequired1 to 10,000 items.
namestringAt most 120 characters.
Responses
- 202Job queued
- 400Invalid requestError
- 401Missing or invalid API keyError
- 403Not entitled, or live access not enabledError
curl -X POST "http://localhost:4000/v1/bulk" \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"product": "account",
"name": "Payout batch 42",
"items": [
{
"account_number": "0123456789",
"bank_code": "058",
"match": {
"name": "Clarke Griffin"
}
}
]
}'{
"id": "job_1a2b3c4d5e6f7a8b",
"object": "bulk_job",
"product": "account",
"name": "Payout batch 42",
"status": "queued",
"total": 2500,
"processed": 0,
"counts": {
"verified": 0,
"not_found": 0,
"failed": 0
},
"progress": 0,
"mode": "sandbox",
"created_at": "2026-10-19T09:41:07.512Z",
"completed_at": null
}curl "http://localhost:4000/v1/bulk" \
-H "Authorization: Bearer sk_test_..."{
"object": "list",
"data": [
{
"id": "job_1a2b3c4d5e6f7a8b",
"object": "bulk_job",
"product": "account",
"name": "Payout batch 42",
"status": "running",
"total": 2500,
"processed": 1180,
"counts": {
"verified": 1102,
"not_found": 61,
"failed": 17
},
"progress": 47,
"mode": "sandbox",
"created_at": "2026-10-19T09:41:07.512Z",
"completed_at": null
}
],
"has_more": false
}curl "http://localhost:4000/v1/bulk/job_1a2b3c4d5e6f7a8b" \
-H "Authorization: Bearer sk_test_..."{
"id": "job_1a2b3c4d5e6f7a8b",
"object": "bulk_job",
"product": "account",
"name": "Payout batch 42",
"status": "running",
"total": 2500,
"processed": 1180,
"counts": {
"verified": 1102,
"not_found": 61,
"failed": 17
},
"progress": 47,
"mode": "sandbox",
"created_at": "2026-10-19T09:41:07.512Z",
"completed_at": null
}Per-row status and match. PII-free; fetch individual records by reference_id.
Path parameters
idstringrequired
Responses
- 200Rows
curl "http://localhost:4000/v1/bulk/job_1a2b3c4d5e6f7a8b/results" \
-H "Authorization: Bearer sk_test_..."{
"object": "list",
"data": [
{
"row": 1,
"reference_id": "spm_0c1d2e3f4a5b6c7d8e9f0a1b",
"status": "verified",
"match": true,
"subject": "******6789"
},
{
"row": 2,
"reference_id": "spm_1d2e3f4a5b6c7d8e9f0a1b2c",
"status": "verified",
"match": false,
"subject": "******7890"
},
{
"row": 3,
"reference_id": "spm_2e3f4a5b6c7d8e9f0a1b2c3d",
"status": "not_found",
"match": false,
"subject": "******0000"
}
]
}Lookup lists: products and prices, purpose codes and bank codes.
curl "http://localhost:4000/v1/products" \
-H "Authorization: Bearer sk_test_..."{
"object": "list",
"data": [
{
"id": "nin",
"name": "NIN Verification",
"category": "identity",
"summary": "Verify a National Identity Number against the NIMC record by raw NIN, in-person selfie, or NINAuth share code.",
"endpoint": "POST /v1/verify/nin",
"availability": "available",
"enabled": true,
"price": {
"amount_kobo": 10000,
"currency": "NGN"
}
},
"…"
]
}curl "http://localhost:4000/v1/reasons" \
-H "Authorization: Bearer sk_test_..."{
"object": "list",
"data": [
{
"key": "taxationEnrollment",
"label": "Taxation Enrollment"
},
{
"key": "taxationAssessment",
"label": "Taxation Assessment"
},
{
"key": "taxationEnforcement",
"label": "Taxation Enforcement"
},
"…"
]
}Questions? Email developers@speedmap.ng. This page is also available as Markdown.