Webhooks
Équipe HUSSTEER · mis à jour 2026-09-16 · 6 min
Être prévenu quand une annonce apparaît, change ou disparaît — sans interroger l'API en boucle.
Les événements
- property.published — le bien devient visible pour votre site.
- property.updated — ce que votre site peut afficher a changé.
- property.unpublished — le bien n'est plus publiable ; retirez-le.
La charge utile
Volontairement minimale : l'identifiant du bien et l'URL pour le relire. Vous obtenez ainsi toujours l'état COURANT, et aucune donnée ne voyage inutilement.
{
"id": "5c3f0a3e-...",
"type": "property.updated",
"api_version": "v1",
"created_at": "2026-09-16T10:00:00.000Z",
"data": {
"property_id": "11111111-1111-1111-1111-111111111111",
"property_url": "https://hussteer.com/api/v1/properties/11111111-1111-1111-1111-111111111111"
}
}Vérifier la signature
L'URL de votre webhook finira par se savoir : n'importe qui pourra donc vous envoyer une requête. La signature est la seule chose qui distingue Hussteer d'un inconnu. Vérifiez-la, toujours, avant de traiter quoi que ce soit.
- X-Hussteer-Signature — v1=<HMAC-SHA256 en hexadécimal>
- X-Hussteer-Timestamp — horodatage Unix, en secondes
- X-Hussteer-Event — le type de l'événement
- X-Hussteer-Delivery — l'identifiant de cet envoi (utile pour dédoublonner)
La signature couvre « <timestamp>.<corps brut> ». Utilisez le corps BRUT, tel qu'il arrive : reparser puis re-sérialiser le JSON change les octets et la vérification échouera.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifier(rawBody, headers, secret) {
const signature = headers["x-hussteer-signature"];
const timestamp = Number(headers["x-hussteer-timestamp"]);
if (!signature || !Number.isFinite(timestamp)) return false;
// Rejeu : refuser au-delà de 5 minutes d'écart.
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const attendu = "v1=" + createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`, "utf8")
.digest("hex");
const a = Buffer.from(attendu);
const b = Buffer.from(signature);
// Comparaison à temps constant : `===` renseigne sur la valeur attendue.
return a.length === b.length && timingSafeEqual(a, b);
}Répondre
- Répondez 2xx dès que vous avez ACCEPTÉ l'événement — pas quand vous l'avez traité.
- Au-delà de 10 secondes, l'envoi est considéré en échec.
- Les redirections ne sont PAS suivies : donnez l'URL finale, en HTTPS, sur le port 443.
- Un même événement peut arriver deux fois : traitez-le de façon idempotente, en vous appuyant sur X-Hussteer-Delivery.
Nouvelles tentatives
En cas d'échec, Hussteer réessaie six fois, en espaçant : 1 min, 5 min, 30 min, 2 h, 6 h, puis 12 h. Au-delà, l'envoi est abandonné et apparaît en échec dans Réglages → Website API. Une intégration révoquée ne reçoit plus rien.
Quelles URL sont acceptées
- HTTPS obligatoire, port 443 ;
- pas d'identifiants dans l'URL ;
- l'hôte doit résoudre vers une adresse publique — les réseaux privés et les points d'accès de métadonnées sont refusés, à la saisie ET à chaque envoi.
Cet article vous a-t-il été utile ?