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:
// 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:
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
- Verify phone first — cheapest check, filters bad actors early.
- Set a confidence threshold for face match and route borderline cases to manual review.
- Never log raw OTP codes or full ID numbers.
- Time-box OTPs (5 minutes) and rate-limit attempts.
- Localize document types — NIN/BVN in Nigeria, Huduma in Kenya, etc.
Related
Last Updated: May 2026