Documentation / Webhooks sortants

Webhooks sortants

Un webhook sortant est un message que le panneau envoie à une adresse de votre choix lorsqu'il arrive quelque chose à un compte d'hébergement, afin qu'un autre système puisse réagir : votre propre facturation, un canal de discussion, un tableur, un script de provisionnement.

Les webhooks sont disponibles pour les administrateurs et les revendeurs. Un administrateur est informé de tous les comptes. Un revendeur n'est informé que des comptes qui lui appartiennent. Les clients et les jetons d'API ne peuvent pas en créer : les webhooks se configurent dans le panneau lui-même, dans la session de la personne, afin qu'un jeton divulgué ne puisse jamais devenir un flux permanent des événements du panneau.

En ajouter un

Ouvrez la page de sécurité de votre compte (administrateur : Sécurité ; revendeur : Sécurité de la connexion) et repérez Webhooks sous les jetons d'API.

  1. Saisissez l'adresse, par exemple https://example.com/hooks/panel.
  2. Cochez les événements souhaités.
  3. Appuyez sur Ajouter un webhook.

Le panneau affiche une seule fois un secret de signature (il commence par whsec_). Copiez-le maintenant. Il est stocké chiffré et ne peut plus être affiché ; si vous le perdez, supprimez le webhook et ajoutez-en un nouveau.

Chaque personne peut avoir au plus 10 webhooks.

L'adresse

  • Elle doit commencer par https://. Le simple http:// est refusé, car l'appel transporte des informations de compte.
  • Elle ne doit contenir ni nom d'utilisateur ni mot de passe. Vérifiez plutôt la signature.
  • Elle peut comporter au plus 500 caractères.
  • Elle doit se trouver sur l'Internet public. Les adresses de ce serveur, d'un réseau privé, de l'interface de bouclage ou de la plage de métadonnées du fournisseur cloud sont refusées, à la fois lorsque vous enregistrez l'adresse et de nouveau au moment où le panneau se connecte (un nom d'hôte qui pointerait plus tard vers une adresse privée ne fonctionne donc pas non plus).
  • Les redirections ne sont pas suivies. Donnez l'adresse finale.

Les événements

Événement Envoyé quand
account.created Un compte d'hébergement est créé
account.suspended Un compte est suspendu
account.unsuspended Un compte suspendu est rétabli
account.deleted Un compte est supprimé
account.activity Autre activité sur un compte

Un bouton Test sur chaque webhook envoie un événement appelé ping, pour que vous voyiez si votre adresse répond. Un seul test peut être en attente à la fois.

Ce qui est envoyé

Chaque appel est un POST HTTP avec un corps JSON :

{
  "event": "account.created",
  "at": "2026-10-23T08:15:00Z",
  "account": { "id": 42, "username": "example", "domain": "example.com" },
  "detail": "short text about what happened"
}

at est une heure UTC. L'événement ping a la forme {"event":"ping","at":"…","webhook_id":7}.

Ces en-têtes accompagnent chaque appel :

En-tête Signification
X-Nimbopanel-Event Le nom de l'événement, par exemple account.created
X-Nimbopanel-Delivery Un numéro qui identifie cette remise. Une nouvelle tentative de la même remise garde le même numéro : servez-vous-en pour ignorer les doublons
X-Nimbopanel-Timestamp Le moment où l'appel a été signé, en secondes Unix
X-Nimbopanel-Signature sha256= suivi de la signature (ci-dessous)
Content-Type application/json
User-Agent Nimbopanel-Webhook/1

Vérifier la signature

N'importe qui peut envoyer une requête à votre adresse. La signature vous permet de savoir qu'un appel vient bien de votre panneau.

La signature est un HMAC-SHA256, en hexadécimal, de l'horodatage, d'un point et du corps brut exactement tel que reçu, calculé avec votre secret de signature :

X-Nimbopanel-Signature == "sha256=" + hex( HMAC_SHA256( secret, X-Nimbopanel-Timestamp + "." + body ) )

Vérifiez-la dans cet ordre :

  1. Calculez la valeur ci-dessus à partir du corps brut de la requête (avant tout traitement ou remise en forme du JSON).
  2. Comparez-la à l'en-tête avec une comparaison en temps constant.
  3. Rejetez l'appel si l'horodatage s'écarte de plus de 5 minutes de votre horloge. Cela empêche quelqu'un de rejouer un ancien appel.
  4. Servez-vous de X-Nimbopanel-Delivery pour ignorer une remise déjà traitée.

Exemple en PHP :

$body = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_NIMBOPANEL_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_NIMBOPANEL_SIGNATURE'] ?? '';
$want = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $secret);
if (!hash_equals($want, $sig) || abs(time() - (int) $ts) > 300) {
    http_response_code(401);
    exit;
}

Exemple en Node.js :

const crypto = require('crypto');
function valid(rawBody, headers, secret) {
  const ts = headers['x-nimbopanel-timestamp'] || '';
  const want = 'sha256=' + crypto.createHmac('sha256', secret).update(ts + '.' + rawBody).digest('hex');
  const got = headers['x-nimbopanel-signature'] || '';
  return got.length === want.length
    && crypto.timingSafeEqual(Buffer.from(got), Buffer.from(want))
    && Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
}

Réponse, nouvelles tentatives et mise en pause

  • Répondez avec n'importe quel statut 2xx en moins de 10 secondes. Tout le reste compte comme un échec.
  • Un appel échoué est retenté après 1 minute, puis 5 minutes, 30 minutes et 2 heures. Cela fait cinq essais au total, répartis sur environ deux heures et demie, après quoi la remise est marquée comme échouée.
  • Les appels vers une même adresse sont envoyés un par un, du plus ancien au plus récent. Une remise en attente d'une nouvelle tentative ne retient pas les plus récentes : ne comptez donc pas sur l'arrivée des événements dans un ordre strict. Une adresse lente ne retient qu'elle-même.
  • Après 50 remises échouées d'affilée, le webhook se met en pause : les nouveaux événements ne sont plus mis en file pour lui. Un Test réussi remet le compteur à zéro et les événements circulent de nouveau.
  • Au plus 200 appels non remis attendent pour un webhook. Au-delà, les événements suivants ne sont plus mis en file tant que certains n'ont pas été remis ou n'ont pas échoué.
  • Le panneau conserve les 50 dernières remises terminées de chaque webhook, avec la réponse reçue, afin que vous voyiez ce qui a échoué. Les plus récentes sont listées sous le webhook.

Si le panneau affiche une raison plutôt qu'un statut, c'est l'une des suivantes : l'adresse n'est pas sur l'Internet public, aucune réponse en 10 secondes, le nom d'hôte n'existe pas, le certificat HTTPS n'est pas valide, ou le panneau n'a pas pu se connecter.

Bonnes habitudes

  • Répondez vite avec 200 et faites le vrai travail ensuite. Un récepteur qui met plus de 10 secondes ressemble à un échec et reçoit de nouveau le même événement.
  • Traitez deux fois la même remise sans dommage. Les nouvelles tentatives et les erreurs réseau rendent les doublons possibles.
  • Gardez le secret hors de votre dépôt de code. S'il fuit, supprimez le webhook et ajoutez-en un nouveau.

À lire aussi : Guide du revendeur · Dépannage