Aller au contenu

Intégrations

Webhook

Chaque alerte en JSON signé dans votre outil, ou en message dans Slack, Discord et Teams.

Le régler

Dans Alertes, section « Où prévenir », collez l’adresse de votre outil dans « Webhook », puis cliquez sur « Tester » : Kelva envoie un message de test et dit ce que votre outil a répondu. Le webhook est inclus à partir de l’offre Solo.

Une adresse de Slack, de Discord ou de Microsoft Teams (un flux Workflows) reçoit un message mis en forme pour lui : le titre de l’alerte, sa phrase et son lien. Toute autre adresse reçoit le corps JSON ci-dessous.

Le corps du message

Un POST en JSON, à l’ouverture d’une alerte (alert.opened), à sa résolution (alert.resolved), quand l’agent d’une machine est désinstallé (machine.uninstalled) et pour « Tester » (test, sans machine ni alerte). Les clés sont en anglais, les phrases en français, comme dans l’application.

json
{  "type": "alert.opened",  "id": "0b6f3c1e-8d2a-4c55-9a51-2f1f2c9d7e10",  "timestamp": "2026-10-09T07:41:00.000Z",  "organization": { "id": "org_1", "name": "Atelier Morel" },  "url": "https://app.kelva.sh/alerts?machine=00000000-0000-4000-8000-000000000001",  "machine": {    "id": "00000000-0000-4000-8000-000000000001",    "hostname": "srv-fichiers"  },  "group": { "id": "4f0c2a9e-7d1b-4e3a-9b6c-5a2d8e1f0c3b", "name": "Cabinet Durand" },  "alert": {    "id": "00000000-0000-4000-9000-000000000001",    "rule": "disk_full",    "severity": "warning",    "title": "Disque D: à 92 %",    "text": "Le disque D: de srv-fichiers est rempli à 92 % (80 Go libres).",    "subject": "D:",    "openedAt": "2026-10-09T07:41:00.000Z",    "resolvedAt": null,    "facts": {      "mountpoint": "D:",      "usedPercent": 92,      "freeBytes": 85899345920,      "peakPercent": 92,      "unreported": false    }  }}
  • id est le même à chaque nouvel essai d’un même message : servez-vous-en pour ne le traiter qu’une fois.
  • group est le dossier de la machine, ou null quand elle n’en a pas. La clé est toujours là dans un message d’alerte ; le message de test n’en a pas, ni les messages mis en forme pour Slack, Discord et Teams.
  • machine.uninstalled a alert à null et une clé uninstall : title, text, uninstalledAt et purge (true quand la clé de la machine a aussi été révoquée). Lisez type avant alert.
  • rule vaut machine_offline, disk_full, cpu_high ou service_stopped ; severity, warning ou critical. facts donne les mesures propres à chaque règle.

La signature

Chaque message est signé selon la spécification Standard Webhooks, avec le secret affiché sous le champ du webhook (« Copier le secret »). Trois en-têtes l’accompagnent :

  • webhook-id, l’identifiant du message ;
  • webhook-timestamp, l’heure d’envoi, en secondes Unix ;
  • webhook-signature, v1, suivi de la signature.

Vérifiez le corps tel qu’il arrive, avant de le lire, avec la bibliothèque Standard Webhooks de votre langage. En JavaScript :

js
// npm install standardwebhooksimport { Webhook } from "standardwebhooks";const payload = new Webhook(process.env.KELVA_WEBHOOK_SECRET).verify(rawBody, request.headers);

En Python :

python
# pip install standardwebhooksimport osfrom standardwebhooks.webhooks import Webhookpayload = Webhook(os.environ["KELVA_WEBHOOK_SECRET"]).verify(raw_body, request.headers)

La vérification échoue si la signature ne correspond pas ou si l’heure d’envoi est à plus de 5 minutes. Sans bibliothèque : la signature est le HMAC-SHA256, en base64, de <webhook-id>.<webhook-timestamp>.<corps>, avec pour clé la partie du secret après whsec_, décodée du base64. Comparez-la en temps constant.

« Renouveler le secret » en crée un nouveau : les messages suivants sont signés avec lui. Mettez votre outil à jour dans la foulée.

Répondre

Répondez par un statut 2xx en moins de 10 secondes. Kelva réessaie après un 408, un 429 ou un 5xx, ou sans réponse ; pas après un autre statut. Il ne suit pas les redirections et n’envoie qu’à une adresse en HTTPS.