Côté serveur : Node.js et Python
Les deux bibliothèques ont la même forme. Elles signent les requêtes, posent une clé
d’idempotence sur chaque écriture et la gardent d’un réessai à l’autre, et réessaient d’elles-mêmes
après une coupure réseau, un 429 ou un 5xx. Aucune dépendance.
Installer
Section intitulée « Installer »Node.js 20 ou plus récent.
npm install @tano-africa/nodePython 3.9 ou plus récent.
pip install tano-sdkOuvrir un dossier et une session
Section intitulée « Ouvrir un dossier et une session »import { Tano } from "@tano-africa/node";
const tano = new Tano({ apiKey: process.env.TANO_API_KEY! });
const kase = await tano.cases.create({ flow_name: "onboarding_particulier_ci", country: "CI", external_ref: "client-42",});
const session = await tano.sessions.create({ case_id: kase.id, return_url: "https://votre-site.example/verification/terminee",});// session.url : le lien du parcours, rendu une seule fois.import osfrom tano_sdk import Tano
tano = Tano(os.environ["TANO_API_KEY"])
case = tano.cases.create( flow_name="onboarding_particulier_ci", country="CI", external_ref="client-42",)
session = tano.sessions.create( case_id=case["id"], return_url="https://votre-site.example/verification/terminee",)# session["url"] : le lien du parcours, rendu une seule fois.L’environnement se déduit de la clé : une clé tano_sandbox_… travaille dans le
bac à sable, une clé tano_prod_… en production.
Lire le résultat
Section intitulée « Lire le résultat »const results = await tano.cases.results(kase.id);
switch (results.state) { case "approved": // ouvrir le compte break; case "rejected": // refus définitif : results.decision.reason_code break; case "resubmission_requested": // la personne doit reprendre results.resubmission.steps break;}results = tano.cases.results(case["id"])
if results["state"] == "approved": ... # ouvrir le compteelif results["state"] == "rejected": ... # refus définitif : results["decision"]["reason_code"]elif results["state"] == "resubmission_requested": ... # la personne doit reprendre results["resubmission"]["steps"]La liste des états et le détail des résultats sont dans la référence de l’API.
Les données personnelles (cases.data) et les images (cases.image) demandent une clé avec la
permission personal_data ; trancher un dossier en revue (cases.decide), la permission
decisions.
Vérifier les webhooks
Section intitulée « Vérifier les webhooks »Passez toujours le corps brut de la requête : un objet relu puis réécrit ne correspond plus à la signature.
import express from "express";import { verifyWebhook, WebhookSignatureError } from "@tano-africa/node";
app.post("/webhooks/tano", express.raw({ type: "application/json" }), (req, res) => { try { const event = verifyWebhook(req.body, req.headers, process.env.TANO_WEBHOOK_SECRET!); // écarter les doublons avec event.delivery_id, mettre le traitement en file res.sendStatus(204); } catch (error) { if (error instanceof WebhookSignatureError) return res.sendStatus(401); throw error; }});from flask import abort, requestfrom tano_sdk import WebhookSignatureError, verify_webhook
@app.post("/webhooks/tano")def tano_webhook(): try: event = verify_webhook( request.get_data(), request.headers, os.environ["TANO_WEBHOOK_SECRET"] ) except WebhookSignatureError: abort(401) # écarter les doublons avec event["delivery_id"], mettre le traitement en file return "", 204Les erreurs
Section intitulée « Les erreurs »Une erreur de l’API lève TanoApiError, avec son code : c’est lui qu’il faut tester, il ne
change pas (voir la liste des erreurs). TanoConnectionError signale une
absence de réponse après les réessais ; rejouer avec la même clé d’idempotence est alors sans
risque.
© 2026 Qalebasse · Tano, plateforme de confiance numériquetano.africaDemander un accès[email protected]