Le flux hébergé pas à pas
Guide technique : créer un parcours de vérification, rediriger l'utilisateur vers la page hébergée par Todis, confirmer le résultat côté serveur, et recevoir les webhooks signés. Les autres guides : boutiques en ligne et applis mobiles et intégration native.
Créer, rediriger, confirmer
Créer le parcours (ici, un contrôle de majorité) :
curl -X POST https://verify.todis.eu/hosted/sessions \
-H "Authorization: Bearer VOTRE_JETON" \
-H "Content-Type: application/json" \
-d '{
"check": "age_over_18",
"country_code": "FR",
"locale": "fr",
"success_url": "https://votre-boutique.example/retour-verification",
"reference": "commande-1042"
}'
Réponse : l'URL vers laquelle rediriger, et l'identifiant à conserver.
{
"session_id": "…",
"hosted_url": "https://verify.todis.eu/v/…",
"expires_at": "2026-08-19T12:34:56Z"
}
Redirigez le navigateur de votre utilisateur vers
hosted_url : Todis affiche le QR code (portefeuille
sur un autre appareil), le bouton d'ouverture (portefeuille sur le
même appareil), et gère l'attente dans la langue demandée.
success_url signifie vérification réussie,
jamais que l'utilisateur est majeur : une preuve d'âge qui
vaut false y renvoie aussi, comme tout résultat
vérifié. Lisez le résultat côté serveur
(claims.age_over_18 avec le raccourci
age_over_18) et appliquez-y votre propre règle. Au
retour sur votre success_url, votre backend confirme
(jamais sur la seule foi des paramètres d'URL, falsifiables par
l'utilisateur) :
curl https://verify.todis.eu/verify/sessions/SESSION_ID \
-H "Authorization: Bearer VOTRE_JETON"
{ "status": "verified", "claims": { "age_over_18": true } }
Le raccourci "check": "identity" demande à la place
nom, prénom, date de naissance et nationalité (le socle d'une
entrée en relation KYC), et tous les champs avancés de
l'API de session restent
disponibles. cancel_url (optionnelle) reçoit
l'utilisateur en cas d'échec. La page est aux couleurs de Todis ;
un affichage en marque blanche est à l'étude pour le plan Premium.
Le webhook, votre ceinture de sécurité
Si l'utilisateur ferme la page avant la redirection, vous restez
prévenu : ajoutez webhook_url à la création et votre
backend reçoit un POST JSON
{"event": "session.verified", "session_id": "…", "reference": "…"}
à l'issue du parcours (relances automatiques tant que vous ne
répondez pas 2xx). Chaque envoi est signé HMAC-SHA256 dans
l'en-tête X-Todis-Signature avec le
webhook_secret remis à la création :
// Node.js : vérifier la signature t=<horodatage>,v1=<hex>
const crypto = require("node:crypto");
function signatureValide(corps, entete, secret) {
const [t, v1] = entete.split(",").map((p) => p.split("=")[1]);
const attendu = crypto.createHmac("sha256", secret)
.update(t + "." + corps).digest("hex");
return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(attendu));
}
Le webhook ne contient jamais les données vérifiées : il vous dit seulement que c'est terminé, et vous lisez le résultat par l'appel authentifié ci-dessus.
Le QR dans votre page : le composant web
Si vous préférez garder l'utilisateur sur votre page plutôt que de le rediriger, un composant web encapsule la page hébergée et vous remonte les changements d'état :
<script src="https://todis.eu/js/todis-verify.js"></script>
<todis-verify hosted-url="HOSTED_URL_GENEREE_PAR_VOTRE_BACKEND"></todis-verify>
<script>
document.querySelector("todis-verify")
.addEventListener("todis:verified", () => {
// Débloquer l'étape suivante de VOTRE interface,
// puis confirmer côté serveur comme toujours.
});
</script>
Événements émis : todis:status à chaque changement,
puis todis:verified, todis:failed ou
todis:expired. La hosted_url est
toujours générée par votre backend : votre jeton de licence ne
quitte jamais votre serveur.
Les trois règles qui ne changent jamais. Le jeton
de licence reste côté serveur. Le résultat se confirme par
GET /verify/sessions/{id} authentifié, jamais sur la
foi d'un paramètre d'URL ou d'un événement navigateur. Et il n'y a
rien à stocker : pas de copie de pièce d'identité, pas de photo,
seulement la réponse vérifiée que vous avez demandée, comme
expliqué dans la FAQ.