Websites11 min read

KYC + identity verification Africa: NINEA, NIF, ID scan in 2026

Mohamed Bah·Fondateur, Kolonell
May 19, 2026
Share:
KYC + identity verification Africa: NINEA, NIF, ID scan in 2026

KYC + identity verification Africa: NINEA, NIF, ID scan in 2026

Websites

KYC (Know Your Customer) is mandatory for fintechs, marketplaces, payment platforms, neobanks. In Senegal and Ivory Coast, in 2026, the BCEAO regulatory framework requires progressive KYC: level 1 (basic), level 2 (moderate), level 3 (enhanced) per transaction volume.

TL;DR

- 3 BCEAO KYC levels: N1 (ID only), N2 (ID + selfie + address), N3 (interview + reinforced documents).

- Stack: ID OCR + face matching + NINEA/NIF check + sanctions screening.

- Tools: Smile ID, Onfido, Yoti, Veriff (pan-African).

2026 BCEAO KYC levels

LevelRequirementsTransaction cap
N1First/last name + phone + ID scan200K XOF/month
N2N1 + liveness selfie + face match + proof of address5M XOF/month
N3N2 + video interview + income + sanctions screeningUnlimited

Complete KYC architecture

`

[User uploads ID]

[OCR: extract name, ID number, birth date]

[Validate ID format per country]

[Selfie liveness check (anti-photo)]

[Face match selfie vs ID photo]

[NINEA (company) / NIF check if applicable]

[Sanctions screening (OFAC, BCEAO, UN)]

[Address: water/electricity bill photo]

[Auto approve if score >90 / manual if 70-90 / reject <70]

`

Step 1 — pick KYC provider

ProviderAfrica supportPricingNotes
Smile IDAll AF + Diaspora$0.10-0.50/checkAfrican leader
OnfidoInternational$0.50-2.00/checkEnterprise
YotiInternational$0.30-1.00/checkUK based, very good
VeriffInternational$1.00-3.00/checkHigh-end enterprise
In-houseDIYVariableIf volume >100K/month

For SME/startup: Smile ID best suited. Transparent pricing + documented APIs.

Step 2 — Smile ID implementation

`ts

import { SmileIdentityCore } from '@smileidentity/web-core';

export async function verifyKYC(userData: KYCInput) {

const sdk = new SmileIdentityCore({

partner_id: process.env.SMILE_PARTNER_ID,

api_key: process.env.SMILE_API_KEY,

});

const docResult = await sdk.documentVerification({

user_id: userData.userId,

job_id: job_${Date.now()},

country: userData.country,

id_type: 'NATIONAL_ID',

id_number: userData.cniNumber,

image: userData.cniImage,

selfie_image: userData.selfieImage,

});

if (docResult.ResultCode !== '0810') {

throw new Error(Doc verification failed: ${docResult.ResultText});

}

const matchResult = await sdk.faceMatch({

image1: userData.cniImage,

image2: userData.selfieImage,

});

if (matchResult.match_score < 0.85) {

return { status: 'PENDING_MANUAL_REVIEW', reason: 'low_match_score' };

}

const sanctionsResult = await checkSanctions(userData);

if (sanctionsResult.match) {

return { status: 'REJECTED', reason: 'sanctions_match' };

}

return {

status: 'APPROVED',

extractedData: docResult.PersonalInfo,

matchScore: matchResult.match_score,

};

}

`

Step 3 — KYC data model

`prisma

model KycVerification {

id String @id @default(cuid())

userId String @unique

level String

status String

country String

firstName String?

lastName String?

birthDate DateTime?

cniNumber String?

cniExpiryDate DateTime?

ninea String?

nif String?

cniImageUrl String?

selfieImageUrl String?

proofOfAddressUrl String?

ocrConfidence Float?

faceMatchScore Float?

livenessScore Float?

sanctionsChecked Boolean @default(false)

sanctionsMatch Boolean @default(false)

reviewedBy String?

reviewedAt DateTime?

rejectionReason String?

expiresAt DateTime

createdAt DateTime @default(now())

updatedAt DateTime @updatedAt

}

`

Step 4 — corporate NINEA / NIF verification

For KYB (Know Your Business) — corporate clients:

`ts

async function verifyNinea(ninea: string): Promise {

Need a professional website?

Kolonell builds websites that attract clients, optimized for the Sénégalese market. Free quote in 2 minutes.

const res = await fetch(https://services.dgid.sn/api/ninea/${ninea});

if (!res.ok) return null;

const data = await res.json();

return {

ninea,

companyName: data.raison_sociale,

rccm: data.rccm,

activity: data.activite,

registeredAt: new Date(data.date_inscription),

isActive: data.statut === 'ACTIF',

};

}

async function verifyNif(nif: string, country: 'CI' | 'SN'): Promise {

// CI: DGI Ivory Coast

// SN: DGID Senegal

// Different endpoints per country

}

`

Step 5 — face liveness check

Anti-printed-photo / video replay:

`ts

const livenessResult = await sdk.smartSelfieEnrollment({

user_id: userData.userId,

});

if (livenessResult.liveness_score < 0.90) {

return { status: 'REJECTED', reason: 'liveness_failed' };

}

`

Step 6 — sanctions screening

Critical for international compliance:

`ts

async function checkSanctions(userData: KYCInput) {

const results = await Promise.all([

checkOFAC(userData),

checkEUSanctions(userData),

checkUNSanctions(userData),

checkBceaoLists(userData),

]);

const matches = results.filter(r => r.match);

return {

match: matches.length > 0,

matchedLists: matches.map(m => m.list),

score: Math.max(...results.map(r => r.score)),

};

}

`

Tools: ComplyAdvantage, Refinitiv World-Check, Onfido (included).

Step 7 — human review workflow

For borderline cases (score 70-90):

`tsx

export default async function KycReviewPage({ params }) {

const verification = await getKycVerification(params.id);

return (

Review KYC: {verification.user.firstName} {verification.user.lastName}

ID scan

Extracted data

  • Last name: {verification.lastName}
  • First name: {verification.firstName}
  • ID number: {verification.cniNumber}
  • Birth date: {verification.birthDate?.toLocaleDateString()}
  • Expiry date: {verification.cniExpiryDate?.toLocaleDateString()}

Selfie + face match

Match score: {(verification.faceMatchScore * 100).toFixed(1)}%

Liveness score: {(verification.livenessScore * 100).toFixed(1)}%

);

}

`

Real case — Senegal fintech

Metric2026 value
Sign-ups/month4,200
KYC completion rate68%
Auto-approved (score >90)72%
Manual (70-90)23%
Rejected (<70)5%
Avg KYC cost$0.18/sign-up
Avg approval time12 min (auto) / 4h (manual)

FAQ

Q: KYC mandatory simple e-commerce?

A: No if seller only. If platform with wallet transactions, yes N1 minimum.

Q: Total KYC cost for startup?

A: Smile ID Pay-as-you-go: ~$0.20/check. Monthly ~$1-5K for startup 5K-25K KYC.

Q: KYC data: how long to keep?

A: 5 years after account closure (SN anti-money laundering law). Mandatory at-rest encryption.

Conclusion

KYC in 2026 = mandatory layer for any African fintech / marketplace. Modern stack (Smile ID + OCR + liveness + sanctions) = $0.20/check vs $5-15 manual. 2-4 week integration investment. BCEAO + global AML compliance ensured.

Tags:#KYC#Identity Verification#NINEA#ID#BCEAO#Africa
Share:

Mohamed Bah

Fondateur, Kolonell

Passionate about digital and entrepreneurship in Africa, Mohamed has been helping Sénégalese businesses with their digital transformation since 2020. Founder of Kolonell, he believes every SME deserves a professional and accessible online présence.