KYC (Know Your Customer) est obligatoire pour fintech, marketplaces, plateformes paiement, néo-banques. Au Sénégal et Côte d'Ivoire, en 2026, le cadre réglementaire BCEAO exige KYC progressif : niveau 1 (basique), niveau 2 (modéré), niveau 3 (renforcé) selon volume transaction.
TL;DR
- 3 niveaux KYC BCEAO : N1 (CNI seule), N2 (CNI + selfie + adresse), N3 (entretien + justificatifs renforcés).
- Stack : OCR pour CNI + face matching + check NINEA/NIF + sanctions screening.
- Outils : Smile ID, Onfido, Yoti, Veriff (panafricains).
Niveaux KYC BCEAO 2026
| Niveau | Exigences | Plafond transaction |
|---|---|---|
| N1 | Nom + prénom + numéro téléphone + CNI scan | 200K XOF/mois |
| N2 | N1 + selfie liveness + face match + justificatif domicile | 5M XOF/mois |
| N3 | N2 + entretien vidéo + revenus + sanctions screening | Illimité |
Architecture KYC complète
`
[Utilisateur upload CNI]
↓
[OCR : extraction nom, prénom, n° CNI, date naissance]
↓
[Validation format CNI selon pays]
↓
[Selfie liveness check (anti-photo)]
↓
[Face match selfie vs CNI photo]
↓
[Vérification NINEA (entreprise) / NIF si applicable]
↓
[Sanctions screening (OFAC, BCEAO, UN)]
↓
[Adresse : photo facture eau/électricité]
↓
[Approbation auto si score > 90 / manuel si 70-90 / refusé < 70]
`
Étape 1 — choisir provider KYC
| Provider | Africa support | Pricing | Notes |
|---|---|---|---|
| Smile ID | Tous pays AF + Diaspora | $0.10-0.50/check | Le leader africain |
| Onfido | International | $0.50-2.00/check | Enterprise |
| Yoti | International | $0.30-1.00/check | UK based, très bon |
| Veriff | International | $1.00-3.00/check | Enterprise haut de gamme |
| In-house | DIY | Variable | Si volume > 100K/mois |
Pour PME/startup : Smile ID le mieux adapté. Pricing transparent + APIs documentées.
Étape 2 — implementation Smile ID
`ts
// lib/kyc/smile-id.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,
});
// Étape 1 : KYC document scan (CNI)
const docResult = await sdk.documentVerification({
user_id: userData.userId,
job_id: job_${Date.now()},
country: userData.country, // SN, CI, etc.
id_type: 'NATIONAL_ID',
id_number: userData.cniNumber,
image: userData.cniImage, // base64
selfie_image: userData.selfieImage,
});
if (docResult.ResultCode !== '0810') {
throw new Error(Doc verification failed: ${docResult.ResultText});
}
// Étape 2 : Face match
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' };
}
// Étape 3 : sanctions screening (via API tiers)
const sanctionsResult = await checkSanctions(userData);
if (sanctionsResult.match) {
return { status: 'REJECTED', reason: 'sanctions_match' };
}
return {
status: 'APPROVED',
extractedData: docResult.PersonalInfo,
matchScore: matchResult.match_score,
};
}
`
Étape 3 — modèle de données KYC
`prisma
model KycVerification {
id String @id @default(cuid())
userId String @unique
level String // N1 / N2 / N3
status String // PENDING / APPROVED / REJECTED / EXPIRED
country String
// Identité
firstName String?
lastName String?
birthDate DateTime?
cniNumber String?
cniExpiryDate DateTime?
ninea String?
nif String?
// Documents (encrypted URLs)
cniImageUrl String?
selfieImageUrl String?
proofOfAddressUrl String?
// Scores
ocrConfidence Float?
faceMatchScore Float?
livenessScore Float?
// Sanctions screening
sanctionsChecked Boolean @default(false)
sanctionsMatch Boolean @default(false)
reviewedBy String? // admin user ID
reviewedAt DateTime?
rejectionReason String?
expiresAt DateTime // KYC expire après 24-36 mois selon BCEAO
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
`
Étape 4 — vérification NINEA / NIF entreprise
Pour KYB (Know Your Business) — sociétés clientes :
`ts
// lib/kyc/ninea-check.ts
Besoin d'un site web professionnel ?
Kolonell crée des sites web qui attirent des clients, optimisés pour le marché sénégalais. Devis gratuit en 2 minutes.
async function verifyNinea(ninea: string): Promise
// Sénégal : API publique DGI ou scraping (à valider légalement)
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 Côte d'Ivoire
// SN : DGID Sénégal
// Endpoints différents par pays
}
`
Étape 5 — face liveness check
Anti-photo printée / vidéo replay :
`ts
// Smile ID supporte liveness natif
const livenessResult = await sdk.smartSelfieEnrollment({
user_id: userData.userId,
// Sequence de gestes : sourire, tourner tête, fermer yeux
// SDK gère côté frontend, retourne score liveness
});
if (livenessResult.liveness_score < 0.90) {
// Trop bas = potentielle attaque
return { status: 'REJECTED', reason: 'liveness_failed' };
}
`
Étape 6 — sanctions screening
Critique pour conformité internationale :
`ts
// Listes : OFAC US, UE Sanctions, UN Sanctions, BCEAO, Interpol
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)),
};
}
`
Outils : ComplyAdvantage, Refinitiv World-Check, Onfido (inclus).
Étape 7 — workflow review humain
Pour cas borderline (score 70-90) :
`tsx
// app/admin/kyc/review/[id]/page.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)}% ✓ Approuver ✗ RejeterReview KYC : {verification.user.firstName} {verification.user.lastName}
CNI scan
Données extraites
Selfie + face match
);
}
`
Cas réel — fintech Sénégal
| Métrique | Valeur 2026 |
|---|---|
| Inscriptions/mois | 4 200 |
| Taux complétion KYC | 68 % |
| Auto-approuvé (score >90) | 72 % |
| Manuel (70-90) | 23 % |
| Rejeté (< 70) | 5 % |
| Coût KYC moyen | $0.18/inscription |
| Temps moyen approbation | 12 min (auto) / 4h (manuel) |
FAQ
Q : KYC obligatoire e-commerce simple ?
R : Non si vendeur uniquement. Si plateforme avec transactions wallets, oui niveau N1 minimum.
Q : Coût total KYC pour startup ?
R : Smile ID Pay-as-you-go : ~$0.20/check. Mensuel ~$1-5K pour startup 5K-25K KYC.
Q : Données KYC : combien de temps garder ?
R : 5 ans après fermeture compte (loi anti-blanchiment SN). Encryption at-rest obligatoire.
Conclusion
KYC en 2026 = couche obligatoire pour toute fintech / marketplace africaine. Stack moderne (Smile ID + OCR + liveness + sanctions) = $0.20/check vs $5-15 manuel. Investissement intégration 2-4 semaines. Conformité BCEAO + AML mondial assurée.
Mohamed Bah
Fondateur, Kolonell
Passionné par le digital et l'entrepreneuriat en Afrique, Mohamed accompagne les entreprises sénégalaises dans leur transformation digitale depuis 2020. Fondateur de Kolonell, il croit que chaque PME mérite une présence en ligne professionnelle et accessible.
