Skip to content

API reference

Every Speedmap endpoint with parameters, request and response examples, and a Try it panel for sandbox keys.

View as Markdown

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.

Identity

NIN and phone.

NIN Verification

POST/v1/verify/nin

Verify a National Identity Number against the NIMC record by raw NIN, in-person selfie, or NINAuth share code.

Headers

  • Idempotency-Keystring

    Retries 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.

  • methodstringrequired

    Always nin.

  • ninstringrequired

    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.

  • matchobject

    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.

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
Request
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"
  }
}'
200 · Response
{
  "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"
}

Phone Identity Lookup

POST/v1/verify/phone

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-Keystring

    Retries with the same key and body return the original result and are never billed twice. 8 to 128 characters.

Body

  • phonestringrequired

    Format: Nigerian mobile number, 0803… or +234803….

  • 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.

  • matchobject

    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.

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
Request
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"
  }
}'
200 · Response
{
  "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"
}

Financial

BVN and bank accounts.

BVN Verification

POST/v1/verify/bvn

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

Headers

  • Idempotency-Keystring

    Retries 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.

  • 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.

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
Request
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"
  }
}'
200 · Response
{
  "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"
}

Bank Account Verification

POST/v1/verify/account

Resolve and verify the holder name on a Nigerian bank account via NIBSS ICAD Name Enquiry. Batch-capable.

Headers

  • Idempotency-Keystring

    Retries with the same key and body return the original result and are never billed twice. 8 to 128 characters.

Body

  • account_numberstringrequired

    Format: 10 digits.

  • bank_codestringrequired

    Format: 3 to 6 digits.

  • matchobject
  • match.namestringrequired

    Expected 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
Request
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"
  }
}'
200 · Response
{
  "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"
}

Biometric

Face liveness and match.

Face Liveness & Match

POST/v1/verify/face

Passive liveness detection and face comparison against the BVN photo in one call, via NIBSS N-Face.

Headers

  • Idempotency-Keystring

    Retries with the same key and body return the original result and are never billed twice. 8 to 128 characters.

Body

  • imagestringrequired

    Selfie as base64 JPEG/PNG, or an https URL when image_type is url. At least 20 characters.

  • image_typestring

    One of: base64, url. Defaults to base64.

  • bvnstring

    Compare the selfie against the photo on this BVN. Omit for liveness only. Format: 11 digits.

  • liveness_thresholdnumber

    Between 0 and 1. Defaults to 0.6.

  • face_match_thresholdnumber

    Between 0 and 1. Defaults to 0.9.

  • orderstring

    Liveness first, comparison first, or both in parallel. One of: pl_fc_serial, fc_pl_serial, fc_pl_parallel. Defaults to pl_fc_serial.

  • os_typestring

    One of: ios, android, desktop, unknown. Defaults to unknown.

  • reasonstringrequired

    Purpose 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
Request
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"
}'
200 · Response
{
  "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"
}

Business

CAC company verification (KYB).

Business Verification (KYB)

POST/v1/verify/business

CAC company verification through NIBSS CIV: status, registration, directors, shareholders, share capital and winding-up.

Headers

  • Idempotency-Keystring

    Retries with the same key and body return the original result and are never billed twice. 8 to 128 characters.

Body

  • rc_numberstring

    CAC RC or BN number, e.g. RC1234567. At least 3 characters.

  • tinstring

    At least 5 characters.

  • company_namestring

    At least 2 characters.

  • includearray of strings

    Each one of: directors, shareholders, share_capital, line_of_business, affiliates, status_report, winding_up, certificate. Defaults to ["directors","shareholders","share_capital","status_report"].

  • reasonstring

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

  • matchobject
  • match.company_namestring

    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
Request
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"
  ]
}'
200 · Response
{
  "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"
}

Fraud

Risk signals.

Fraud Signals

POST/v1/signals

One risk score from SIM-swap recency, BVN demographic changes and watchlist status. Built for account-takeover and onboarding fraud.

Headers

  • Idempotency-Keystring

    Retries with the same key and body return the original result and are never billed twice. 8 to 128 characters.

Body

  • phonestring

    Format: Nigerian mobile number, 0803… or +234803….

  • bvnstring

    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.

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
Request
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
  }
}'
200 · Response
{
  "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"
}

Documents

Passport, driver's licence, voter's card.

International PassportPreview

POST/v1/verify/passport

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-Keystring

    Retries with the same key and body return the original result and are never billed twice. 8 to 128 characters.

Body

  • passport_numberstringrequired

    Format: a letter followed by 8 digits, e.g. A12345678.

  • 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.

  • matchobject

    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.

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
Request
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
  }
}'
200 · Response
{
  "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"
}

Driver's LicencePreview

POST/v1/verify/drivers-license

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-Keystring

    Retries with the same key and body return the original result and are never billed twice. 8 to 128 characters.

Body

  • license_numberstringrequired

    Format: FRSC format, e.g. LAG12345AA01.

  • 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.

  • matchobject

    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.

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
Request
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
  }
}'
200 · Response
{
  "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"
}

Voter's CardPreview

POST/v1/verify/voters-card

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-Keystring

    Retries with the same key and body return the original result and are never billed twice. 8 to 128 characters.

Body

  • vinstringrequired

    Format: 19 letters or 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.

  • matchobject

    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.

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
Request
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
  }
}'
200 · Response
{
  "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"
}

Verifications

Retrieve and list the results of earlier checks. See Verifications.

List verifications

GET/v1/verifications

Query parameters

  • limitinteger

    Maximum 100. Defaults to 20.

  • productstring
  • statusstring
  • beforestring

    Cursor: created_at of the last item ISO 8601 timestamp.

Responses

  • 200Assertion-only list
Request
curl "http://localhost:4000/v1/verifications" \
  -H "Authorization: Bearer sk_test_..."
200 · Response
{
  "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
}

Retrieve a verification

GET/v1/verifications/{reference_id}

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
Request
curl "http://localhost:4000/v1/verifications/spm_8171f3a87cbe221341f7185f" \
  -H "Authorization: Bearer sk_test_..."
200 · Response
{
  "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.

List consents

GET/v1/consents

Responses

  • 200Consents
Request
curl "http://localhost:4000/v1/consents" \
  -H "Authorization: Bearer sk_test_..."
200 · Response
{
  "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
}

Bulk

Up to 10,000 checks per job; results are read from the job, never returned inline. See Bulk verification.

Create a bulk job

POST/v1/bulk

Up to 10,000 items of one product. Returns a job handle; results are read from the job, never inline.

Body

  • productstringrequired

    One of: nin, bvn, phone, business, account, signals, passport, drivers_license, voters_card.

  • itemsarray of objectsrequired

    1 to 10,000 items.

  • namestring

    At most 120 characters.

Responses

  • 202Job queued
  • 400Invalid requestError
  • 401Missing or invalid API keyError
  • 403Not entitled, or live access not enabledError
Request
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"
      }
    }
  ]
}'
202 · Response
{
  "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
}

List bulk jobs

GET/v1/bulk

Responses

  • 200Jobs
Request
curl "http://localhost:4000/v1/bulk" \
  -H "Authorization: Bearer sk_test_..."
200 · Response
{
  "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
}

Bulk job progress

GET/v1/bulk/{id}

Path parameters

  • idstringrequired

Responses

  • 200Job
Request
curl "http://localhost:4000/v1/bulk/job_1a2b3c4d5e6f7a8b" \
  -H "Authorization: Bearer sk_test_..."
200 · Response
{
  "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
}

Bulk job results

GET/v1/bulk/{id}/results

Per-row status and match. PII-free; fetch individual records by reference_id.

Path parameters

  • idstringrequired

Responses

  • 200Rows
Request
curl "http://localhost:4000/v1/bulk/job_1a2b3c4d5e6f7a8b/results" \
  -H "Authorization: Bearer sk_test_..."
200 · Response
{
  "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"
    }
  ]
}

Reference

Lookup lists: products and prices, purpose codes and bank codes.

List products, prices and entitlements

GET/v1/products

Responses

  • 200Products
Request
curl "http://localhost:4000/v1/products" \
  -H "Authorization: Bearer sk_test_..."
200 · Response
{
  "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"
      }
    },
    "…"
  ]
}

List the 38 NIMC purpose codes

GET/v1/reasons

Responses

  • 200Reasons
Request
curl "http://localhost:4000/v1/reasons" \
  -H "Authorization: Bearer sk_test_..."
200 · Response
{
  "object": "list",
  "data": [
    {
      "key": "taxationEnrollment",
      "label": "Taxation Enrollment"
    },
    {
      "key": "taxationAssessment",
      "label": "Taxation Assessment"
    },
    {
      "key": "taxationEnforcement",
      "label": "Taxation Enforcement"
    },
    "…"
  ]
}

List bank codes

GET/v1/banks

Responses

  • 200Banks
Request
curl "http://localhost:4000/v1/banks" \
  -H "Authorization: Bearer sk_test_..."
200 · Response
{
  "object": "list",
  "data": [
    {
      "code": "044",
      "name": "Access Bank"
    },
    {
      "code": "058",
      "name": "Guaranty Trust Bank"
    },
    "…"
  ]
}

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