# Référence API Source: https://verifner.mintlify.app/api-reference/introduction Tous les endpoints de l'API VerifNer. Cette référence est générée depuis le schéma OpenAPI servi par l'API elle-même, à [`https://api.verifner.com/openapi.json`](https://api.verifner.com/openapi.json) : elle correspond toujours à ce qui tourne en production. Les descriptions des endpoints sont en anglais. Chaque page permet d'essayer l'appel : collez une clé **de test** (`vn_test_…`) dans le champ d'authentification. N'y mettez jamais une clé live. | Groupe | Pour | | ------------ | -------------------------------------------------------------------------------------- | | **Verify** | Vérifier un document depuis votre serveur, relire une vérification, accéder aux images | | **Sessions** | Ouvrir une session pour le [SDK web](/guides/web-sdk) et suivre son résultat | | **Webhooks** | Gérer vos endpoints et suivre les livraisons. Voir [Webhooks](/guides/webhooks) | Authentification : `Authorization: Bearer `. Voir [Authentification](/essentials/authentication). # Sent after every verdict and again after a human review with `final verdict` set Source: https://verifner.mintlify.app/api-reference/sent-after-every-verdict-and-again-after-a-human-review-with-`final_verdict`-set /openapi.json webhook verification.completed Headers: `VerifNer-Signature: t=,v1=.")>`, `VerifNer-Event`, `VerifNer-Delivery`. Reject timestamps older than 5 minutes. Retried 8 times over about four hours until a 2xx. # Open a session for the web SDK Source: https://verifner.mintlify.app/api-reference/sessions/open-a-session-for-the-web-sdk /openapi.json post /v1/sessions # Read a session and its outcome Source: https://verifner.mintlify.app/api-reference/sessions/read-a-session-and-its-outcome /openapi.json get /v1/sessions/{id} # Upload from the browser with the client token Source: https://verifner.mintlify.app/api-reference/sessions/upload-from-the-browser-with-the-client-token /openapi.json post /v1/sessions/{id}/verify Authenticate with `Authorization: Bearer `. CORS is open. A 422 leaves the session usable; a 201 completes it. # Get a short-lived URL to a stored image Source: https://verifner.mintlify.app/api-reference/verify/get-a-short-lived-url-to-a-stored-image /openapi.json get /v1/verifications/{id}/images/{kind} Live keys only; the URL is valid 5 minutes and every issue and view is an audit event. 410 when the image was never stored or has been purged after the retention window. # Read a verification Source: https://verifner.mintlify.app/api-reference/verify/read-a-verification /openapi.json get /v1/verifications/{id} # Verify a document, and optionally a selfie, synchronously Source: https://verifner.mintlify.app/api-reference/verify/verify-a-document-and-optionally-a-selfie-synchronously /openapi.json post /v1/verify Send an `Idempotency-Key` header to make retries safe: the same key returns the original result with `Idempotent-Replayed: true`. Test keys (`vn_test_`) run the full pipeline and never store images. # Last 50 deliveries with their state and attempts Source: https://verifner.mintlify.app/api-reference/webhooks/last-50-deliveries-with-their-state-and-attempts /openapi.json get /v1/webhooks/{id}/deliveries # List endpoints Source: https://verifner.mintlify.app/api-reference/webhooks/list-endpoints /openapi.json get /v1/webhooks # Register an endpoint Source: https://verifner.mintlify.app/api-reference/webhooks/register-an-endpoint /openapi.json post /v1/webhooks # Remove an endpoint Source: https://verifner.mintlify.app/api-reference/webhooks/remove-an-endpoint /openapi.json delete /v1/webhooks/{id} # Nouveautés Source: https://verifner.mintlify.app/changelog Les évolutions de l'API, du SDK web et de la console. * **Guide de démarrage** en haut du tableau de bord : sécuriser le compte, faire un premier essai par QR code, créer une clé de test, appeler l'API (exemples prêts à copier), ajouter un webhook, inviter l'équipe, passer en production. Chaque étape se coche d'elle-même dès qu'elle est faite. * **Nouvelle page Journaux** dans la console. **Requêtes API** : chaque appel fait avec vos clés ou par le SDK, avec le statut, la route, le code d'erreur, la clé, le mode et la durée, filtrable et exportable en CSV, conservé 90 jours. Jamais le contenu des documents. * **Journal d'audit** : qui a fait quoi dans l'organisation (connexions, décisions de revue, accès aux photos, clés, membres, paramètres), en phrases lisibles, filtrable par catégorie et exportable. Réservé au propriétaire et aux admins. Voir [Journaux](/console/logs). * **Prise en charge de la carte d'identité papier**, encore délivrée et très répandue : une seule page, sans MRZ ni date d'expiration. Elle est lue (numéro, date de délivrance, autorité), considérée valide **5 ans après sa délivrance**, et vérifiée automatiquement quand le visage concorde nettement et que la lecture est propre ; sinon, revue humaine. Ces cartes étaient jusqu'ici toujours rejetées. * **SDK web** : nouveau choix « Ancienne carte d'identité », avec un cadre vertical et sans étape verso. * **Visage** : sur la carte AES, le petit portrait « fantôme » n'empêche plus la comparaison faciale. * **Nouveau design du SDK web 0.2** : accueil avec les étapes et la durée, conseils illustrés avant chaque photo, écran « Retournez votre carte », liste de contrôle pour relire chaque photo, erreurs qui disent quoi faire. * **Plus lisible** : police Satoshi, textes plus grands, thème clair ou sombre, en français et en anglais avec un sélecteur de langue. * **Prise automatique** des photos du document dès que l'image est nette et stable ; les photos du document peuvent aussi venir de la galerie. * **Nouvelles options** : `layout`, `font` et `showVerdict`. À la fin, la personne voit le résultat (vérifiée, en cours d'examen ou non aboutie), sans les raisons ; `showVerdict: false` le masque. * **Serveur MCP** `@verifner/mcp` : Claude, Cursor et les autres agents peuvent envoyer des liens de vérification, vérifier des documents, lire les verdicts et gérer les webhooks. Voir [Serveur MCP](/guides/mcp). * **Liens de vérification hébergés** : `POST /v1/sessions` renvoie `url`, une page de capture prête à envoyer à la personne, sans intégrer le SDK. * **Nouveau modèle de lecture.** Les documents sont lus en un seul appel par un modèle de vision qui voit la photo : il lit les champs de la zone imprimée et relève lui-même les anomalies visuelles. La lecture est plus complète et plus rapide. * **MRZ vérifiée en priorité.** Quand la lecture dédiée de la MRZ passe tous les chiffres de contrôle, elle est toujours préférée. * **Anomalies de prise de vue.** Un reflet, un flou ou un cadrage imparfait coûtent des points mais ne font plus échouer le contrôle d'altération à eux seuls. La justification du contrôle donne désormais la gravité et la description de chaque anomalie. * **SDK web : recadrage automatique.** Les photos du document sont recadrées sur le cadre affiché, avec une petite marge. Pour un passeport, la page en regard et les doigts ne sont plus envoyés. * **Nouvelle session** depuis l'accueil ou la page Sessions : un QR code à faire scanner, le parcours s'ouvre sur le téléphone de la personne, le résultat arrive dans la console. Voir [Sessions QR](/console/qr-sessions). * `POST /v1/sessions` accepte `document_type` (`cni` ou `passport`) pour imposer un document. * **Découverte** (d'abord appelée « Gratuit »), sans limite de durée : 50 vérifications live par mois, puis 130 FCFA l'unité. * **Croissance** : 100 FCFA la vérification, sans abonnement. * **Entreprise** sur devis. Voir [Tarifs](/getting-started/pricing). * **Carte d'identité AES** (Niger, Mali, Burkina Faso) prise en charge, y compris les numéros de carte à 17 chiffres qui débordent de la MRZ. * **Passkeys** pour se connecter à la console sans e-mail. * Nouvelle console : barre latérale, tableau de bord, nouveau logo. * **Inscription sur invitation** pour la bêta, puis activation du mode live par VerifNer. * **Double authentification** (TOTP) et **2FA obligatoire** à l'échelle d'une organisation. * **Paramètres** : profil, sécurité, préférences, organisation et durée de rétention des images. * **Webhooks** `verification.completed` signés, avec tentatives sur environ quatre heures. * **Sessions** et **SDK web** `@verifner/web` pour la capture dans le navigateur. * **Console** : vérifications, file de revue, clés, équipe, export CSV. * **Images chiffrées** avec suppression automatique à la fin de la durée de rétention. # Les cinq contrôles Source: https://verifner.mintlify.app/concepts/checks Ce que vérifie chaque contrôle, et ce que veulent dire pass, warn, fail et skipped. Chaque contrôle a un `name`, un `status`, un `score` entre 0 et 1 (ou `null` s'il est ignoré), et une justification `evidence` en français et en anglais, à afficher telle quelle à vos équipes. ```json theme={null} { "name": "viz_mrz_consistency", "status": "pass", "score": 1, "evidence": { "fr": "6 champs sur 6 concordent", "en": "6 of 6 fields agree" } } ``` | Statut | Signification | | --------- | ------------------------------------------------------------------------------- | | `pass` | Le contrôle est satisfait | | `warn` | Un doute, qui coûte des points sans bloquer à lui seul | | `fail` | Le contrôle échoue : la vérification ne peut pas être `verified` | | `skipped` | Le contrôle n'a pas pu s'appliquer (pas de selfie, pas de MRZ) et ne compte pas | ## `mrz_checksum` La zone de lecture automatique (MRZ) contient des chiffres de contrôle calculés selon la norme OACI 9303. VerifNer recalcule chacun d'eux : numéro de document, date de naissance, date d'expiration, et le chiffre composite. * **pass** : tous les chiffres de contrôle sont justes. * **fail** : un chiffre faux, un caractère invalide ou un format inconnu. C'est un signe fort de falsification ou de document fabriqué. Score plafonné à 0,50. * **skipped** : le document n'a pas de MRZ. Le score est alors plafonné à 0,85, sauf pour la carte papier du Niger quand tous les autres contrôles sont solides. ## `expiry` La date d'expiration, lue sur la MRZ en priorité, sinon sur la zone imprimée. * **pass** : le document est valide à la date de la vérification. * **fail** : le document est expiré (score ramené à 0) ou la date est illisible (plafond à 0,50). La carte d'identité papier du Niger n'imprime pas de date d'expiration : elle est valide 5 ans après sa date de délivrance (« Fait le »), et la justification le précise. ## `viz_mrz_consistency` Compare ce qui est **imprimé** sur le document (zone visuelle) à ce qui est **encodé** dans la MRZ : nom, prénoms, date de naissance, sexe, numéro de document, date d'expiration. Un faussaire modifie souvent l'un sans l'autre. * **pass** : tous les champs concordent. * **warn** : ceux qui ont pu être lus concordent, mais certains étaient illisibles. * **fail** : un champ diverge. Si c'est le nom, les prénoms ou la date de naissance, score plafonné à 0,50. La comparaison tolère les accents, la casse et les translittérations de la MRZ (`É` devient `E`, les espaces deviennent `<`). ## `tamper` Les signes visuels relevés sur la photo du document. Chaque anomalie a un type et une gravité (faible, moyenne, élevée), et la justification reprend la description de ce qui a été vu. | Type | Nature | Effet maximal | | -------------------- | ------------------------------------------- | ------------- | | `photo_of_screen` | Photo d'un écran au lieu du document | fail | | `photocopy` | Photocopie ou impression | fail | | `font_inconsistency` | Police différente à l'intérieur d'un champ | fail | | `portrait_edge` | Bords du portrait qui semblent recollés | fail | | `field_overwritten` | Champ surchargé | fail | | `glare` | Reflet | warn | | `blur` | Flou | warn | | `partial_document` | Une partie du document hors cadre ou cachée | warn | Les anomalies de **prise de vue** (reflet, flou, cadrage) coûtent des points mais ne font jamais échouer le contrôle à elles seules : elles ne prouvent pas une altération. Si un mauvais cadrage cache la MRZ ou un champ, ce sont les autres contrôles qui échouent. Un portrait invisible ou une lisibilité très faible font aussi échouer ce contrôle. ## `face_match` Compare le portrait du document au selfie, avec un modèle de reconnaissance faciale. Le visage est détecté et recadré automatiquement sur chaque image. * **pass** : similarité de 0,45 ou plus. * **warn** : similarité entre 0,30 et 0,45. * **fail** : similarité sous 0,30 (score ramené à 0), aucun visage sur le selfie, plusieurs visages, ou portrait introuvable sur le document (plafond à 0,50). * **skipped** : aucun selfie envoyé. Le score du contrôle monte de 0 à 1 entre une similarité de 0,30 et de 0,60. Pour un bon selfie : visage de face, bien éclairé, sans lunettes ni couvre-chef qui masque le visage, une seule personne dans le cadre. Le [SDK web](/guides/web-sdk) guide la personne pour vous. # Documents pris en charge Source: https://verifner.mintlify.app/concepts/documents Les pièces d'identité lues par VerifNer, et comment bien les photographier. ## Documents Envoyez uniquement la **page d'identité** (celle avec la photo) dans `front`. Pas de `back`. La MRZ fait 2 lignes de 44 caractères en bas de la page (format TD3). La carte biométrique commune de l'Alliance des États du Sahel. Envoyez le **recto** dans `front` et le **verso** dans `back`. * Le recto porte le portrait, le nom, les prénoms, la date et le lieu de naissance, et le numéro de la carte. * Le verso porte les dates de délivrance et d'expiration, l'adresse, l'autorité, un QR code et la MRZ de 3 lignes de 30 caractères (format TD1). * Le numéro de la carte fait souvent 17 chiffres, plus que les 9 places prévues par la MRZ : il continue dans le champ suivant, comme le prévoit la norme OACI 9303. VerifNer le lit en entier. Le pays émetteur est renvoyé en code OACI à trois lettres : `NER`, `MLI` ou `BFA`. La carte papier, souvent plastifiée, encore délivrée et très répandue : une seule page, plus haute que large, avec le portrait en haut à droite, le timbre fiscal, l'empreinte et le cachet du commissariat. Envoyez **toute la page ouverte** dans `front`, sans `back`. Dans le SDK web, choisissez « Ancienne carte d'identité ». * Elle n'a **pas de MRZ**. Elle est **vérifiée automatiquement** quand tout le reste est solide : visage nettement concordant (similarité d'au moins 0,50, en pratique autour de 0,57 pour atteindre 0,90), carte non expirée, aucun signe d'altération, lecture nette avec nom, prénoms, date de naissance et numéro. Sinon, elle part en **revue humaine**. * Elle n'imprime **pas de date d'expiration**, seulement « Fait le ». VerifNer la considère valide **5 ans après la date de délivrance**, et expirée au-delà. * Le numéro est le « N° » à droite, par exemple `1234/567/21`. * Les cachets, le timbre fiscal, l'empreinte, l'écriture manuscrite et l'usure sont normaux et ne comptent pas comme des signes d'altération. Recto dans `front`, verso dans `back`. Quand la carte a une MRZ, elle est au verso sur 3 lignes. Sans MRZ, le score est plafonné à 0,85. `document_type` vaut `passport` ou `cni` (les deux modèles de carte), ou `unknown` quand le document n'a pas été reconnu. ## Formats d'image | | | | --------------------- | ----------------------------------- | | Formats | JPEG, PNG, WebP | | Taille maximale | 12 Mo par image | | Résolution conseillée | 1 600 px sur le grand côté, ou plus | Les images sont normalisées à la réception (orientation, taille). Une image trop floue est refusée avant toute lecture, avec l'erreur `422 unreadable` : demandez une nouvelle photo. ## Bien photographier un document Les quatre coins visibles, le document remplit le cadre. Pour un passeport, seulement la page d'identité. Posez le document sur une surface sombre et mate. Inclinez-le légèrement si l'hologramme brille. Téléphone immobile, mise au point faite. La MRZ doit être lisible à l'œil. Pas de photocopie, pas de photo d'écran : ce sont des signes d'altération. Le [SDK web](/guides/web-sdk) applique ces règles automatiquement : il mesure la netteté, les reflets et la luminosité en direct, et recadre la photo sur le cadre affiché. # Modes test et live Source: https://verifner.mintlify.app/concepts/modes Ce qui change entre une clé de test et une clé live. Le mode vient de la clé utilisée : `vn_test_…` ou `vn_live_…`. Le traitement est identique dans les deux cas : même lecture, mêmes contrôles, même verdict. | | Test | Live | | ---------------------- | ------------------------ | -------------------------------------------------------------- | | Traitement complet | Oui | Oui | | Images conservées | Jamais | Chiffrées, pendant la durée de rétention de votre organisation | | URL d'accès aux images | Non | Oui, `GET /v1/verifications/{id}/images/{kind}` | | Facturé | Non | Oui | | Webhooks | Oui, avec `mode: "test"` | Oui, avec `mode: "live"` | | Disponible | Dès l'inscription | Après activation par VerifNer | ## Quand utiliser le mode test * Pendant le développement et en recette. * Pour vos tests automatisés : ils ne laissent aucune image derrière eux. * Pour une démonstration. Les vérifications de test apparaissent dans la console, avec un badge **Test**, et ne comptent pas dans votre facture. ## Passer en live Les nouvelles organisations commencent en mode test. Quand votre accord pilote est signé, VerifNer active le mode live sur votre organisation. Vous pouvez alors créer des clés `vn_live_` dans la console. Tant que ce n'est pas fait, la création d'une clé live renvoie `403 live_not_enabled`. Votre code ne change pas : remplacez la clé, c'est tout. ## Facturation Seules les vérifications **live** sont facturées, par mois calendaire (heure de Niamey). Votre consommation du mois et l'estimation du montant sont dans l'onglet **Abonnement** de la console. Une vérification n'est jamais bloquée pour une raison de facturation. # Verdict et score Source: https://verifner.mintlify.app/concepts/verdict Comment VerifNer passe de cinq contrôles à un verdict. Chaque vérification produit **cinq contrôles**, un **score** entre 0 et 1, et un **verdict** déduit du score. | Verdict | Score | Ce que vous faites | | ---------- | -------------- | -------------------------------------- | | `verified` | 0,90 et plus | Poursuivre le parcours | | `review` | de 0,60 à 0,89 | Faire regarder par un humain | | `rejected` | moins de 0,60 | Refuser, ou demander un autre document | ## Les trois verdicts en détail **Valeur** : `"verified"`, score de 0,90 ou plus. Aucun contrôle n'a échoué et l'ensemble est solide. Vous pouvez poursuivre le parcours (ouverture de compte, prêt, retrait) sans intervention humaine. **Définitif** : oui. **Valeur** : `"review"`, score de 0,60 à 0,89. Un doute sérieux mais pas de fraude évidente : un contrôle en échec (qui plafonne le score sous 0,90), un visage moyennement ressemblant, une carte sans MRZ, des champs illisibles. La vérification apparaît dans la **File de revue** de la console. **Ce que vous faites** : mettez le dossier en attente. Un relecteur tranche, et un second webhook vous apporte `final_verdict`. **Valeur** : `"rejected"`, score sous 0,60. Un échec grave : MRZ falsifiée, nom ou date de naissance qui divergent, document expiré, visage différent. Refusez, ou proposez à la personne de recommencer avec un autre document. **Définitif** : oui. Si la photo était simplement ratée, faites recommencer la vérification. ```mermaid theme={null} flowchart LR S[Score] -->|"≥ 0,90"| V[verified] S -->|"0,60 à 0,89"| R[review] S -->|"< 0,60"| X[rejected] R -->|relecteur, une seule fois| F[final_verdict] ``` ## Traiter le verdict Décidez toujours sur `final_verdict` quand il existe, sinon sur `verdict` : ```javascript theme={null} function decide(v) { const verdict = v.final_verdict ?? v.verdict; switch (verdict) { case 'verified': return approve(v.id); case 'review': return hold(v.id); // un second webhook apportera final_verdict case 'rejected': return decline(v.id, v.checks.filter((c) => c.status === 'fail').map((c) => c.evidence.fr)); } } ``` Les valeurs sont en minuscules, sans espace. Le champ `status` (`VERIFIED`, `REVIEW`, `REJECTED`) répète `verdict` en majuscules pour compatibilité : préférez `verdict`. ## Comment le score est calculé Chaque contrôle donne un score entre 0 et 1, pondéré ainsi : | Contrôle | Poids | | --------------------- | ----- | | `face_match` | 35 % | | `mrz_checksum` | 20 % | | `viz_mrz_consistency` | 20 % | | `tamper` | 15 % | | `expiry` | 10 % | Un contrôle **ignoré** (`skipped`), par exemple la comparaison faciale quand vous n'envoyez pas de selfie, ne coûte rien : les poids des autres contrôles sont redistribués. Deux règles passent avant la moyenne : * **Un contrôle en échec plafonne le score sous 0,90.** Un document dont un seul contrôle échoue ne peut jamais être `verified` : au mieux, il part en revue. * **Un échec grave plafonne le score à 0,50 au plus.** Chiffre de contrôle MRZ faux, nom ou date de naissance différents entre la zone imprimée et la MRZ, date d'expiration illisible, portrait introuvable : score plafonné à 0,50. Document expiré ou visage nettement différent (similarité sous 0,30) : score ramené à 0. Dans tous ces cas, le verdict est `rejected`, quel que soit le reste. Un document sans MRZ est plafonné à 0,85, donc envoyé en revue. Seule exception : la carte d'identité papier du Niger, qui peut être `verified` quand le visage concorde nettement, qu'elle n'est pas expirée, sans signe d'altération et bien lue. Voir [Documents](/concepts/documents). Les seuils et les poids seront ajustés sur notre jeu d'évaluation de documents réels. Le principe, lui, ne changera pas : un échec grave ne peut jamais être compensé par les autres contrôles. ## La réponse ```json theme={null} { "id": "vrf_w6e35w8a9iehsf6shzuw", "status": "VERIFIED", "verdict": "verified", "score": 1, "document_type": "passport", "document": { "type": "passport", "country": "NER", "fields": { "surname": "Eriksson", "given_names": "Anna Maria", "date_of_birth": "1974-08-12", "sex": "F", "nationality": "NER", "place_of_birth": "Zinder", "document_number": "L898902C3", "date_of_issue": null, "date_of_expiry": "2031-04-15", "issuing_authority": null }, "mrz": { "lines": [ "P Les journaux ne contiennent **jamais** le corps des requêtes ou des réponses : ni image, ni champ lu sur le document. Pour l'envoi fait depuis le téléphone de la personne vérifiée, ni son adresse IP ni son navigateur ne sont conservés. Les appels sans clé valide ne sont pas journalisés. Les requêtes sont conservées **90 jours**, puis supprimées automatiquement. Accès : propriétaire, admin et développeur. ## Journal d'audit Qui a fait quoi dans votre organisation, avec l'auteur et l'heure : * **Connexions et sécurité** : connexions (lien e-mail, passkey, 2FA), sessions fermées, passkeys et double authentification. * **Équipe** : membres ajoutés, rôles modifiés, membres retirés. * **Clés API et webhooks** : créations, révocations, suppressions. * **Vérifications et photos** : décisions de revue, ouverture des photos, téléchargement par lien signé, suppression à la fin de la rétention, sessions QR, exports. * **Organisation et abonnement** : informations de l'organisation, rétention des images, 2FA obligatoire, demandes d'offre. Le journal d'audit est conservé sans limite de durée et s'exporte en CSV. Chaque export, de l'un ou l'autre registre, est lui-même inscrit au journal d'audit. Accès : propriétaire et admin. # Sessions depuis la console Source: https://verifner.mintlify.app/console/qr-sessions Vérifier quelqu'un en agence, sans rien intégrer : un QR code, un téléphone. Un conseiller peut lancer une vérification depuis la console, sans ligne de code. La personne scanne un QR code avec son propre téléphone, prend ses photos, et le résultat arrive dans la console. Sur **Accueil** ou **Sessions**, cliquez sur **Nouvelle session**. Choisissez le document (au choix, CNI ou passeport), une référence si vous voulez (numéro de dossier, par exemple) et le mode, test ou live. La personne scanne le code avec l'appareil photo de son téléphone. La page `verify.verifner.com` s'ouvre et la guide : document, puis selfie. Le lien peut aussi être copié et envoyé. La fenêtre de la console suit la session toute seule : **En attente du scan**, **Ouvert sur le téléphone**, puis **Vérification reçue** avec un lien vers le résultat. ## Bon à savoir * Le QR code est valable **15 minutes** et ne sert qu'une fois. Une fois expiré, un bouton en génère un nouveau. * Le jeton du lien est placé après le `#` de l'adresse : le navigateur ne l'envoie jamais à un serveur, et la page l'efface de la barre d'adresse. * Le mode live n'est proposé qu'une fois votre organisation activée. * Tous les membres de l'organisation peuvent créer une session. Les images suivent la durée de rétention de l'organisation. * Ces vérifications déclenchent vos webhooks comme les autres. # Revue manuelle Source: https://verifner.mintlify.app/console/review Trancher les vérifications en review depuis la console. Les vérifications au verdict `review` arrivent dans la **File de revue** de la console. Le nombre en attente s'affiche à côté du lien, dans la barre latérale. ## Qui peut relire Les rôles **propriétaire**, **admin** et **relecteur**. Les développeurs voient les vérifications mais pas les photos, et ne peuvent pas trancher. Voir [Équipe et rôles](/console/team). ## Examiner une vérification La page d'une vérification montre : * les **photos** (recto, verso, selfie), par des liens valables 5 minutes, chaque consultation étant journalisée ; * les **cinq contrôles**, avec leur statut et leur justification : c'est là qu'on voit ce qui a coûté des points ; * les **champs lus** sur le document et la **MRZ** ; * la **similarité faciale** entre le portrait et le selfie. Commencez par les contrôles en `fail` ou `warn` : leur justification dit quoi regarder sur la photo (un champ qui diverge, un reflet sur le portrait, une anomalie décrite). ## Trancher Dans le bloc **Décision humaine**, choisissez **Approuver** (`verified`) ou **Rejeter** (`rejected`), avec une note facultative (jusqu'à 2 000 caractères) qui explique votre décision. La décision : * renseigne `final_verdict` sur la vérification, sans modifier le `verdict` d'origine ; * est inscrite au journal d'audit, avec l'ancien et le nouveau verdict, l'auteur et la note ; * déclenche un second webhook `verification.completed`, avec `final_verdict` renseigné. La décision est **unique et définitive** : une fois prise, le bloc disparaît et la page montre la décision dans l'historique. Seules les vérifications `review` en reçoivent une ; une vérification `verified` ou `rejected` n'a pas de bloc de décision. ## Exporter La page **Sessions** exporte la liste filtrée (verdict, mode) en CSV, pour vos rapports de conformité. # Équipe et rôles Source: https://verifner.mintlify.app/console/team Qui peut faire quoi dans la console, et comment sécuriser les accès. ## Rôles | Action | Propriétaire | Admin | Relecteur | Développeur | | -------------------------------------------------- | :----------: | :---: | :-------: | :---------: | | Voir les vérifications et les sessions | ✓ | ✓ | ✓ | ✓ | | Créer une session QR | ✓ | ✓ | ✓ | ✓ | | Voir les photos et trancher une revue | ✓ | ✓ | ✓ | | | Gérer les clés API et les webhooks | ✓ | ✓ | | ✓ | | Consulter les requêtes API | ✓ | ✓ | | ✓ | | Consulter le journal d'audit | ✓ | ✓ | | | | Gérer l'équipe | ✓ | ✓ | | | | Demander un changement d'offre | ✓ | ✓ | | | | Modifier l'organisation et la rétention des images | ✓ | ✓ | | | ## Ajouter un membre Console → **Équipe** → saisissez l'e-mail et le rôle. La personne se connecte ensuite sur [console.verifner.com](https://console.verifner.com) avec cette adresse et reçoit son lien de connexion par e-mail. Retirer un membre lui ferme l'accès à l'organisation et le déconnecte. Ses données restent celles de l'organisation. Un membre peut appartenir à plusieurs organisations et passer de l'une à l'autre depuis la barre latérale. ## Sécuriser les connexions Connexion par empreinte, visage ou code de l'appareil, sans e-mail. Compte comme une double authentification. Jusqu'à 10 par personne, dans **Paramètres → Sécurité**. Un code à six chiffres d'une application (Google Authenticator, 1Password…) après le lien e-mail, et dix codes de secours à garder. Le propriétaire ou un admin peut **rendre la double authentification obligatoire** pour toute l'organisation (**Paramètres → Organisation**), une fois qu'il l'a lui-même activée. Les membres qui ne l'ont pas encore sont alors invités à la configurer avant d'accéder au reste de la console. La page **Paramètres → Sécurité** liste aussi vos sessions ouvertes (appareil, date) pour les fermer à distance. # Authentification Source: https://verifner.mintlify.app/essentials/authentication Clés secrètes, jetons client et bonnes pratiques. Chaque requête porte une clé dans l'en-tête `Authorization` : ```bash theme={null} Authorization: Bearer vn_live_... ``` ## Les deux types d'identifiants | Identifiant | Préfixe | Où l'utiliser | Durée de vie | | ------------ | ------------------------ | ----------------------------------- | ------------------------------------------------------ | | Clé secrète | `vn_live_` ou `vn_test_` | Uniquement sur votre serveur | Jusqu'à révocation | | Jeton client | `vn_ct_` | Dans le navigateur, avec le SDK web | 15 minutes par défaut, usage unique, une seule session | La **clé secrète** ouvre toute l'API de votre organisation. Elle ne doit jamais apparaître dans une page web, une application mobile ou un dépôt de code. Le **jeton client** est créé par votre serveur avec `POST /v1/sessions`. Il ne permet qu'une chose : envoyer les photos d'une session précise. Voir [SDK web](/guides/web-sdk). ## Créer et révoquer une clé Dans la [console](https://console.verifner.com), page **Clés API**. Les rôles **propriétaire**, **admin** et **développeur** peuvent gérer les clés. * La clé complète ne s'affiche qu'une fois, à la création. VerifNer n'en garde qu'une empreinte SHA-256 : nous ne pouvons pas vous la renvoyer. * Révoquer une clé prend effet immédiatement. Les requêtes suivantes reçoivent `401 unauthorized`. * Pour faire tourner une clé sans interruption : créez la nouvelle, déployez-la, puis révoquez l'ancienne. ## Test et live Le mode de la clé décide du comportement, pas un paramètre de requête. Une clé `vn_test_` ne conserve jamais d'image et n'est pas facturée. Une clé `vn_live_` conserve les images chiffrées pendant la durée de rétention de votre organisation. Voir [Modes test et live](/concepts/modes). ## Erreurs d'authentification ```json theme={null} { "error": { "code": "unauthorized", "message": "Unknown or revoked API key" } } ``` `401` quand la clé est absente, mal formée, inconnue ou révoquée. Voir [Erreurs](/reference/errors). # Parcours de vérification Source: https://verifner.mintlify.app/getting-started/journey Ce que vit la personne vérifiée, et ce qui se passe de votre côté à chaque étape. ## Côté personne vérifiée Avec le [SDK web](/guides/web-sdk) ou un [QR code depuis la console](/console/qr-sessions), le parcours dure moins d'une minute : Carte d'identité ou passeport. Cet écran est sauté quand vous imposez le document. Un cadre au format exact du document s'affiche. Le SDK mesure la netteté, les reflets et la lumière quatre fois par seconde, et indique quoi corriger : « rapprochez-vous », « inclinez légèrement », « trouvez plus de lumière ». Pour une carte, le recto puis le verso. Le visage dans l'ovale, de face, sans lunettes. Les photos partent, compressées pour les réseaux lents. Quelques secondes plus tard, la personne voit que sa vérification est reçue. ## Côté serveur ```mermaid theme={null} flowchart TD A[Photos reçues] --> C{Assez nette ?} C -- non --> B2[422 : reprendre la photo] C -- oui --> D[Lecture du document et comparaison faciale] D --> E[5 contrôles et score] E -->|"≥ 0,90"| V[verified] E -->|"0,60 à 0,89"| R[review] E -->|"< 0,60"| X[rejected] R --> H[Revue humaine : final_verdict] ``` 1. **Réception** : les images sont normalisées (orientation, taille) et leur empreinte calculée. Une photo trop floue est refusée tout de suite, pour que la personne la reprenne. 2. **Lecture et visage, en parallèle** : un modèle de vision lit les champs et relève les anomalies visuelles ; un lecteur dédié lit la MRZ ; un modèle de reconnaissance faciale compare le portrait au selfie. 3. **Contrôles** : cinq contrôles, un score, un verdict. Voir [Verdict et score](/concepts/verdict). 4. **Enregistrement** : le résultat est enregistré, les images chiffrées si la clé est live, et un [webhook](/guides/webhooks) part vers vos serveurs. 5. **Revue** : une vérification en `review` attend un relecteur dans la console. Sa décision déclenche un second webhook. ## Temps de traitement | Étape | Durée habituelle | | --------------------------------------------------------- | ---------------- | | Réception et contrôle de netteté | \< 0,5 s | | Lecture du document et comparaison faciale (en parallèle) | 4 à 8 s | | Contrôles et verdict | \< 50 ms | Le détail de chaque vérification est dans le champ `timings` de la réponse. # Tarifs Source: https://verifner.mintlify.app/getting-started/pricing Payez à la vérification, en FCFA. 50 vérifications offertes chaque mois pour démarrer, sans engagement. Toutes les offres donnent accès aux mêmes contrôles : lecture du document, MRZ, expiration, cohérence, altération et comparaison faciale. Seul le prix par vérification change. **0 FCFA par mois** * 50 vérifications live offertes chaque mois * Puis 130 FCFA la vérification * Sans abonnement ni limite de durée * Support par e-mail **100 FCFA la vérification** * Dès la première, sans abonnement * Facture mensuelle selon l'usage * Virement ou mobile money * Support prioritaire **Sur devis** * Dès 5 000 vérifications par mois * Tarif dégressif, dès 75 FCFA * Contrat annuel, SLA 99,9 % * Interlocuteur dédié, conservation des images sur mesure Prix hors taxes, en francs CFA (XOF). ## Ce qui est facturé Une **vérification facturable** est une vérification terminée (réponse `201`) faite avec une clé **live**. Ne sont jamais facturés : * tout ce qui passe par une clé de test ; * une photo refusée avant lecture (`422`, par exemple trop floue) ; * une requête rejouée avec la même [`Idempotency-Key`](/guides/idempotency) ; * une seconde revue humaine sur une vérification déjà comptée. Le compteur repart à zéro le 1er de chaque mois, à minuit heure de Niamey. ## Changer d'offre Dans la console, onglet **Abonnement**, le propriétaire ou un admin demande l'offre souhaitée. Nous vous recontactons, puis l'offre est activée dès réception du premier règlement ou de la signature du contrat. L'onglet affiche aussi votre consommation du mois et une estimation du montant. Aucune vérification n'est jamais bloquée pour une raison de facturation. # Sécurité et conformité Source: https://verifner.mintlify.app/getting-started/security Comment VerifNer protège les données d'identité qui lui sont confiées. AES-256-GCM, une clé différente par image. Jamais conservées avec une clé de test. Les images sont effacées à la fin de la durée de rétention que vous choisissez : 0, 7, 14 ou 30 jours. Chaque lien vers une image, chaque consultation et chaque suppression est inscrit au journal d'audit. Clés API, jetons de session et liens de connexion : seule leur empreinte SHA-256 est conservée. ## Données * **Ce qui est gardé** : le résultat de chaque vérification (verdict, contrôles, champs lus), et les images pour une clé live, pendant la durée de rétention. Voir [Données et conservation](/reference/data-retention). * **Accès aux images** : uniquement par une URL signée, valable 5 minutes, demandée avec la clé secrète ou depuis la console par un rôle autorisé à relire. * **Journaux** : nos journaux techniques ne contiennent ni les champs lus sur les documents, ni les adresses e-mail. * **Cloisonnement** : chaque organisation ne voit que ses propres vérifications, sessions et webhooks. ## Accès à la console * Connexion par lien envoyé par e-mail, valable 15 minutes et à usage unique, ou par **passkey**. * **Double authentification** (application TOTP) par membre, avec dix codes de secours. Le propriétaire ou un admin peut la **rendre obligatoire** pour toute l'organisation. * Quatre rôles : propriétaire, admin, relecteur, développeur. Voir [Équipe et rôles](/console/team). ## Transport et API * HTTPS partout. Webhooks signés en HMAC-SHA256, avec horodatage contre le rejeu. * Limitation de débit par clé et par adresse IP. * Les jetons du SDK web ne valent que pour une session, 15 minutes, un seul envoi réussi. ## Conformité VerifNer prépare sa déclaration auprès de la **HAPDP**, l'autorité de protection des données du Niger. Vous restez responsable du traitement des données de vos clients : informez la personne vérifiée et recueillez son consentement quand la loi l'exige. Pour un questionnaire de sécurité ou une revue de conformité : [contact@verifner.com](mailto:contact@verifner.com). # Prompt d'intégration Source: https://verifner.mintlify.app/guides/ai-prompt Faites faire l'intégration par votre agent IA : Claude Code, Cursor, Copilot, Windsurf. Copiez ce prompt dans votre agent de code, dans le dépôt de votre application. Il décrit tout ce qu'il faut pour intégrer VerifNer correctement, y compris les pièges (clé secrète dans le navigateur, signature des webhooks, idempotence). Cette documentation existe aussi en texte brut pour les agents : [`llms.txt`](https://docs.verifner.com/llms.txt) pour l'index, [`llms-full.txt`](https://docs.verifner.com/llms-full.txt) pour tout le contenu. ```text Prompt theme={null} Intègre la vérification d'identité VerifNer dans cette application. Documentation : https://docs.verifner.com (index pour agents : https://docs.verifner.com/llms.txt) API : https://api.verifner.com — schéma OpenAPI : https://api.verifner.com/openapi.json Contexte - VerifNer vérifie un passeport ou une carte d'identité du Niger, du Mali ou du Burkina Faso, compare le portrait à un selfie et rend un verdict : "verified" (score >= 0.90), "review" (0.60 à 0.89, un humain tranche dans la console) ou "rejected" (< 0.60). - Authentification : en-tête "Authorization: Bearer ". Clé secrète vn_test_… ou vn_live_…, lue depuis la variable d'environnement VERIFNER_API_KEY. Ne jamais l'exposer au navigateur ni la commiter. À faire 1. Côté serveur, une route qui ouvre une session : POST https://api.verifner.com/v1/sessions corps JSON : {"reference": "", "document_type": "cni" | "passport" (facultatif)} réponse 201 : {"id": "ses_…", "client_token": "vn_ct_…", "status": "pending", "expires_at": …} Renvoie seulement id et client_token au navigateur. Enregistre id avec le dossier. 2. Côté navigateur, sur une page HTTPS, monte le SDK web : VerifNer.create({ sessionId, clientToken, apiUrl: "https://api.verifner.com", lang: "fr", onComplete: (r) => { /* afficher un écran d'attente ; ne rien décider ici */ }, onError: (e) => { /* e.code : unreadable, session_expired, session_completed, network */ } }).mount(element) (ou npm install @verifner/web puis import { create } from "@verifner/web"). Appelle destroy() en quittant la page. 3. Côté serveur, un endpoint webhook (POST, corps brut, réponse 2xx en moins de 10 s) : - En-tête VerifNer-Signature: t=,v1=. - Recalcule HMAC-SHA256(secret, ".") en hex avec VERIFNER_WEBHOOK_SECRET, compare en temps constant, refuse si |maintenant - t| > 300 s. Calcule sur le corps BRUT, avant JSON.parse. - Événement : {"id": "evt_…", "type": "verification.completed", "data": {"id": "vrf_…", "mode", "verdict", "final_verdict", "score", "document_type", "document": {"fields": …}, "checks": [...]}} - Idempotent sur event.id (les livraisons sont réessayées jusqu'à 8 fois). - Décision : v = data.final_verdict ?? data.verdict. "verified" → valider le dossier, "review" → mettre en attente (un second événement avec final_verdict arrivera), "rejected" → refuser. - Retrouve le dossier via GET /v1/sessions/{id} (champ verification_id) ou en stockant data.id. 4. En secours du webhook, GET https://api.verifner.com/v1/sessions/{id} renvoie status ("pending", "completed", "expired") et result.verdict / result.final_verdict. 5. Si l'application envoie déjà des photos depuis le serveur, utilise plutôt POST /v1/verify en multipart (champs front, back pour une carte, selfie) avec un en-tête Idempotency-Key unique par tentative, et un délai client de 60 s. Le verdict est dans la réponse 201. Erreurs : corps {"error": {"code", "message"}}. 401 unauthorized, 409 session_completed / session_expired (ouvrir une nouvelle session), 422 unreadable (redemander une photo), 429 rate_limited (réessayer plus tard). Ajoute VERIFNER_API_KEY et VERIFNER_WEBHOOK_SECRET à la configuration (fichier .env d'exemple, sans valeur réelle), écris des tests pour la vérification de signature du webhook et la logique de décision, puis explique-moi comment enregistrer l'URL du webhook dans https://console.verifner.com (page Webhooks). ``` ## Après l'intégration * Testez avec une clé `vn_test_` : le traitement est complet, rien n'est conservé ni facturé. * Déclarez l'URL du webhook dans la console, page **Webhooks**, et copiez son secret dans `VERIFNER_WEBHOOK_SECRET`. * Vérifiez à la main un parcours complet sur un téléphone : la caméra ne s'ouvre qu'en HTTPS. # Idempotence Source: https://verifner.mintlify.app/guides/idempotency Réessayer une requête sans créer (ni payer) deux vérifications. Un réseau coupé au mauvais moment, et vous ne savez pas si la vérification a été faite. Avec l'en-tête `Idempotency-Key`, vous pouvez renvoyer exactement la même requête sans risque. ```bash theme={null} curl https://api.verifner.com/v1/verify \ -H "Authorization: Bearer $VERIFNER_API_KEY" \ -H "Idempotency-Key: dossier-4821-tentative-1" \ -F front=@recto.jpg -F back=@verso.jpg -F selfie=@selfie.jpg ``` * **Première fois** : la vérification est faite, réponse `201`. * **Même clé ensuite** : VerifNer ne refait rien et renvoie la vérification d'origine, avec le statut `200` et l'en-tête `Idempotent-Replayed: true`. Elle n'est pas facturée une seconde fois. ## Les règles * La clé est propre à votre **organisation**, quelle que soit la clé API qui l'envoie. Jusqu'à 255 caractères. * Elle n'expire pas. Une clé réutilisée des mois plus tard renvoie toujours la même vérification. * Le contenu de la requête n'est pas comparé : une clé déjà utilisée renvoie la vérification d'origine, même avec d'autres images. * Une requête refusée (`400`, `422`) n'enregistre rien : vous pouvez réessayer avec la même clé. ## Choisir la clé Prenez un identifiant stable de **la tentative** dans votre système, par exemple l'identifiant du dossier suivi d'un numéro de tentative. Si la personne reprend ses photos, changez de clé : sinon vous recevrez l'ancien résultat. Les sessions du SDK web n'ont pas besoin de cet en-tête : une session ne peut produire qu'une vérification. # Serveur MCP Source: https://verifner.mintlify.app/guides/mcp Vérifiez des identités depuis Claude, Cursor, Copilot, Gemini ou tout agent compatible MCP. Le serveur MCP de VerifNer met l'API à disposition des agents d'IA : ils peuvent envoyer un lien de vérification à un client, vérifier un document, lire un verdict ou déboguer un webhook, avec **votre** clé et rien de plus. « Envoie un lien de vérification à Aïssa pour le dossier 4821, puis dis-moi le verdict. » « Pourquoi mon endpoint webhook ne reçoit rien ? » L'agent lit les dernières livraisons et l'erreur. ## Clients compatibles Le MCP est un protocole ouvert : le serveur VerifNer fonctionne avec tout outil qui sait lancer un serveur MCP local, quel que soit le modèle derrière (Claude, GPT, Gemini…). | Client | Modèles | État | | --------------------------------- | -------------------- | -------------------------------------------------------------------------- | | Claude Code, Claude Desktop | Claude | Disponible | | Cursor | Claude, GPT, Gemini… | Disponible | | VS Code avec GitHub Copilot | Claude, GPT, Gemini… | Disponible | | Windsurf | Claude, GPT, Gemini… | Disponible | | Codex CLI (OpenAI) | GPT | Disponible | | Gemini CLI (Google) | Gemini | Disponible | | ChatGPT, Claude.ai, Le Chat (web) | | Bientôt : ces assistants demandent un serveur distant avec connexion OAuth | ## Installation Créez une clé dans la [console](https://console.verifner.com). Commencez par une clé **de test** : le traitement est complet, rien n'est conservé ni facturé. Node.js 20 ou plus récent doit être installé sur la machine. ```bash theme={null} claude mcp add verifner --scope user --env VERIFNER_API_KEY=vn_test_... -- npx -y @verifner/mcp ``` `--scope user` le rend disponible dans tous vos projets. Vérifiez avec `claude mcp list`, puis ouvrez une nouvelle session. Réglages → Développeur → Modifier la configuration : ```json claude_desktop_config.json theme={null} { "mcpServers": { "verifner": { "command": "npx", "args": ["-y", "@verifner/mcp"], "env": { "VERIFNER_API_KEY": "vn_test_..." } } } } ``` Redémarrez Claude Desktop. Dans `~/.cursor/mcp.json` (tous les projets) ou `.cursor/mcp.json` (un seul projet) : ```json mcp.json theme={null} { "mcpServers": { "verifner": { "command": "npx", "args": ["-y", "@verifner/mcp"], "env": { "VERIFNER_API_KEY": "vn_test_..." } } } } ``` Le serveur apparaît dans Réglages → MCP. Dans `.vscode/mcp.json`. La clé est demandée à la première utilisation et gardée par VS Code, pas écrite dans le fichier : ```json .vscode/mcp.json theme={null} { "inputs": [ { "type": "promptString", "id": "verifner-key", "description": "Clé API VerifNer", "password": true } ], "servers": { "verifner": { "type": "stdio", "command": "npx", "args": ["-y", "@verifner/mcp"], "env": { "VERIFNER_API_KEY": "${input:verifner-key}" } } } } ``` Utilisez ensuite Copilot Chat en mode **Agent**. Dans `~/.codeium/windsurf/mcp_config.json` : ```json mcp_config.json theme={null} { "mcpServers": { "verifner": { "command": "npx", "args": ["-y", "@verifner/mcp"], "env": { "VERIFNER_API_KEY": "vn_test_..." } } } } ``` Dans `~/.codex/config.toml` : ```toml config.toml theme={null} [mcp_servers.verifner] command = "npx" args = ["-y", "@verifner/mcp"] env = { VERIFNER_API_KEY = "vn_test_..." } ``` Dans `~/.gemini/settings.json` : ```json settings.json theme={null} { "mcpServers": { "verifner": { "command": "npx", "args": ["-y", "@verifner/mcp"], "env": { "VERIFNER_API_KEY": "vn_test_..." } } } } ``` Tapez `/mcp` dans Gemini CLI pour voir les outils. Tout client MCP qui lance un serveur en **stdio** : ```bash theme={null} VERIFNER_API_KEY=vn_test_... npx -y @verifner/mcp ``` Pour essayer : « Crée un lien de vérification VerifNer pour le dossier test-1 », puis, une fois la vérification faite sur le téléphone, « Quel est le verdict ? ». Avec une clé **live**, chaque vérification terminée est facturée et ses images sont conservées. Le serveur prévient l'agent de demander confirmation avant d'en lancer une, mais gardez une clé de test pour vos essais. ## Outils | Outil | Ce qu'il fait | Lecture seule | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | :-----------: | | `create_verification_link` | Ouvre une session et renvoie le **lien hébergé** à envoyer à la personne. Elle l'ouvre sur son téléphone, photographie son document et fait un selfie. | | | `get_session` | État d'une session : en attente, terminée (avec le verdict) ou expirée | ✓ | | `verify_document` | Vérifie un document à partir d'images : fichier local, URL ou `data:` | | | `get_verification` | Relit une vérification : verdict, `final_verdict`, contrôles, champs | ✓ | | `get_image_url` | Lien de 5 minutes vers une image d'une vérification live (journalisé) | ✓ | | `list_webhooks` | Vos endpoints webhook | ✓ | | `create_webhook` | Déclare un endpoint et renvoie son secret de signature, une seule fois | | | `delete_webhook` | Supprime un endpoint | | | `list_webhook_deliveries` | Les 50 dernières livraisons d'un endpoint, avec erreurs et tentatives | ✓ | Le jeton client d'une session n'est jamais montré à l'agent : il n'apparaît que dans le lien. ## Variables d'environnement | Variable | Obligatoire | Description | | ------------------ | :---------: | ------------------------------------- | | `VERIFNER_API_KEY` | ✓ | Votre clé `vn_test_…` ou `vn_live_…` | | `VERIFNER_API_URL` | | `https://api.verifner.com` par défaut | ## Données personnelles Les champs lus sur un document (nom, date de naissance, numéro) passent par l'agent, et donc par le fournisseur de son modèle. Pour des dossiers réels, préférez `create_verification_link` et `get_session`, qui ne renvoient que le verdict, ou vérifiez que votre usage de l'agent est compatible avec vos obligations de protection des données. # SDK web Source: https://verifner.mintlify.app/guides/web-sdk Une capture guidée dans le navigateur : document, selfie, envoi, verdict. Le SDK web `@verifner/web` guide la personne pas à pas : choix du document, photo du recto (et du verso pour une carte), selfie, envoi. Il mesure en direct la netteté, les reflets et la luminosité, recadre la photo sur le cadre affiché et la compresse pour les connexions lentes. Il n'a aucune dépendance et fonctionne avec ou sans framework. ## Comment ça marche ```mermaid theme={null} sequenceDiagram participant N as Navigateur participant S as Votre serveur participant V as VerifNer N->>S: La personne commence la vérification S->>V: POST /v1/sessions (clé secrète) V-->>S: id + client_token S-->>N: id + client_token N->>V: Photos, via le SDK (client_token) V-->>N: Verdict affiché V->>S: Webhook verification.completed ``` La clé secrète reste sur votre serveur. Le navigateur ne reçoit qu'un **jeton client**, valable 15 minutes, pour une seule session et un seul envoi réussi. Ne vous fiez pas au résultat renvoyé dans le navigateur pour prendre une décision : il peut être modifié. Utilisez le [webhook](/guides/webhooks) ou `GET /v1/sessions/{id}` depuis votre serveur. ## 1. Ouvrez une session depuis votre serveur ```javascript Node.js theme={null} app.post('/kyc/session', async (req, res) => { const r = await fetch('https://api.verifner.com/v1/sessions', { method: 'POST', headers: { Authorization: `Bearer ${process.env.VERIFNER_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ reference: req.user.id, // votre identifiant, renvoyé tel quel document_type: 'cni', // facultatif : sinon la personne choisit }), }); const session = await r.json(); res.json({ sessionId: session.id, clientToken: session.client_token }); }); ``` ```python Python theme={null} @app.post("/kyc/session") def open_session(): r = requests.post( "https://api.verifner.com/v1/sessions", headers={"Authorization": f"Bearer {os.environ['VERIFNER_API_KEY']}"}, json={"reference": current_user.id, "document_type": "cni"}, timeout=10, ) s = r.json() return {"sessionId": s["id"], "clientToken": s["client_token"]} ``` ```bash curl theme={null} curl https://api.verifner.com/v1/sessions \ -H "Authorization: Bearer $VERIFNER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reference": "client-4821", "document_type": "cni"}' ``` Réponse : ```json theme={null} { "id": "ses_ztkotjy7xytlxxfmhm5x", "mode": "test", "status": "pending", "reference": "client-4821", "document_type": "cni", "verification_id": null, "expires_at": "2026-09-26T10:15:00.000Z", "created_at": "2026-09-26T10:00:00.000Z", "client_token": "vn_ct_fjtsBilZpNknFBUFeKTnJpob3o3zU7JI", "url": "https://verify.verifner.com/#ses_ztkotjy7xytlxxfmhm5x.vn_ct_fjtsBilZpNknFBUFeKTnJpob3o3zU7JI" } ``` | Paramètre | Type | Description | | --------------- | ------------------- | ------------------------------------------------------------------------------------ | | `reference` | string, 200 max | Votre identifiant pour ce client ou ce parcours. Renvoyé tel quel, jamais interprété | | `document_type` | `cni` ou `passport` | Impose un document. Omis, la personne choisit | | `ttl_seconds` | entier, 60 à 3600 | Durée de validité de la session. 900 (15 minutes) par défaut | Le `client_token` n'est renvoyé qu'une fois. **Pas envie d'intégrer le SDK ?** La réponse contient aussi `url`, un lien vers notre page de capture hébergée (`https://verify.verifner.com/#…`). Envoyez-le à la personne par SMS, WhatsApp ou e-mail : elle fait tout sur son téléphone, et vous recevez le résultat par webhook comme d'habitude. Le lien ne sert qu'une fois et expire avec la session. ## 2. Montez le SDK dans votre page ```html theme={null}
```
```bash theme={null} npm install @verifner/web ``` ```javascript theme={null} import { create } from '@verifner/web'; const flow = create({ sessionId, clientToken, apiUrl: 'https://api.verifner.com', lang: 'fr', onComplete: (result) => router.push('/kyc/merci'), }); flow.mount(document.getElementById('kyc')); // En quittant la page (React : dans le cleanup d'un useEffect) flow.destroy(); ```
La page doit être servie en **HTTPS** : les navigateurs n'ouvrent la caméra que sur une origine sécurisée (ou `localhost`). ## Options | Option | Type | Défaut | Description | | -------------- | ----------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `sessionId` | string | requis | L'`id` de la session | | `clientToken` | string | requis | Le `client_token` de la session | | `apiUrl` | string | requis | `https://api.verifner.com` | | `lang` | `fr` ou `en` | `fr` | Langue de l'interface | | `documentType` | `cni` ou `passport` | | Saute l'écran de choix du document | | `selfie` | boolean | `true` | Demander un selfie | | `theme` | `light`, `dark` ou `auto` | `auto` | Suit le thème du système en `auto` | | `layout` | `card` ou `fullscreen` | `card` | `card` s'insère dans votre page ; `fullscreen` occupe tout l'écran, pour une page dédiée | | `font` | URL ou `false` | Satoshi | Police du parcours. Par défaut Satoshi, servie par verify.verifner.com ; une URL de fichier `.woff2` pour la vôtre ; `false` pour reprendre celle de votre page | | `showVerdict` | boolean | `true` | Montrer le résultat à la personne à la fin : « Identité vérifiée », « Vérification en cours » ou « Vérification non aboutie », jamais les raisons. `false` : elle voit seulement « Vérification envoyée » | | `onComplete` | `(result) => void` | | Appelé avec `{ id, verdict, score, document_type, latency_ms, created_at }` | | `onError` | `({ code, message }) => void` | | Appelé sur une erreur affichée à la personne | | `onStep` | `(step) => void` | | Chaque changement d'étape : `intro`, `document`, `prepare`, `front`, `back`, `selfie`, `review`, `uploading`, `result`, `error`. Utile pour vos statistiques | ## Erreurs dans le navigateur | `code` | Cause | Ce que voit la personne | | ---------------------------- | ----------------------------- | ------------------------------------------------------------- | | `unreadable`, `not_an_image` | Photo trop floue ou illisible | Un bouton pour reprendre la photo | | `session_expired` | Session de plus de 15 minutes | Un message : il faut recommencer. Ouvrez une nouvelle session | | `session_completed` | Session déjà utilisée | Un message : il faut recommencer | | `network` | Pas de connexion | Un bouton pour renvoyer | Une erreur `422` laisse la session utilisable : la personne peut reprendre ses photos sans que vous rouvriez de session. ## 3. Récupérez le résultat côté serveur Deux possibilités, que vous pouvez combiner : * **Webhook** (recommandé) : VerifNer appelle votre serveur à chaque verdict. Voir [Webhooks](/guides/webhooks). * **Lecture** : `GET /v1/sessions/{id}` avec la clé secrète. Quand `status` vaut `completed`, `result` contient le verdict et `verification_id` pointe vers la vérification complète. ```json theme={null} { "id": "ses_ztkotjy7xytlxxfmhm5x", "status": "completed", "reference": "client-4821", "verification_id": "vrf_w6e35w8a9iehsf6shzuw", "result": { "verdict": "verified", "final_verdict": null, "score": 0.97, "document_type": "cni" } } ``` ## Les écrans Les deux étapes, la durée (environ une minute), le consentement et le choix de la langue. Carte d'identité (AES ou ancienne) ou passeport. Sauté si vous passez `documentType`. Une illustration et quatre conseils : lumière, à plat, les quatre coins, pas de reflet. On peut aussi importer une photo de la galerie. Un cadre au format du document, des indications en direct (« Trop sombre », « Reflet », « Ne bougez plus… ») et une prise automatique dès que l'image est nette et stable. La photo prise et une liste de contrôle, pour reprendre ou valider. Pour une carte, un écran « Retournez votre carte » mène au verso. Des conseils, puis un ovale pour placer le visage. Le selfie se prend uniquement à la caméra, jamais depuis la galerie. L'avancement de l'envoi, puis le résultat : « Identité vérifiée », « Vérification en cours » (un agent examine le dossier) ou « Vérification non aboutie », sans les raisons. Chaque erreur dit quoi faire et propose de réessayer. Tout le parcours est en français et en anglais, en police Satoshi, avec des textes grands et lisibles sur téléphone, en thème clair ou sombre. ## Ce que fait le SDK pour vous * **Contrôle qualité en direct**, quatre fois par seconde : netteté, reflets, luminosité. Le bouton passe au vert quand l'image est stable et propre. * **Recadrage** sur le cadre affiché, avec une petite marge, pour que le document remplisse l'image. * **Compression** à environ 300 Ko par photo, pour les réseaux 3G. * **Repli** sur le sélecteur de fichier quand il n'y a pas de caméra. * **Styles isolés** sous `.vn-root` : le SDK ne touche pas au reste de votre page. # Webhooks Source: https://verifner.mintlify.app/guides/webhooks Recevez chaque verdict sur votre serveur, signé et renvoyé jusqu'à réception. À chaque verdict, VerifNer envoie un `POST` à vos endpoints avec l'événement `verification.completed`. Quand un humain tranche une vérification en revue, un second `verification.completed` part avec `final_verdict` renseigné. ## Enregistrer un endpoint Depuis la console, page **Webhooks**, ou par l'API : ```bash theme={null} curl https://api.verifner.com/v1/webhooks \ -H "Authorization: Bearer $VERIFNER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://votre-organisation.ne/hooks/verifner", "description": "Production"}' ``` ```json theme={null} { "id": "whe_4k2m9x7q1c5v8b3n6z0a", "url": "https://votre-organisation.ne/hooks/verifner", "description": "Production", "created_at": "2026-09-26T10:00:00.000Z", "secret": "whsec_Hq3...Zk" } ``` * L'URL doit être en **HTTPS**. `http://localhost` est accepté pour vos tests. * Le `secret` ne s'affiche qu'une fois : il sert à vérifier la signature. * Chaque endpoint reçoit les événements de votre organisation, en test comme en live. Le champ `data.mode` vous dit lequel. ## L'événement ```http theme={null} POST /hooks/verifner HTTP/1.1 Content-Type: application/json VerifNer-Event: verification.completed VerifNer-Delivery: whd_8f1c... VerifNer-Signature: t=1790416800,v1=5d41402abc4b2a76b9719d911017c592... ``` ```json theme={null} { "id": "evt_q8w2e4r6t8y0u2i4o6p8", "type": "verification.completed", "created_at": "2026-09-26T10:00:06.000Z", "data": { "id": "vrf_w6e35w8a9iehsf6shzuw", "mode": "live", "verdict": "review", "final_verdict": null, "score": 0.88, "document_type": "cni", "document": { "...": "..." }, "checks": [ "..." ], "latency_ms": 6120, "created_at": "2026-09-26T10:00:00.000Z" } } ``` `data` est la vérification complète, comme dans la réponse de `POST /v1/verify`, avec `mode` et `final_verdict` en plus. Pour retrouver votre dossier, conservez l'`id` de la vérification, ou la `reference` passée à la session et lisible avec `GET /v1/sessions/{id}`. ## Vérifier la signature L'en-tête `VerifNer-Signature` contient un horodatage `t` (secondes Unix) et `v1`, le HMAC-SHA256 en hexadécimal de la chaîne `"."`, calculé avec le secret de l'endpoint. Calculez le HMAC sur le **corps brut** reçu, avant tout parsing JSON. Re-sérialiser le JSON change les octets et la signature ne correspond plus. ```javascript Node.js (Express) theme={null} import crypto from 'node:crypto'; import express from 'express'; const app = express(); app.post('/hooks/verifner', express.raw({ type: 'application/json' }), (req, res) => { const header = req.get('VerifNer-Signature') ?? ''; const parts = Object.fromEntries(header.split(',').map((kv) => kv.trim().split('='))); const t = Number(parts.t); const body = req.body.toString('utf8'); const expected = crypto .createHmac('sha256', process.env.VERIFNER_WEBHOOK_SECRET) .update(`${t}.${body}`) .digest('hex'); const fresh = Math.abs(Date.now() / 1000 - t) <= 300; const valid = fresh && typeof parts.v1 === 'string' && parts.v1.length === expected.length && crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected)); if (!valid) return res.sendStatus(400); const event = JSON.parse(body); // Traitez l'événement de façon idempotente : event.id peut arriver plusieurs fois. handle(event).catch(console.error); res.sendStatus(200); }); ``` ```python Python (Flask) theme={null} import hashlib, hmac, json, os, time from flask import Flask, request, abort app = Flask(__name__) SECRET = os.environ["VERIFNER_WEBHOOK_SECRET"].encode() @app.post("/hooks/verifner") def verifner_hook(): header = request.headers.get("VerifNer-Signature", "") parts = dict(kv.strip().split("=", 1) for kv in header.split(",") if "=" in kv) body = request.get_data(as_text=True) try: t = int(parts.get("t", "")) except ValueError: abort(400) expected = hmac.new(SECRET, f"{t}.{body}".encode(), hashlib.sha256).hexdigest() if abs(time.time() - t) > 300 or not hmac.compare_digest(parts.get("v1", ""), expected): abort(400) event = json.loads(body) # Traitez l'événement de façon idempotente : event["id"] peut arriver plusieurs fois. handle(event) return "", 200 ``` ```php PHP theme={null} 300 || !hash_equals($expected, $parts['v1'] ?? '')) { http_response_code(400); exit; } $event = json_decode($body, true); // Traitez l'événement de façon idempotente : $event['id'] peut arriver plusieurs fois. http_response_code(200); ``` Refusez un horodatage de plus de 5 minutes : cela empêche de rejouer un ancien événement intercepté. ## Répondre et réessayer * Répondez avec un statut **2xx** en moins de **10 secondes**. Faites le travail lourd en arrière-plan. * Sans 2xx (erreur, délai dépassé, serveur injoignable), VerifNer réessaie avec un délai qui double à chaque fois, à partir d'une minute : **8 tentatives** au total, sur environ quatre heures. * Un même événement garde le même `id` à chaque tentative. Traitez-le de façon **idempotente** : ignorez un `id` déjà traité. * Les événements peuvent arriver dans le désordre. Pour une vérification donnée, un événement avec `final_verdict` renseigné est toujours le plus récent. ## Suivre les livraisons `GET /v1/webhooks/{id}/deliveries` renvoie les 50 dernières livraisons d'un endpoint, avec leur état, le nombre de tentatives et la dernière erreur. La console les affiche aussi, page **Webhooks**. Pour supprimer un endpoint : `DELETE /v1/webhooks/{id}`. # Introduction Source: https://verifner.mintlify.app/index La vérification d'identité pensée pour le Sahel : un appel, un verdict motivé, en quelques secondes. VerifNer vérifie les pièces d'identité du **Niger**, du **Mali** et du **Burkina Faso**. Envoyez la photo d'un passeport ou d'une carte, et un selfie : VerifNer lit le document, recalcule sa MRZ, cherche les signes d'altération, compare les visages et vous rend un verdict, **avec la raison de chaque décision**, en français et en anglais. **Offre Découverte.** 50 vérifications live offertes chaque mois, et des clés de test illimitées. Voir les [tarifs](/getting-started/pricing). ## En chiffres Niger, Mali, Burkina Faso Passeport, carte AES, carte papier MRZ, expiration, cohérence, altération, visage Du téléversement au verdict ## Pourquoi VerifNer Conçue pour le passeport nigérien et la carte d'identité AES, y compris ses numéros à 17 chiffres qui débordent de la MRZ. Chaque contrôle donne sa justification, lisible par un agent de conformité comme par un auditeur. Pas de boîte noire. Le SDK web contrôle la qualité avant l'envoi et compresse chaque photo autour de 300 Ko. Facture mensuelle en francs CFA, par virement ou mobile money. 100 FCFA la vérification en Croissance. ## Quatre façons d'intégrer Un conseiller affiche un QR code, le client le scanne avec son téléphone. Idéal en agence. Un parcours de capture guidé qui s'intègre dans votre page, avec ou sans framework. Vous avez déjà les photos ? Un appel `POST /v1/verify`, le verdict dans la réponse. Le serveur MCP VerifNer pour Claude, Cursor, Copilot, Windsurf, Codex et Gemini, et un [prompt d'intégration](/guides/ai-prompt) prêt à coller. ## Par où commencer ## Ce que vérifie chaque contrôle Les chiffres de contrôle de la norme OACI 9303, recalculés un par un. Le document est-il encore valide aujourd'hui ? Ce qui est imprimé correspond-il à ce qui est encodé ? Photocopie, photo d'écran, champ surchargé, portrait recollé. Le selfie est-il bien la personne du document ? `verified`, `review` ou `rejected`, et pourquoi. ## Besoin d'aide ? [contact@verifner.com](mailto:contact@verifner.com) Vos clés, vos vérifications, votre équipe. # Démarrage rapide Source: https://verifner.mintlify.app/quickstart De zéro à votre première vérification en cinq minutes. Vous codez avec un agent IA ? Collez-lui le [prompt d'intégration](/guides/ai-prompt) : il contient tout ce qu'il faut pour faire ce guide à votre place. VerifNer est en bêta sur invitation. Suivez votre lien d'invitation, renseignez votre entreprise et le responsable du compte, puis connectez-vous à la [console](https://console.verifner.com) avec le lien reçu par e-mail. Pas encore d'invitation ? Écrivez-nous à [contact@verifner.com](mailto:contact@verifner.com). Console → **Clés API** → **Nouvelle clé**, mode **Test**. Elle commence par `vn_test_` et ne s'affiche qu'une fois. ```bash theme={null} export VERIFNER_API_KEY=vn_test_... ``` Une clé de test fait tourner exactement le même traitement qu'une clé live, sans conserver d'image et sans être facturée. Choisissez selon votre cas : La personne prend elle-même ses photos, guidée par VerifNer. Votre serveur ouvre une session : ```bash theme={null} curl https://api.verifner.com/v1/sessions \ -H "Authorization: Bearer $VERIFNER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reference": "client-4821"}' ``` Puis votre page monte le SDK web avec l'`id` et le `client_token` reçus : ```html theme={null}
``` Guide complet : [SDK web](/guides/web-sdk). Pour tester sans rien intégrer, lancez une [session QR depuis la console](/console/qr-sessions).
Vous avez déjà les photos. Envoyez-les depuis votre serveur : ```bash curl theme={null} curl https://api.verifner.com/v1/verify \ -H "Authorization: Bearer $VERIFNER_API_KEY" \ -H "Idempotency-Key: client-4821-1" \ -F front=@recto.jpg \ -F back=@verso.jpg \ -F selfie=@selfie.jpg ``` ```javascript Node.js theme={null} import fs from 'node:fs'; const form = new FormData(); for (const [field, file] of [['front', 'recto.jpg'], ['back', 'verso.jpg'], ['selfie', 'selfie.jpg']]) { form.append(field, new Blob([fs.readFileSync(file)]), file); } const res = await fetch('https://api.verifner.com/v1/verify', { method: 'POST', headers: { Authorization: `Bearer ${process.env.VERIFNER_API_KEY}`, 'Idempotency-Key': 'client-4821-1' }, body: form, }); const { verdict, score, checks } = await res.json(); ``` ```python Python theme={null} import os, requests with open("recto.jpg", "rb") as f, open("verso.jpg", "rb") as b, open("selfie.jpg", "rb") as s: res = requests.post( "https://api.verifner.com/v1/verify", headers={"Authorization": f"Bearer {os.environ['VERIFNER_API_KEY']}", "Idempotency-Key": "client-4821-1"}, files={"front": f, "back": b, "selfie": s}, timeout=60, ) result = res.json() ``` Pour un passeport, envoyez seulement la page d'identité dans `front`, sans `back`. Le verdict arrive dans la réponse, en général en 5 à 10 secondes.
Déclarez un endpoint dans la console → **Webhooks**. À chaque verdict, VerifNer y envoie `verification.completed`, signé ; après une revue humaine, un second événement avec `final_verdict`. Pas besoin d'interroger l'API en boucle. | Verdict | Score | Action | | ---------- | ------------ | ------------------------------------- | | `verified` | 0,90 et plus | Poursuivre | | `review` | 0,60 à 0,89 | Attendre la décision du relecteur | | `rejected` | sous 0,60 | Refuser ou demander un autre document | Voir [Webhooks](/guides/webhooks) et [Verdict et score](/concepts/verdict). Une fois l'accord pilote signé, nous activons le mode live sur votre organisation. Créez une clé `vn_live_` et remplacez la clé de test : c'est tout. Les 50 premières vérifications live de chaque mois sont offertes.
## Cas d'échec Clé absente, mal copiée ou révoquée. Vérifiez l'en-tête `Authorization: Bearer vn_…`. Photo trop floue pour être lue. Demandez une nouvelle photo : rien n'est enregistré ni facturé. Normal pour un document limite : un relecteur tranche dans la console, et vous recevez un second webhook. Les justifications des contrôles disent ce qui a coûté des points. Une vérification peut prendre jusqu'à une dizaine de secondes. Réglez votre client HTTP à 60 secondes et réessayez avec la même `Idempotency-Key` : vous ne paierez pas deux fois. Tous les codes : [Erreurs](/reference/errors). ## Besoin d'aide ? [contact@verifner.com](mailto:contact@verifner.com) Tous les endpoints, avec essai en direct. # Données et conservation Source: https://verifner.mintlify.app/reference/data-retention Ce que VerifNer conserve, combien de temps, et comment y accéder. ## Ce qui est conservé | Donnée | Clé de test | Clé live | | ---------------------------------------------------- | ----------- | --------------------------------------------- | | Résultat (verdict, contrôles, champs lus) | Oui | Oui | | Images (recto, verso, selfie) | Jamais | Oui, chiffrées, pendant la durée de rétention | | Journal des requêtes API (métadonnées, sans contenu) | 90 jours | 90 jours | | Journal d'audit | Oui | Oui | ## Images * Chaque image est chiffrée en **AES-256-GCM** avec une clé propre à l'image, avant d'être stockée. * Elles sont supprimées automatiquement à la fin de la **durée de rétention** de votre organisation : 0, 7, 14 ou 30 jours, 30 par défaut. Le propriétaire ou un admin la règle dans **Paramètres → Organisation**. * Pour consulter une image pendant cette durée, demandez une URL signée, valable 5 minutes : ```bash theme={null} curl https://api.verifner.com/v1/verifications/vrf_w6e35w8a9iehsf6shzuw/images/front \ -H "Authorization: Bearer $VERIFNER_API_KEY" ``` ```json theme={null} { "url": "https://api.verifner.com/v1/images/…", "expires_at": "2026-09-26T10:05:00.000Z" } ``` `kind` vaut `front`, `back` ou `selfie`. Après suppression, la réponse est `410 image_gone`. Chaque URL émise et chaque consultation sont inscrites au **journal d'audit** de votre organisation, tout comme les suppressions. ## Vos obligations Vous restez responsable du traitement des données de vos clients. En particulier, informez la personne vérifiée de l'usage de ses données et recueillez son consentement quand la loi l'exige : au Niger, la loi relative à la protection des données à caractère personnel et la HAPDP. Pour toute question sur la sécurité ou la protection des données : [contact@verifner.com](mailto:contact@verifner.com). # Erreurs Source: https://verifner.mintlify.app/reference/errors Le format des erreurs et la liste des codes. Toutes les erreurs ont la même forme : ```json theme={null} { "error": { "code": "unreadable", "message": "front image too blurred (sharpness 4.2)" } } ``` Basez votre code sur `code`, qui est stable. `message` est une aide au débogage en anglais, qui peut changer. ## Codes | HTTP | `code` | Cause | Que faire | | ---- | ------------------- | ----------------------------------------------------------------------------- | ------------------------------------------- | | 400 | `invalid_request` | Paramètre manquant ou mal formé, `front` absent, image de plus de 12 Mo | Corriger la requête | | 413 | `invalid_request` | Corps JSON trop lourd (images en base64 au-delà de la limite) | Envoyer en multipart, ou réduire les images | | 401 | `unauthorized` | Clé absente, mal formée, inconnue ou révoquée ; jeton client invalide | Vérifier la clé | | 403 | `invalid_token` | Lien d'image expiré ou falsifié | Redemander une URL | | 403 | `live_not_enabled` | Création d'une clé live avant l'activation du mode live | Contacter VerifNer | | 404 | `not_found` | Vérification, session ou webhook inconnu dans votre organisation | Vérifier l'identifiant | | 409 | `session_completed` | La session a déjà produit une vérification | Ouvrir une nouvelle session | | 409 | `session_expired` | La session a dépassé sa durée de validité | Ouvrir une nouvelle session | | 410 | `image_gone` | Image jamais conservée (clé de test) ou supprimée après la durée de rétention | | | 422 | `unreadable` | Photo trop floue pour être lue | Demander une nouvelle photo | | 422 | `not_an_image` | Fichier qui n'est pas une image JPEG, PNG ou WebP | Envoyer une image | | 422 | `extraction_failed` | Le document n'a pas pu être lu | Réessayer, ou demander une meilleure photo | | 429 | `rate_limited` | Trop de requêtes | Attendre, puis réessayer | | 5xx | `internal` | Incident de notre côté | Réessayer avec la même `Idempotency-Key` | Une erreur `4xx` n'est pas facturée et n'enregistre aucune vérification. ## Réessayer Réessayez automatiquement les `429` et les `5xx`, avec un délai croissant (1 s, 2 s, 4 s…) et la même `Idempotency-Key`. Ne réessayez pas les autres `4xx` sans corriger la requête. # Limites Source: https://verifner.mintlify.app/reference/limits Débit, taille des images, durées de validité. ## Débit | Appels | Limite | | ------------------------------------------------------------ | ----------------------------------------- | | Avec une clé secrète | 120 requêtes par minute et par clé | | Envoi depuis le navigateur (`POST /v1/sessions/{id}/verify`) | 12 requêtes par minute | | Sans clé | 120 requêtes par minute et par adresse IP | Au-delà, la réponse est `429 rate_limited`. Les en-têtes `x-ratelimit-limit`, `x-ratelimit-remaining` et `x-ratelimit-reset` indiquent où vous en êtes, et `retry-after` le nombre de secondes à attendre. Besoin de plus pour un lancement ou une reprise de dossiers ? Écrivez-nous à [contact@verifner.com](mailto:contact@verifner.com). ## Images | | | | ----------------------- | ----------------------------- | | Formats | JPEG, PNG, WebP | | Taille maximale | 12 Mo par image | | Images par vérification | 3 : `front`, `back`, `selfie` | ## Durées | | | | ------------------------------------------ | ----------------------------------------------------------- | | Session du SDK web | 15 minutes par défaut, de 1 à 60 minutes avec `ttl_seconds` | | URL signée d'une image | 5 minutes | | Tolérance sur l'horodatage d'un webhook | 5 minutes | | Réponse attendue de votre endpoint webhook | 10 secondes | | Tentatives de livraison d'un webhook | 8, sur environ 4 heures | ## Temps de réponse Une vérification prend en général entre 5 et 10 secondes, lecture du document et comparaison faciale faites en parallèle. Réglez le délai d'attente de votre client HTTP à **60 secondes** au moins. Le détail par étape est dans le champ `timings` de la réponse.