Webhooks
Signalez les résultats de vérification à Novauth afin que vos enregistrements de session restent exacts. Chaque canal expose un endpoint webhook dédié que votre serveur appelle après avoir observé le résultat.
Fonctionnement
Novauth n'envoie pas d'événements à votre serveur. Au lieu de cela, votre backend observe le résultat de la vérification (via le SDK mobile, votre propre logique applicative ou un sondage de vérification de statut) puis envoie le résultat en POST à l'endpoint webhook du Connect Hub.
Tous les endpoints webhook nécessitent le même en-tête x-api-key utilisé pour les requêtes API standard. Retournez HTTP 200 pour accuser réception.
Verify Call
Après que votre SDK mobile a lu l'ID d'appelant entrant, signalez si les chiffres correspondaient à l'appelant attendu.
uuidstringstatus"Success" | "Failed" | "Incomplete" | "WrongNumber"{
"uuid": "01J8K2M3N4P5Q6R7S8T9U0V1W2",
"status": "Success"
}
// Possible status values:
// "Success" — caller ID matched, user verified
// "Failed" — call was not answered or no match
// "Incomplete" — call dropped before matching
// "WrongNumber" — mismatch detected# After initiating a flash call, POST the result back to Novauth:
curl -X POST https://api.novauth.com/api/v1/connect-hub/call/flash/webhook \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"uuid": "01J8K2M3N4P5Q6R7S8T9U0V1W2",
"status": "Success"
}'SMS
Une fois que votre serveur confirme que l'utilisateur a saisi le bon code OTP, signalez le statut de livraison à Novauth.
idstringstatus"delivered" | "sent" | "failed" | "undelivered"{
"id": "msg_01J8K2M3N4P5Q6R7S8T9",
"status": "delivered"
}
// Possible status values (from carrier):
// "delivered" — confirmed delivery to handset
// "sent" — dispatched to carrier, awaiting DLR
// "failed" — delivery failed (invalid number, blocked, etc.)
// "undelivered" — carrier accepted but delivery not confirmedcurl -X POST https://api.novauth.com/api/v1/connect-hub/sms/webhook \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"id": "msg_01J8K2M3N4P5Q6R7S8T9",
"status": "delivered"
}'Signalez le résultat de livraison de l'OTP WhatsApp. Seuls deux statuts sont possibles.
uuidstringstatus"Success" | "Failed"{
"uuid": "01J8K2M3N4P5Q6R7S8T9U0V1W2",
"status": "Success"
}
// Only two status values:
// "Success" — WhatsApp OTP delivered to user
// "Failed" — delivery failed (user not on WhatsApp, etc.)curl -X POST https://api.novauth.com/api/v1/connect-hub/whatsapp/webhook \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"uuid": "01J8K2M3N4P5Q6R7S8T9U0V1W2",
"status": "Success"
}'OTP Telegram
Signalez la livraison du message Telegram. Utilisez POST /check-verification-status pour la validation du code côté serveur — consultez le démarrage rapide OTP Telegram pour le flux complet.
idstringstatus"Success" | "Failed"{
"id": "01J8K2M3N4P5Q6R7S8T9U0V1W2",
"status": "Success"
}
// Only two status values:
// "Success" — Telegram message delivered
// "Failed" — delivery failed (user blocked bot, etc.)curl -X POST https://api.novauth.com/api/v1/connect-hub/telegram/webhook \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"id": "01J8K2M3N4P5Q6R7S8T9U0V1W2",
"status": "Success"
}'Telegram Gateway entrant
Lorsque vous transmettez un callback_url dans votre requête d'envoi Telegram, le Gateway de Telegram enverra des événements de statut de vérification directement en POST à cette URL. Contrairement aux autres canaux, c'est vous qui êtes le récepteur — et Telegram signe chaque requête avec HMAC-SHA256.
X-Request-TimestampSecondes d'époque Unix (entier). Rejetez si |now − timestamp| > 300.X-Request-SignatureHMAC-SHA256 encodé en hexadécimal. Vérifiez avec une comparaison à temps constant.secret = SHA256(access_token) · data = "{timestamp}\n{rawBody}" · sig = HMAC-SHA256(secret, data)// Telegram Gateway sends status updates to your callback_url
// when you provided it in the original send request.
// Payload (example):
{
"request_id": "tg_req_abc123",
"phone_number": "+14155552671",
"status": "code_valid",
"verification_status": {
"status": "code_valid",
"updated_at": 1713350400
}
}
// status values:
// "code_valid" — user entered correct code
// "code_invalid" — wrong code entered
// "code_max_attempts_exceeded" — too many attempts
// "expired" — TTL elapsed before entryimport { createHmac, timingSafeEqual } from 'node:crypto';
app.post('/telegram/gateway-callback', express.raw({ type: '*/*' }), (req, res) => {
const timestamp = req.headers['x-request-timestamp'];
const signature = req.headers['x-request-signature'];
const rawBody = req.body; // must be raw Buffer
// 1. Replay-attack guard — reject requests older than 5 minutes
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return res.status(401).json({ error: 'Request expired' });
}
// 2. Derive signing secret: SHA256 of your Telegram Gateway access token
const secret = createHmac('sha256', '')
.update(process.env.TELEGRAM_GATEWAY_TOKEN)
.digest();
// 3. Compute expected signature
const data = `${timestamp}\n${rawBody}`;
const expected = createHmac('sha256', secret).update(data).digest('hex');
// 4. Timing-safe comparison
const sigBuf = Buffer.from(signature ?? '', 'hex');
const expBuf = Buffer.from(expected, 'hex');
if (sigBuf.length !== expBuf.length || !timingSafeEqual(sigBuf, expBuf)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const payload = JSON.parse(rawBody.toString());
console.log('Telegram Gateway event:', payload.status);
res.status(200).json({ ok: true });
});Analysez toujours le corps après la vérification de la signature, et analysez-le depuis le tampon d'octets bruts — pas depuis un objet JSON pré-analysé. La re-sérialisation JSON peut modifier l'ordre des octets et invalider le HMAC.