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
| Level | Requirements | Transaction cap |
|---|---|---|
| N1 | First/last name + phone + ID scan | 200K XOF/month |
| N2 | N1 + liveness selfie + face match + proof of address | 5M XOF/month |
| N3 | N2 + video interview + income + sanctions screening | Unlimited |
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
| Provider | Africa support | Pricing | Notes |
|---|---|---|---|
| Smile ID | All AF + Diaspora | $0.10-0.50/check | African leader |
| Onfido | International | $0.50-2.00/check | Enterprise |
| Yoti | International | $0.30-1.00/check | UK based, very good |
| Veriff | International | $1.00-3.00/check | High-end enterprise |
| In-house | DIY | Variable | If 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 (
Match score: {(verification.faceMatchScore * 100).toFixed(1)}% Liveness score: {(verification.livenessScore * 100).toFixed(1)}% ✓ Approve ✗ RejectReview KYC: {verification.user.firstName} {verification.user.lastName}
ID scan
Extracted data
Selfie + face match
);
}
`
Real case — Senegal fintech
| Metric | 2026 value |
|---|---|
| Sign-ups/month | 4,200 |
| KYC completion rate | 68% |
| Auto-approved (score >90) | 72% |
| Manual (70-90) | 23% |
| Rejected (<70) | 5% |
| Avg KYC cost | $0.18/sign-up |
| Avg approval time | 12 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.
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.
