📚 DOCUMENTATION COMPLÈTE API MODULE 7 - KYC 📋 INFORMATIONS GÉNÉRALES Base URL : http://localhost:8000/api Authentification : Bearer Token (JWT) Format : JSON / Multipart Form Data 🔐 PRÉ-REQUIS 1. Obtenir un token : http POST /api/auth/login Content-Type: application/json { "email": "votre@email.com", "password": "votre_mot_de_passe" } 2. En-tĂȘtes requis : http Authorization: Bearer VOTRE_TOKEN_JWT Content-Type: application/json (ou multipart/form-data selon l'endpoint) Accept: application/json đŸ‘€ ENDPOINTS UTILISATEURS - KYC 📁 7.1 - SOUMISSION DOCUMENTS 1. SOUMETTRE UN DOCUMENT KYC http POST /kyc/documents Content-Type: multipart/form-data ParamĂštres : ParamĂštre Type Requis Description document_type string ✅ id_card, passport, driver_license, utility_bill front_image file ✅ Image recto (max 5MB) back_image file ❌ Image verso selfie_image file ❌ Selfie pour vĂ©rification faciale document_number string ❌ NumĂ©ro du document expiry_date date ❌ Date d'expiration (YYYY-MM-DD) Exemple curl : bash curl -X POST "http://localhost:8000/api/kyc/documents" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: multipart/form-data" \ -F "document_type=id_card" \ -F "document_number=123456789" \ -F "front_image=@/chemin/vers/recto.jpg" \ -F "back_image=@/chemin/verso.jpg" \ -F "selfie_image=@/chemin/selfie.jpg" RĂ©ponse rĂ©ussie (201) : json { "success": true, "message": "Document soumis avec succĂšs", "data": { "id": 1, "user_id": 1, "document_type": "id_card", "document_number": "123456789", "status": "pending", "created_at": "2025-12-05T10:30:00.000000Z", "updated_at": "2025-12-05T10:30:00.000000Z" } } 2. LISTER LES DOCUMENTS http GET /kyc/documents Exemple : bash curl -X GET "http://localhost:8000/api/kyc/documents" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" RĂ©ponse (200) : json { "success": true, "data": [ { "id": 1, "document_type": "id_card", "document_number": "123456789", "status": "pending", "created_at": "2025-12-05T10:30:00.000000Z", "updated_at": "2025-12-05T10:30:00.000000Z" } ] } 3. VOIR UN DOCUMENT SPÉCIFIQUE http GET /kyc/documents/{id} Exemple : bash curl -X GET "http://localhost:8000/api/kyc/documents/1" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" RĂ©ponse (200) : json { "success": true, "data": { "id": 1, "user_id": 1, "document_type": "id_card", "document_number": "123456789", "document_url": "http://localhost/storage/kyc-documents/user_1/id_card/front_abc123.jpg", "front_image": "http://localhost/storage/kyc-documents/user_1/id_card/front_abc123.jpg", "back_image": "http://localhost/storage/kyc-documents/user_1/id_card/back_abc123.jpg", "selfie_image": "http://localhost/storage/kyc-documents/user_1/selfie/selfie_abc123.jpg", "status": "pending", "verified_at": null, "rejection_reason": null, "expiry_date": "2028-12-31", "ip_address": "127.0.0.1", "user_agent": "Mozilla/5.0...", "created_at": "2025-12-05T10:30:00.000000Z", "updated_at": "2025-12-05T10:30:00.000000Z" } } 4. SUPPRIMER UN DOCUMENT http DELETE /kyc/documents/{id} Exemple : bash curl -X DELETE "http://localhost:8000/api/kyc/documents/1" \ -H "Authorization: Bearer YOUR_TOKEN" RĂ©ponse (200) : json { "success": true, "message": "Document supprimĂ©" } 5. RESOUMETTRE UN DOCUMENT http POST /kyc/documents/{id}/resubmit Content-Type: multipart/form-data ParamĂštres : ParamĂštre Type Requis Description front_image file ✅ Nouvelle image recto back_image file ❌ Nouvelle image verso selfie_image file ❌ Nouveau selfie reason string ✅ Raison de la resoumission Exemple : bash curl -X POST "http://localhost:8000/api/kyc/documents/1/resubmit" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: multipart/form-data" \ -F "front_image=@/chemin/nouveau-recto.jpg" \ -F "reason=L'image Ă©tait floue" RĂ©ponse (200) : json { "success": true, "message": "Document resoumis avec succĂšs", "data": { "id": 1, "status": "pending", "rejection_reason": null } } 🔍 7.2 - VÉRIFICATION IDENTITÉ 1. VÉRIFIER CNI http POST /kyc/verify/id-card Content-Type: multipart/form-data ParamĂštres : ParamĂštre Type Requis Description front_image file ✅ Recto CNI back_image file ❌ Verso CNI selfie_image file ✅ Selfie pour matching facial Exemple : bash curl -X POST "http://localhost:8000/api/kyc/verify/id-card" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: multipart/form-data" \ -F "front_image=@/chemin/cni-recto.jpg" \ -F "back_image=@/chemin/cni-verso.jpg" \ -F "selfie_image=@/chemin/selfie.jpg" RĂ©ponse (201) : json { "success": true, "message": "CNI soumise pour vĂ©rification", "data": { "id": 2, "document_type": "id_card", "status": "pending" } } 2. VÉRIFIER PASSEPORT http POST /kyc/verify/passport Content-Type: multipart/form-data ParamĂštres : ParamĂštre Type Requis Description front_image file ✅ Page info passeport selfie_image file ✅ Selfie pour matching Exemple : bash curl -X POST "http://localhost:8000/api/kyc/verify/passport" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: multipart/form-data" \ -F "front_image=@/chemin/passeport.jpg" \ -F "selfie_image=@/chemin/selfie.jpg" RĂ©ponse (201) : json { "success": true, "message": "Passeport soumis pour vĂ©rification", "data": { "id": 3, "document_type": "passport", "status": "pending" } } 3. SOUMETTRE SELFIE http POST /kyc/verify/selfie Content-Type: multipart/form-data ParamĂštres : ParamĂštre Type Requis Description selfie_image file ✅ Photo de visage document_id integer ❌ ID du document Ă  associer Exemple : bash # Selfie seul curl -X POST "http://localhost:8000/api/kyc/verify/selfie" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: multipart/form-data" \ -F "selfie_image=@/chemin/selfie.jpg" # Selfie pour document existant curl -X POST "http://localhost:8000/api/kyc/verify/selfie" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: multipart/form-data" \ -F "selfie_image=@/chemin/selfie.jpg" \ -F "document_id=1" RĂ©ponse (201) : json { "success": true, "message": "Selfie soumis avec succĂšs", "data": { "id": 4, "document_type": "selfie", "status": "pending" } } 4. STATUT KYC http GET /kyc/status Exemple : bash curl -X GET "http://localhost:8000/api/kyc/status" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" RĂ©ponse (200) : json { "success": true, "data": { "kyc_status": "pending", "verification_level": "pending_verification", "can_withdraw": false, "max_transfer": 100000, "max_withdrawal": 0, "documents": [ { "id": 1, "document_type": "id_card", "status": "pending", "created_at": "2025-12-05T10:30:00.000000Z" }, { "id": 4, "document_type": "selfie", "status": "pending", "created_at": "2025-12-05T10:35:00.000000Z" } ], "requirements": { "id_document_verified": false, "selfie_verified": false, "next_step": "wait_for_verification" } } } 5. VÉRIFIER ÉLIGIBILITÉ RETRAIT http GET /kyc/eligibility/withdrawal Exemple : bash curl -X GET "http://localhost:8000/api/kyc/eligibility/withdrawal" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" RĂ©ponse (200) : json { "success": true, "data": { "can_withdraw": false, "max_withdrawal": 0, "kyc_status": "pending", "message": "KYC requis pour les retraits" } } 6. VÉRIFIER ÉLIGIBILITÉ TRANSFERT http GET /kyc/eligibility/transfer?amount=50000 ParamĂštres : ParamĂštre Type Requis Description amount float ✅ Montant du transfert Exemple : bash curl -X GET "http://localhost:8000/api/kyc/eligibility/transfer?amount=50000" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" RĂ©ponse (200) : json { "success": true, "data": { "can_transfer": true, "requested_amount": 50000, "max_transfer": 100000, "kyc_status": "pending", "message": "Transfert autorisĂ©" } } RĂ©ponse si limite dĂ©passĂ©e : json { "success": true, "data": { "can_transfer": false, "requested_amount": 150000, "max_transfer": 100000, "kyc_status": "pending", "message": "Limite de transfert dĂ©passĂ©e selon votre niveau KYC" } } 🏱 7.3 - KYC MARCHANDS 1. SOUMETTRE RCCM http POST /kyc/merchant/business-registration Content-Type: multipart/form-data ParamĂštres : ParamĂštre Type Requis Description registration_number string ✅ NumĂ©ro RCCM business_name string ✅ Nom de l'entreprise document_image file ✅ Scan du RCCM registration_date date ❌ Date d'enregistrement business_type string ❌ Type d'entreprise activity_sector string ❌ Secteur d'activitĂ© Exemple : bash curl -X POST "http://localhost:8000/api/kyc/merchant/business-registration" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: multipart/form-data" \ -F "registration_number=RCCM-CM-2024-ABC123" \ -F "business_name=Ma SociĂ©tĂ© SARL" \ -F "document_image=@/chemin/rccm.jpg" \ -F "business_type=sarl" \ -F "activity_sector=ecommerce" RĂ©ponse (201) : json { "success": true, "message": "RCCM soumis pour vĂ©rification", "data": { "id": 5, "document_type": "business_registration", "status": "pending" } } 2. SOUMETTRE CERTIFICAT FISCAL http POST /kyc/merchant/tax-certificate Content-Type: multipart/form-data ParamĂštres : ParamĂštre Type Requis Description tax_number string ✅ NIF/NIU document_image file ✅ Scan du certificat issue_date date ❌ Date d'Ă©mission expiry_date date ❌ Date d'expiration Exemple : bash curl -X POST "http://localhost:8000/api/kyc/merchant/tax-certificate" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: multipart/form-data" \ -F "tax_number=M123456789" \ -F "document_image=@/chemin/certificat-fiscal.jpg" \ -F "issue_date=2024-01-20" RĂ©ponse (201) : json { "success": true, "message": "Certificat fiscal soumis pour vĂ©rification", "data": { "id": 6, "document_type": "tax_certificate", "status": "pending" } } 3. STATUT KYC MARCHAND http GET /kyc/merchant/status Exemple : bash curl -X GET "http://localhost:8000/api/kyc/merchant/status" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" RĂ©ponse (200) : json { "success": true, "data": { "business_registration_verified": false, "tax_certificate_verified": true, "documents": [ { "id": 5, "document_type": "business_registration", "status": "pending" }, { "id": 6, "document_type": "tax_certificate", "status": "verified" } ], "merchant_kyc_complete": false, "message": "Documents marchands en attente de vĂ©rification" } } đŸ‘šâ€đŸ’Œ ENDPOINTS ADMIN - KYC ⚠ Requiert token admin/super_admin 1. DOCUMENTS EN ATTENTE http GET /admin/kyc/pending ParamĂštres optionnels : ParamĂštre Type Description document_type string Filtrer par type date date Filtrer par date (YYYY-MM-DD) per_page integer RĂ©sultats par page (dĂ©faut: 20) Exemple : bash curl -X GET "http://localhost:8000/api/admin/kyc/pending?document_type=id_card" \ -H "Authorization: Bearer ADMIN_TOKEN" \ -H "Accept: application/json" RĂ©ponse (200) : json { "success": true, "data": { "current_page": 1, "data": [ { "id": 1, "user_id": 1, "document_type": "id_card", "status": "pending", "user": { "id": 1, "email": "john@example.com", "phone": "+237612345678" }, "created_at": "2025-12-05T10:30:00.000000Z" } ], "stats": { "total_pending": 15, "count_by_type": [ { "document_type": "id_card", "count": 8 }, { "document_type": "passport", "count": 5 } ] } } } 2. APPROUVER UN DOCUMENT http POST /admin/kyc/{id}/approve Corps optionnel : json { "notes": "Document valide, photo claire" } Exemple : bash curl -X POST "http://localhost:8000/api/admin/kyc/1/approve" \ -H "Authorization: Bearer ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "notes": "Document vĂ©rifiĂ© avec succĂšs" }' RĂ©ponse (200) : json { "success": true, "message": "Document approuvĂ©", "data": { "id": 1, "status": "verified", "verified_by": 2, "verified_at": "2025-12-05T11:00:00.000000Z" } } 3. REJETER UN DOCUMENT http POST /admin/kyc/{id}/reject Corps requis : json { "reason": "document_expired", "notes": "La CNI est expirĂ©e depuis 6 mois" } Exemple : bash curl -X POST "http://localhost:8000/api/admin/kyc/1/reject" \ -H "Authorization: Bearer ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "reason": "document_expired", "notes": "Document expirĂ©" }' RĂ©ponse (200) : json { "success": true, "message": "Document rejetĂ©", "data": { "id": 1, "status": "rejected", "rejection_reason": "document_expired" } } 4. RECHERCHER DES DOCUMENTS http GET /admin/kyc/search ParamĂštres de recherche : ParamĂštre Type Description user_id integer Filtrer par utilisateur email string Filtrer par email document_type string Filtrer par type status string Filtrer par statut date_from date Date de dĂ©but date_to date Date de fin Exemple : bash curl -X GET "http://localhost:8000/api/admin/kyc/search?status=verified&date_from=2025-12-01" \ -H "Authorization: Bearer ADMIN_TOKEN" \ -H "Accept: application/json" RĂ©ponse (200) : json { "success": true, "data": { "current_page": 1, "data": [ { "id": 1, "user_id": 1, "document_type": "id_card", "status": "verified", "user": { "id": 1, "email": "john@example.com" }, "verified_at": "2025-12-05T11:00:00.000000Z" } ] } } 5. STATISTIQUES KYC http GET /admin/kyc/stats ParamĂštres optionnels : ParamĂštre Type Description period string today, week, month, year (dĂ©faut: today) Exemple : bash curl -X GET "http://localhost:8000/api/admin/kyc/stats?period=week" \ -H "Authorization: Bearer ADMIN_TOKEN" \ -H "Accept: application/json" RĂ©ponse (200) : json { "success": true, "data": { "period": "week", "total": 150, "verified": 120, "pending": 25, "rejected": 5, "by_type": [ { "document_type": "id_card", "count": 80 }, { "document_type": "passport", "count": 50 } ], "last_7_days": [ { "date": "2025-11-29", "total": 15, "verified": 10, "pending": 5 }, { "date": "2025-11-30", "total": 20, "verified": 18, "pending": 2 } ] } } đŸ§Ș COLLECTION POSTMAN COMPLÈTE Variables d'environnement Postman : json { "base_url": "http://localhost:8000/api", "user_token": "USER_JWT_TOKEN", "admin_token": "ADMIN_JWT_TOKEN", "document_id": "", "merchant_id": "" } Flux de test utilisateur : Étape 1 : VĂ©rifier statut actuel text GET {{base_url}}/kyc/status Headers: Authorization: Bearer {{user_token}} Étape 2 : Soumettre CNI avec selfie text POST {{base_url}}/kyc/verify/id-card Headers: Authorization: Bearer {{user_token}} Content-Type: multipart/form-data Body (form-data): front_image: [FILE] (recto CNI) back_image: [FILE] (verso CNI) selfie_image: [FILE] (selfie) → Sauvegarder document_id dans les variables Étape 3 : VĂ©rifier Ă©ligibilitĂ© retrait text GET {{base_url}}/kyc/eligibility/withdrawal Headers: Authorization: Bearer {{user_token}} → Devrait retourner "can_withdraw": false Étape 4 : VĂ©rifier Ă©ligibilitĂ© transfert text GET {{base_url}}/kyc/eligibility/transfer?amount=50000 Headers: Authorization: Bearer {{user_token}} → Devrait retourner "can_transfer": true si montant ≀ limite Étape 5 : Lister documents text GET {{base_url}}/kyc/documents Headers: Authorization: Bearer {{user_token}} Flux de test admin : Étape 1 : Voir documents en attente text GET {{base_url}}/admin/kyc/pending Headers: Authorization: Bearer {{admin_token}} Étape 2 : Approuver un document text POST {{base_url}}/admin/kyc/{{document_id}}/approve Headers: Authorization: Bearer {{admin_token}} Content-Type: application/json Body: { "notes": "Document vĂ©rifiĂ©" } Étape 3 : VĂ©rifier statistiques text GET {{base_url}}/admin/kyc/stats Headers: Authorization: Bearer {{admin_token}} Flux de test marchand : Étape 1 : Soumettre RCCM text POST {{base_url}}/kyc/merchant/business-registration Headers: Authorization: Bearer {{user_token}} (marchand) Content-Type: multipart/form-data Body (form-data): registration_number: RCCM-CM-2024-TEST123 business_name: Entreprise Test document_image: [FILE] (RCCM) Étape 2 : VĂ©rifier statut marchand text GET {{base_url}}/kyc/merchant/status Headers: Authorization: Bearer {{user_token}} 🚹 CODES D'ERREUR COURANTS 400 - Bad Request : json { "success": false, "message": "Validation error", "errors": { "front_image": ["Le fichier est requis"], "document_type": ["Type de document invalide"] } } 401 - Unauthorized : json { "message": "Unauthenticated." } 403 - Forbidden : json { "success": false, "message": "VĂ©rification KYC requise pour les retraits", "kyc_status": "pending" } 404 - Not Found : json { "success": false, "message": "Document non trouvĂ©" } 422 - Unprocessable Entity : json { "success": false, "message": "Limite de transfert dĂ©passĂ©e selon votre niveau KYC" } 📊 RÈGLES KYC POUR LES TRANSACTIONS Table des limites : Statut KYC Retraits Transfert Max Transferts autorisĂ©s Sans KYC vĂ©rifiĂ© : Endpoint /withdrawals/request retourne 403 Avec KYC vĂ©rifiĂ© : Retraits autorisĂ©s jusqu'Ă  la limite quotidienne đŸ’Ÿ EXPORT POSTMAN COLLECTION json { "info": { "name": "Nelsius Pay - Module 7: KYC", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { "name": "User - Check KYC Status", "request": { "method": "GET", "header": [ { "key": "Authorization", "value": "Bearer {{user_token}}", "type": "text" } ], "url": { "raw": "{{base_url}}/kyc/status", "host": ["{{base_url}}"], "path": ["kyc", "status"] } } }, { "name": "User - Submit ID Card", "request": { "method": "POST", "header": [ { "key": "Authorization", "value": "Bearer {{user_token}}", "type": "text" }, { "key": "Content-Type", "value": "multipart/form-data", "type": "text" } ], "body": { "mode": "formdata", "formdata": [ { "key": "front_image", "type": "file", "src": "/chemin/recto.jpg" }, { "key": "back_image", "type": "file", "src": "/chemin/verso.jpg" }, { "key": "selfie_image", "type": "file", "src": "/chemin/selfie.jpg" } ] }, "url": { "raw": "{{base_url}}/kyc/verify/id-card", "host": ["{{base_url}}"], "path": ["kyc", "verify", "id-card"] } } }, { "name": "User - Check Withdrawal Eligibility", "request": { "method": "GET", "header": [ { "key": "Authorization", "value": "Bearer {{user_token}}", "type": "text" } ], "url": { "raw": "{{base_url}}/kyc/eligibility/withdrawal", "host": ["{{base_url}}"], "path": ["kyc", "eligibility", "withdrawal"] } } }, { "name": "Admin - Pending Documents", "request": { "method": "GET", "header": [ { "key": "Authorization", "value": "Bearer {{admin_token}}", "type": "text" } ], "url": { "raw": "{{base_url}}/admin/kyc/pending", "host": ["{{base_url}}"], "path": ["admin", "kyc", "pending"] } } }, { "name": "Admin - Approve Document", "request": { "method": "POST", "header": [ { "key": "Authorization", "value": "Bearer {{admin_token}}", "type": "text" }, { "key": "Content-Type", "value": "application/json", "type": "text" } ], "body": { "mode": "raw", "raw": "{\n \"notes\": \"Document vĂ©rifiĂ©\"\n}" }, "url": { "raw": "{{base_url}}/admin/kyc/{{document_id}}/approve", "host": ["{{base_url}}"], "path": ["admin", "kyc", "{{document_id}}", "approve"] } } } ] } 📝 CHECKLIST DE TEST Tests utilisateur : GET /kyc/status - Statut initial POST /kyc/verify/id-card - Soumettre CNI GET /kyc/documents - Lister documents GET /kyc/eligibility/withdrawal - VĂ©rifier avant/aprĂšs KYC GET /kyc/eligibility/transfer - Tester diffĂ©rentes sommes DELETE /kyc/documents/{id} - Supprimer document en attente POST /kyc/documents/{id}/resubmit - Resoumettre document rejetĂ© Tests admin : GET /admin/kyc/pending - Voir documents en attente POST /admin/kyc/{id}/approve - Approuver document POST /admin/kyc/{id}/reject - Rejeter document avec raison GET /admin/kyc/search - Rechercher documents GET /admin/kyc/stats - Voir statistiques Tests marchand : POST /kyc/merchant/business-registration - Soumettre RCCM POST /kyc/merchant/tax-certificate - Soumettre certificat fiscal GET /kyc/merchant/status - VĂ©rifier statut marchand 🔗 INTÉGRATION AVEC LE MODULE 6 Pour tester l'intĂ©gration : Sans KYC : bash # Tenter un retrait curl -X POST "http://localhost:8000/api/withdrawals/request" \ -H "Authorization: Bearer {{user_token}}" \ -H "Content-Type: application/json" \ -d '{"amount": 50000, "phone_number": "+237612345678", "operator": "mtn_money"}' # → Devrait retourner 403 "KYC requis" AprĂšs KYC vĂ©rifiĂ© : bash # MĂȘme requĂȘte # → Devrait retourner 201 "Code envoyĂ©"