Aller au contenu de la page
Documentation
Documentation de Make Agent Fast

Webhooks

Enregistrez un point de terminaison public, vérifiez les charges utiles brutes signées, dédupliquez les événements et gérez les nouvelles tentatives en toute sécurité.

En un coup d’œil

Enregistrez un point de terminaison public, vérifiez les charges utiles brutes signées, dédupliquez les événements et gérez les nouvelles tentatives en toute sécurité.

Livraison des webhooksDes événements signés partent de la plateforme vers votre point de terminaison
Événement de la plateformeSignerHMACHTTPS POSTVotre application
HMAC-SHA256Au moins une fois8 tentatives

Les webhooks développeur envoient les événements de votre compte à votre serveur, ce qui vous évite d'effectuer des interrogations régulières (polling). La livraison s'effectue au moins une fois : les événements peuvent être dupliqués, retardés ou arriver dans le désordre.

Enregistrer un point de terminaison#

Créez une clé disposant de la permission webhooks:write, puis enregistrez un récepteur HTTPS public ainsi que le plus petit ensemble d'événements dont vous avez besoin.

curl --fail-with-body https://makeagent.fast/api/v1/webhook-endpoints \
  -X POST \
  -H "Authorization: Bearer $MAF_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: webhook-production-v1" \
  -d '{
    "url": "https://api.example.com/webhooks/make-agent-fast",
    "events": ["lead.created", "conversation.started"]
  }'

L'URL doit utiliser HTTPS, ne peut contenir ni nom d'utilisateur, ni mot de passe, ni fragment, ni port personnalisé, et ne doit se résoudre que vers des adresses IP publiques. Les redirections ne sont pas suivies lors de la livraison.

La réponse 201 révèle une seule fois un secret de signature whsec_.... Enregistrez-le dans le gestionnaire de secrets du récepteur avant de fermer la réponse. La liste des points de terminaison renvoie ensuite l'URL, les événements, le statut, la dernière livraison et la dernière erreur, mais pas le secret.

Types d'événements#

ÉvénementÉmis lorsque
site.publishedUn site est publié
site.unpublishedUn site repasse à l'état de brouillon
lead.createdL'agent enregistre un nouveau lead
lead.qualifiedL'agent qualifie un lead, ou un lead est accepté dans le pipeline commercial
booking.requestedUn visiteur demande ou réserve un créneau
handoff.requestedL'agent transmet une conversation à une personne
opportunity.createdUn lead devient une opportunité du pipeline
opportunity.updatedL'attribution, la valeur, la prochaine action ou d'autres champs d'une opportunité changent
opportunity.stage_changedUne opportunité passe à une autre étape
opportunity.wonUne opportunité est clôturée comme gagnée
opportunity.lostUne opportunité est clôturée comme perdue
conversation.startedUn nouveau fil de conversation démarre
conversation.message.createdUn message est ajouté à une conversation
knowledge.readyUne source de connaissances termine son traitement
broadcast.sentUne diffusion termine son flux d'envoi
domain.activatedObsolète : les domaines personnalisés ne sont pas proposés ; cet événement n'est jamais émis

Format de la requête#

Make Agent Fast envoie une requête POST avec Content-Type: application/json, User-Agent: MakeAgentFast-Webhooks/1.0 et les en-têtes suivants :

maf-event-id: evt_...
maf-event-type: lead.created
maf-signature: t=1784210566,v1=HEX_HMAC_SHA256

Le corps JSON repose sur une enveloppe stable. Les champs contenus dans data dépendent de l'événement et peuvent recevoir des champs supplémentaires.

{
  "id": "evt_2c34...",
  "type": "lead.created",
  "created_at": "2026-07-16T10:02:46.000Z",
  "data": {
    "site_id": "SITE_ID",
    "lead_id": "LEAD_ID"
  }
}

Utilisez l'id du corps ou maf-event-id comme clé de déduplication. N'utilisez ni l'heure de livraison ni un identifiant de base de données généré.

Vérifier la signature en Node.js#

Lisez les octets bruts exacts avant l'analyse du JSON. La valeur signée est TIMESTAMP + "." + RAW_BODY.

import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyWebhook(rawBody: Buffer, header: string, secret: string) {
  const values = Object.fromEntries(header.split(",").map((part) => part.split("=", 2)));
  const timestamp = values.t;
  const supplied = values.v1;
  if (!timestamp || !supplied || !/^[a-f0-9]{64}$/.test(supplied)) return false;

  const age = Math.abs(Date.now() / 1_000 - Number(timestamp));
  if (!Number.isFinite(age) || age > 300) return false;

  const expected = createHmac("sha256", secret)
    .update(`${timestamp}.`)
    .update(rawBody)
    .digest("hex");
  return timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(supplied, "hex"));
}

Rejetez les signatures malformées et les horodatages plus anciens que la fenêtre de rejeu que vous acceptez ; cinq minutes constituent une valeur par défaut raisonnable. Comparez des octets de longueur fixe en temps constant.

Vérifier la signature en Python#

import hashlib
import hmac
import time

def verify_webhook(raw_body: bytes, header: str, secret: str) -> bool:
    values = dict(part.split("=", 1) for part in header.split(",") if "=" in part)
    timestamp = values.get("t", "")
    supplied = values.get("v1", "")
    try:
        if abs(time.time() - int(timestamp)) > 300:
            return False
    except ValueError:
        return False

    signed = timestamp.encode() + b"." + raw_body
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, supplied)

N'analysez et ne traitez le JSON qu'une fois la vérification de la signature réussie.

Accuser réception et traiter#

  1. Vérifiez la signature et l'horodatage.
  2. Insérez l'identifiant de l'événement dans une table dotée d'une contrainte d'unicité.
  3. S'il existe déjà, renvoyez 204 sans répéter l'effet de bord.
  4. Validez l'événement (commit) ou mettez votre tâche interne en file d'attente.
  5. Renvoyez rapidement une réponse 2xx.

L'expéditeur de Make Agent Fast expire après 10 secondes. Il ne considère comme réussies que les réponses 2xx et ne suit pas les redirections.

Comportement des nouvelles tentatives#

Les livraisons échouées sont mises en file d'attente pour huit tentatives au maximum. Le délai d'attente commence autour de deux secondes, double avec une variation aléatoire (jitter) et est plafonné à une heure ; l'heure réelle de livraison peut être plus tardive lorsque les workers sont occupés. Comme les nouvelles tentatives peuvent survivre à la requête d'origine et arriver dans le désordre, ne partez jamais du principe qu'un événement arrive immédiatement avant un autre.

Ne renvoyez une réponse non 2xx que si vous souhaitez que Make Agent Fast réessaie. Pour une version d'événement définitivement non prise en charge ou une destination supprimée, acceptez et consignez l'événement, ou supprimez le point de terminaison, plutôt que de produire des échecs transitoires sans fin.

Renouveler un secret de signature#

Les secrets de signature ne peuvent être ni révélés ni modifiés. Pour les renouveler en toute sécurité :

  1. Créez un second point de terminaison pointant vers un chemin de récepteur temporaire ou versionné.
  2. Enregistrez le secret nouvellement révélé.
  3. Acceptez et dédupliquez les événements provenant des deux points de terminaison.
  4. Vérifiez que le nouveau point de terminaison reçoit des livraisons valides.
  5. Supprimez l'ancien point de terminaison avec DELETE /webhook-endpoints/{endpoint_id}.

Si l'URL du récepteur reste identique, faites en sorte que l'application réceptrice accepte les deux secrets pendant la période de chevauchement et utilisez les identifiants d'événement pour éviter les effets de bord en double.

Dépannage#

SymptômeÀ vérifier
Aucune livraisonStatut du point de terminaison, événements sélectionnés, DNS public, certificat HTTPS, et si l'événement s'est réellement produit
Signature non concordanteAccès au corps brut, concaténation exacte timestamp.body, secret correct du point de terminaison, et transformations du corps par un proxy
Livraisons répétéesCode de retour, délai d'expiration de 10 secondes, exceptions internes et unicité des identifiants d'événement
Erreur d'adresse privéeLes enregistrements DNS ne doivent se résoudre que vers des adresses publiques ; localhost et les plages internes sont rejetés
Échec de redirectionEnregistrez directement l'URL HTTPS finale ; les redirections ne sont pas suivies

N'incluez jamais le secret de signature, la clé bearer ni la charge utile complète d'un visiteur dans un message adressé au support. Indiquez l'identifiant du point de terminaison, l'identifiant de l'événement, l'heure de l'échec et des journaux du récepteur nettoyés de toute donnée sensible.