Skip to main content

Identity Verification (KYC)

Verifying who your users are is a regulatory requirement for fintechs, banks, and any business handling payments in Africa. AfriRoute combines phone-based OTP verification with document and biometric checks so you can onboard customers remotely while satisfying KYC and AML obligations. This guide walks through a complete onboarding flow.

Scenario: Remote Fintech Onboarding​

A digital lender in Nigeria needs to verify each new applicant: confirm phone ownership, validate a government ID, and match a selfie to the ID photo — all within minutes, fully compliant with NDPR.

The Verification Flow​

phone OTP  →  document upload + OCR  →  selfie + liveness match  →  decision

Step 1: Verify Phone Ownership (OTP)​

Confirm the applicant controls the number before collecting anything else:

otp.js
// 1. Request an OTP
const start = await fetch('https://api.afriroute.ai/api/v1/verify/start', {
method: 'POST',
headers: { 'Authorization': 'Bearer $AFRIROUTE_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ to: '+2348012345678', channel: 'sms', from: 'KashLend' })
}).then(r => r.json());
// { "verification_id": "ver_abc123", "status": "pending", "expires_in": 300 }

// 2. Check the code the user entered
const check = await fetch('https://api.afriroute.ai/api/v1/verify/check', {
method: 'POST',
headers: { 'Authorization': 'Bearer $AFRIROUTE_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ verification_id: 'ver_abc123', code: '123456' })
}).then(r => r.json());
// { "status": "approved" }

Step 2: Verify a Government ID​

Upload the document; AfriRoute's OCR extracts and validates the fields against the issuing format:

curl -X POST https://api.afriroute.ai/api/v1/kyc/document \
-H "Authorization: Bearer $AFRIROUTE_API_KEY" \
-F "country=NG" \
-F "document_type=nin" \
-F "front=@/path/to/id_front.jpg"
{
"document_id": "doc_xyz789",
"status": "verified",
"extracted": { "full_name": "Chidi Okeke", "dob": "1994-03-12", "id_number": "NIN-*****6789" },
"checks": { "format_valid": true, "tampering_detected": false, "expired": false }
}

Step 3: Biometric Liveness & Face Match​

Confirm the live applicant matches the ID photo:

curl -X POST https://api.afriroute.ai/api/v1/kyc/face-match \
-H "Authorization: Bearer $AFRIROUTE_API_KEY" \
-F "document_id=doc_xyz789" \
-F "selfie=@/path/to/selfie.jpg"
{ "match": true, "confidence": 0.97, "liveness": "passed" }

Step 4: Make a Decision​

Combine the signals into an onboarding decision and store the result for your audit trail:

decide.py
def kyc_decision(otp, doc, face):
if otp['status'] != 'approved':
return 'reject', 'phone_unverified'
if doc['checks']['tampering_detected'] or doc['checks']['expired']:
return 'reject', 'document_invalid'
if not face['match'] or face['confidence'] < 0.90:
return 'manual_review', 'face_mismatch'
return 'approve', 'all_checks_passed'

Compliance Notes​

  • KYC data is sensitive PII — encrypt at rest, restrict access, and honor erasure requests under Data Protection and NDPR.
  • For EU applicants, apply GDPR rules including explicit consent and data residency.
  • Retain verification records only as long as AML law requires, then delete.

Best Practices​

  1. Verify phone first — cheapest check, filters bad actors early.
  2. Set a confidence threshold for face match and route borderline cases to manual review.
  3. Never log raw OTP codes or full ID numbers.
  4. Time-box OTPs (5 minutes) and rate-limit attempts.
  5. Localize document types — NIN/BVN in Nigeria, Huduma in Kenya, etc.

Last Updated: May 2026