// docs / webhooks
Webhooks
FixWeb envoie des webhooks sortants signés pour les scans terminés, les échecs terminaux, les findings de haute sévérité, les alertes de monitoring live et les exécutions programmées. Les livraisons sont at-least-once et réessayées pendant environ 24 heures.
Configuration
Ouvre Compte → Webhooks, crée un endpoint HTTPS et stocke le secret à usage unique whsec_ côté récepteur. Les webhooks sont disponibles sur les plans payants.
- Crée un endpoint depuis Compte → Webhooks.
- Choisis les événements que FixWeb doit envoyer à cet endpoint.
- Copie le secret immédiatement; il n'est affiché qu'une fois et ne pourra ensuite qu'être renouvelé.
Événements
La surface d'événements de lancement couvre les moments que les équipes branchent souvent à la CI, aux alertes ou aux tickets:
- scan.completed — déclenché quand un scan passe à completed. Payload: id du scan, cible, mode, comptes par sévérité, lien vers le rapport.
- scan.failed — notification d'échec terminal. Payload: id du scan, phase en échec, erreur et lien vers le rapport.
- finding.created — émis pour chaque finding critical ou high. Les sévérités plus basses restent dans scan.completed par défaut pour éviter le bruit.
- monitor.alert.fired — déclenché sur le plan Unlimited quand les logs de certificate transparency, DNS ou bases de threat intelligence détectent des changements.
- schedule.run.queued — déclenché quand le scheduler met un rescan en file. Utile pour l'orchestration CI.
Format du payload
Chaque livraison utilise la même enveloppe: <code>id</code>, <code>type</code>, <code>created_at</code> et <code>data</code> spécifique à l'événement.
{
"id": "8f1c4e2a-8c3a-4b6f-9c0d-9b1e8f3c2a4d",
"type": "scan.completed",
"created_at": "2026-05-15T10:20:30.000Z",
"data": {
"scan": {
"id": "8f1c4e2a-8c3a-4b6f-9c0d-9b1e8f3c2a4d",
"target_hostname": "staging.example.com",
"mode": "passive",
"status": "completed",
"findings_count": { "critical": 0, "high": 1, "medium": 2, "low": 3, "info": 4 },
"report_url": "https://fixweb.app/dashboard/scans/8f1c4e2a-..."
}
}
}Signature
FixWeb signe le corps JSON brut exact avec HMAC-SHA-256. Vérifie la signature avant de parser ou de faire confiance aux données. Headers:
fixweb-signature: t=<timestamp>,v1=<hex hmac>fixweb-event: scan.completedfixweb-delivery: <uuid>(clé d'idempotence)
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody: string, header: string, secret: string) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const signed = `${parts.t}.${rawBody}`;
const expected = createHmac("sha256", secret).update(signed).digest("hex");
const received = Buffer.from(parts.v1 ?? "", "hex");
const calculated = Buffer.from(expected, "hex");
return received.length === calculated.length && timingSafeEqual(received, calculated);
}Retries
Toute réponse non-2xx, timeout, erreur DNS ou blocage SSRF est réessayé avec backoff exponentiel pendant environ 24 heures. Les lignes de livraison affichent le statut de réponse, un court extrait, le nombre de tentatives et l'état dead-letter dans Compte → Webhooks.
