Webhooks

GF

É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.
Un événement signale un changement COMMERCIAL, pas une écriture en base. Corriger une note interne ou un digicode ne déclenche rien : l'empreinte porte sur ce que votre site peut lire.

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);
}
Le secret de signature est DISTINCT de votre Client Secret : il ne donne accès à aucune API. Il s'affiche une seule fois, à la configuration du webhook, et se régénère depuis Réglages → Website API.

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 ?