API REFERENCE

Documentation API

Bienvenue dans la documentation officielle de VerifyPro Africa. Notre API REST vous permet d'intégrer la vérification d'identité dans n'importe quelle application web, mobile ou backend.

API Key

Authentification simple par Bearer token

< 3 secondes

Temps de traitement moyen

HTTPS only

Toutes les requêtes chiffrées TLS 1.3

URL de base : https://verifypro-africa.com/api/v1

Authentification

Toutes les requêtes doivent inclure votre clé API dans le header Authorization.

Authorization: Bearer vpa_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

⚠ Mode test : Les clés commençant par vpa_test_ ne consomment pas votre quota et retournent des données fictives réalistes.

🔒 Sécurité : Ne jamais exposer vos clés API dans votre frontend ou dans un dépôt Git. Utilisez des variables d'environnement.

Démarrage rapide

Vérifiez votre première identité en moins de 5 minutes.

1

Créez votre compte et obtenez une clé API

Inscrivez-vous sur verifypro-africa.com et créez votre première clé API depuis le dashboard.

2

Lancez votre première vérification

curl -X POST https://verifypro-africa.com/api/v1/verify \
  -H "Authorization: Bearer vpa_test_votre_cle" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "email",
    "email": "test@exemple.com"
  }'
3

Recevez le résultat

{
  "id": "vrf_abc123",
  "status": "completed",
  "type": "email",
  "overallScore": 85,
  "riskLevel": "low",
  "fraudDetected": false,
  "emailResult": {
    "valid": true,
    "disposable": false,
    "mxValid": true,
    "riskScore": 15
  },
  "completedAt": "2025-01-15T10:30:00.000Z",
  "isTestMode": true
}

Vérification d'identité

POSThttps://verifypro-africa.com/api/v1/verify

Paramètres du corps (JSON)

ChampTypeRequisDescription
typestringType de vérification (voir section Types)
documentTypestringConditionnelnational_id, passport, driving_license, residence_permit
documentImagestringConditionnelImage base64 du document (JPG/PNG, max 10 Mo)
selfieImagestringConditionnelSelfie base64 pour la comparaison faciale
videoFramesstring[]ConditionnelFrames vidéo base64 pour la détection de vivacité
emailstringConditionnelEmail à vérifier
phonestringConditionnelNuméro de téléphone avec indicatif (+229...)
firstNamestringPrénom pour la vérification AML
lastNamestringNom pour la vérification AML
countrystringCode pays ISO 3166-1 alpha-2

Exemple — KYC Complet

const response = await fetch('https://verifypro-africa.com/api/v1/verify', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer vpa_live_votre_cle',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    type: 'full-kyc',
    documentType: 'national_id',
    documentImage: documentBase64,  // string base64
    selfieImage: selfieBase64,       // string base64
    email: 'client@exemple.com',
    phone: '+229 96 00 00 00',
    country: 'BJ'
  })
});

const result = await response.json();
console.log(result.overallScore);   // 92
console.log(result.riskLevel);      // "low"
console.log(result.fraudDetected);  // false

Réponse

{
  "id": "vrf_7f3a9b2c",
  "status": "completed",
  "type": "full-kyc",
  "overallScore": 92,
  "riskLevel": "low",
  "fraudDetected": false,
  "extractedData": {
    "firstName": "KOFI",
    "lastName": "MENSAH",
    "birthDate": "15/03/1990",
    "docNumber": "BJ1234567",
    "expiryDate": "14/03/2030",
    "nationality": "BEN",
    "expired": false,
    "tamperingDetected": false,
    "confidenceScore": 0.97
  },
  "faceMatch": {
    "matched": true,
    "similarityScore": 0.94,
    "livenessConfirmed": false
  },
  "emailResult": {
    "valid": true,
    "disposable": false,
    "mxValid": true,
    "riskScore": 10
  },
  "phoneResult": {
    "valid": true,
    "country": "Bénin",
    "lineType": "mobile",
    "riskScore": 10
  },
  "amlResult": {
    "sanctionsMatch": false,
    "pepMatch": false,
    "kycRiskScore": 0
  },
  "completedAt": "2025-01-15T10:30:01.234Z",
  "isTestMode": false
}

Sessions — Lien de vérification

Générez un lien unique à envoyer à votre utilisateur. Il ouvre une page de vérification hébergée par VerifyPro Africa, sans aucune intégration frontend supplémentaire.

POSThttps://verifypro-africa.com/api/v1/sessions
GEThttps://verifypro-africa.com/api/v1/sessions?sessionId=xxx

Créer une session

// Créer un lien de vérification pour votre utilisateur
const { sessionId, verificationUrl, expiresAt } = await fetch('https://verifypro-africa.com/api/v1/sessions', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer vpa_live_xxx', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    type: 'full-kyc',
    documentType: 'national_id',
    redirectUrl: 'https://votre-app.com/verification-done',
    expiresInMinutes: 60,
    prefill: {
      email: 'client@exemple.com',
      firstName: 'Kofi'
    },
    metadata: {
      userId: 'usr_internal_123',
      orderId: 'ord_456'
    }
  })
}).then(r => r.json());

// Envoyer verificationUrl à votre utilisateur par email ou SMS
// Exemple : https://verifypro-africa.com/verify/abc123?token=xyz
console.log(verificationUrl);

Vérifier le statut

const status = await fetch(
  'https://verifypro-africa.com/api/v1/sessions?sessionId=abc123',
  { headers: { 'Authorization': 'Bearer vpa_live_xxx' } }
).then(r => r.json());

// status.status: "pending" | "viewed" | "completed" | "expired"
// status.verificationId: ID de la vérification une fois complétée

Statistiques d'utilisation

GEThttps://verifypro-africa.com/api/v1/usage?period=30
GET https://verifypro-africa.com/api/v1/usage?period=30
Authorization: Bearer vpa_live_xxx

// Réponse
{
  "plan": { "name": "pro", "displayName": "Pro", "verificationsPerMonth": 10000 },
  "currentMonth": { "used": 1234, "limit": 10000, "percentage": 12 },
  "period": {
    "days": 30,
    "total": 1234,
    "completed": 1150,
    "failed": 60,
    "fraud": 24,
    "averageScore": 88,
    "successRate": 93
  },
  "typeBreakdown": { "full-kyc": 800, "document": 300, "email": 134 },
  "dailyStats": [
    { "date": "2025-01-01", "verifications": 42, "completed": 40, "failed": 2, "fraud": 0 }
  ]
}

Webhooks

Configurez des URLs qui recevront des notifications HTTP POST signées pour chaque événement.

Événements disponibles

verification.completedVérification réussie
verification.failedVérification échouée
fraud.detectedFraude détectée
quota.warningQuota à 80%
quota.exceededQuota dépassé
document.expiredDocument expiré
session.createdSession créée
plan.expiringAbonnement expirant

Validation de la signature

// Chaque requête webhook contient ce header :
// X-VerifyPro-Signature: t=1704067200,v1=abc123...

const crypto = require('crypto');

function verifyWebhookSignature(payload, header, secret) {
  const [tsStr, sigStr] = header.split(',');
  const timestamp = tsStr.replace('t=', '');
  const signature = sigStr.replace('v1=', '');
  
  const signedPayload = `${timestamp}.${payload}`;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');
  
  // Utiliser un comparateur sécurisé pour éviter les timing attacks
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expected, 'hex')
  );
}

// Express.js
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const isValid = verifyWebhookSignature(
    req.body.toString(),
    req.headers['x-verifypro-signature'],
    process.env.VERIFYPRO_WEBHOOK_SECRET
  );
  
  if (!isValid) return res.status(401).send('Signature invalide');
  
  const event = JSON.parse(req.body);
  
  switch (event.event) {
    case 'verification.completed':
      // Activer le compte utilisateur
      await activateUser(event.data.id, event.data.extractedData);
      break;
    case 'fraud.detected':
      // Bloquer et alerter
      await blockAndAlert(event.data.id);
      break;
  }
  
  res.status(200).send('OK');
});

Types de vérification

documentGratuit+

Extraction OCR des données d'un document d'identité. Requis : documentImage, documentType.

extractedData
faceStarter+

Comparaison biométrique entre le document et un selfie. Requis : documentImage, selfieImage.

faceMatch
livenessPro+

Détection de vivacité par analyse de frames vidéo. Requis : videoFrames (min 3).

livenessResult
emailStarter+

Validation de l'email, détection des emails jetables. Requis : email.

emailResult
phoneStarter+

Validation du numéro de téléphone africain. Requis : phone.

phoneResult
amlPro+

Vérification AML/PEP dans les listes de sanctions. Requis : firstName, lastName.

amlResult
full-kycPro+

Combine document + faciale + email + téléphone + AML en une seule requête.

extractedDatafaceMatchemailResultphoneResultamlResult

Codes de réponse HTTP

CodeSignificationAction recommandée
200SuccèsTraiter la réponse normalement
201Ressource crééeRécupérer l'ID de la ressource
400Données invalidesVérifier le corps de la requête
401Clé API invalide ou manquanteVérifier votre clé API
403Permission insuffisanteVérifier les permissions de la clé ou upgrader
404Ressource introuvableVérifier l'ID fourni
409Conflit (ex: session déjà complétée)Ne pas ré-envoyer
410Ressource expiréeCréer une nouvelle session
429Quota dépassé ou rate limitAttendre ou upgrader votre plan
500Erreur serveurRéessayer après quelques secondes

SDKs & Exemples

Node.js / JavaScript

// Installation (pas encore de package npm officiel)
// Utilisez fetch ou axios directement

class VerifyProAfrica {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://verifypro-africa.com/api/v1';
  }
  
  async verify(params) {
    const res = await fetch(`${this.baseUrl}/verify`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(params)
    });
    if (!res.ok) throw new Error(`API error ${res.status}`);
    return res.json();
  }
  
  async createSession(params) {
    const res = await fetch(`${this.baseUrl}/sessions`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(params)
    });
    if (!res.ok) throw new Error(`API error ${res.status}`);
    return res.json();
  }
  
  async getUsage(period = 30) {
    const res = await fetch(`${this.baseUrl}/usage?period=${period}`, {
      headers: { 'Authorization': `Bearer ${this.apiKey}` }
    });
    return res.json();
  }
}

// Utilisation
const client = new VerifyProAfrica(process.env.VERIFYPRO_API_KEY);

const result = await client.verify({
  type: 'full-kyc',
  documentType: 'national_id',
  documentImage: base64Doc,
  selfieImage: base64Selfie,
  email: 'user@example.com'
});

Python

import requests
import base64

class VerifyProAfrica:
    BASE_URL = 'https://verifypro-africa.com/api/v1'
    
    def __init__(self, api_key: str):
        self.headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        }
    
    def verify(self, **kwargs) -> dict:
        response = requests.post(
            f'{self.BASE_URL}/verify',
            json=kwargs,
            headers=self.headers,
            timeout=30
        )
        response.raise_for_status()
        return response.json()
    
    def create_session(self, **kwargs) -> dict:
        response = requests.post(
            f'{self.BASE_URL}/sessions',
            json=kwargs,
            headers=self.headers
        )
        response.raise_for_status()
        return response.json()

# Utilisation
with open('document.jpg', 'rb') as f:
    doc_b64 = base64.b64encode(f.read()).decode()

client = VerifyProAfrica(api_key='vpa_live_xxx')
result = client.verify(
    type='document',
    document_type='national_id',
    document_image=doc_b64,
    country='BJ'
)
print(f"Score: {result['overallScore']}/100")

PHP

<?php
class VerifyProAfrica {
    private string $apiKey;
    private string $baseUrl = 'https://verifypro-africa.com/api/v1';
    
    public function __construct(string $apiKey) {
        $this->apiKey = $apiKey;
    }
    
    public function verify(array $params): array {
        $ch = curl_init($this->baseUrl . '/verify');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . $this->apiKey,
                'Content-Type: application/json'
            ],
            CURLOPT_POSTFIELDS => json_encode($params),
            CURLOPT_TIMEOUT => 30
        ]);
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }
}

// Utilisation
$client = new VerifyProAfrica($_ENV['VERIFYPRO_API_KEY']);
$docBase64 = base64_encode(file_get_contents('document.jpg'));

$result = $client->verify([
    'type' => 'full-kyc',
    'documentType' => 'national_id',
    'documentImage' => $docBase64,
    'email' => 'client@exemple.com'
]);

echo "Score: " . $result['overallScore'] . "/100\n";

Intégration React Native (Mobile)

import { launchImageLibrary, launchCamera } from 'react-native-image-picker';
import RNFS from 'react-native-fs';

async function verifyUser() {
  // 1. Sélectionner le document
  const docResult = await launchImageLibrary({ mediaType: 'photo', includeBase64: true });
  const docBase64 = docResult.assets[0].base64;
  
  // 2. Prendre le selfie
  const selfieResult = await launchCamera({ mediaType: 'photo', includeBase64: true });
  const selfieBase64 = selfieResult.assets[0].base64;
  
  // 3. Envoyer à VerifyPro Africa
  const response = await fetch('https://verifypro-africa.com/api/v1/verify', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      type: 'full-kyc',
      documentType: 'national_id',
      documentImage: 'data:image/jpeg;base64,' + docBase64,
      selfieImage: 'data:image/jpeg;base64,' + selfieBase64
    })
  });
  
  const result = await response.json();
  return result; // { status, overallScore, riskLevel, extractedData, ... }
}

Gestion des erreurs

Toutes les erreurs retournent un JSON avec le champ error :

{
  "error": "Clé API invalide",
  "message": "La clé API fournie est invalide ou révoquée.",
  "status": 401
}

Pattern de retry recommandé

async function verifyWithRetry(params, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const res = await fetch('https://verifypro-africa.com/api/v1/verify', { /* ... */ });
      
      if (res.status === 429) {
        // Rate limit — attendre et réessayer
        const delay = Math.pow(2, attempt) * 1000;
        await new Promise(r => setTimeout(r, delay));
        continue;
      }
      
      if (res.status >= 500 && attempt < maxRetries) {
        await new Promise(r => setTimeout(r, 2000 * attempt));
        continue;
      }
      
      return await res.json();
    } catch (networkError) {
      if (attempt === maxRetries) throw networkError;
      await new Promise(r => setTimeout(r, 1000 * attempt));
    }
  }
}

Sécurité

🔑 Gestion des clés API

  • Stockez vos clés dans des variables d'environnement, jamais en dur dans le code
  • Créez des clés séparées par environnement (dev, staging, production)
  • Donnez le minimum de permissions nécessaires à chaque clé
  • Faites pivoter vos clés régulièrement (tous les 90 jours)
  • Révoquez immédiatement toute clé compromise

🖼 Images et documents

  • Les images sont traitées en mémoire et jamais stockées sur nos serveurs
  • N'envoyez pas des images avec des données PII non nécessaires
  • Compressez les images (JPEG 80%) pour réduire la latence
  • Taille max recommandée : 2 Mo par image

🔒 Transport et chiffrement

  • HTTPS/TLS 1.3 obligatoire pour toutes les requêtes
  • Les webhooks sont signés HMAC-SHA256 — toujours valider la signature
  • Utilisez des timeouts courts (30s max) pour éviter les connexions pendantes

📋 Conformité

  • Respectez le RGPD : informez vos utilisateurs de la collecte de données biométriques
  • Obtenez le consentement explicite avant toute vérification d'identité
  • Conservez un journal de vérification pour vos obligations légales

Prêt à intégrer ?

500 vérifications gratuites pour commencer. Aucune carte bancaire.

Créer un compte gratuit