SocialHub.AI
Centre de développement · Extensibilité ouverte

Webhooks

Abonnez vos systèmes aux événements Flash. Enregistrez un point de terminaison HTTPS pour les événements qui vous intéressent, et Flash transmet une charge utile légère et signée dès que chaque événement se déclenche — pas d'interrogation, pas d'exportation nocturne . Les signatures respectent la spécification Standard Webhooks, les envois sont relancés avec un délai d'attente, et chaque tentative est consignée.

Étape 1 — S'abonner

Enregistrer un point de terminaison

Créez un point de terminaison webhook avec une clé Bearer fl_live_ contenant la portée webhooks:manage. Publiez une requête HTTPS url et la liste des eventTypes à y envoyer. Le secret de signature ) ; conservez-le précieusement, car il est nécessaire pour vérifier chaque envoi.

curl -X POST https://flash.socialhub.ai/api/v2/webhooks \
  -H "Authorization: Bearer fl_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.your-app.com/flash",
    "description": "prod ingest",
    "eventTypes": ["member.created", "loyalty.tier_upgraded"]
  }'

# 201 Created
# {
#   "data": {
#     "id": "whe_...",
#     "url": "https://hooks.your-app.com/flash",
#     "eventTypes": ["member.created", "loyalty.tier_upgraded"],
#     "status": "active",
#     "secret": "whsec_..."   <-- shown ONCE, store it now
#   }
# }

Gérez les points de terminaison ultérieurement avec GET /api/v2/webhooks (liste, sans secret), PATCH /api/v2/webhooks/{id} (modification de l'URL, des événements ou du statut, ou envoi de { "action": "rotate_secret" } pour renouveler le secret) et DELETE /api/v2/webhooks/{id}. Vous pouvez également enregistrer, tester et rejouer les livraisons depuis Paramètres → Webhooks.

Étape 2 — Découvrir les événements

Le catalogue des événements

Demandez au API Les événements auxquels vous pouvez vous abonner. Le catalogue est établi à partir de la source de référence en temps réel déclenchée par l'automatisation ; il répertorie donc les événements auxquels il est possible de s'abonner. uniquement les événements qui se produisent réellement aujourd'hui — regroupées par étape du cycle de vie (acquisition, engagement, fidélisation, rétention, commerce, recommandation) — chacune avec sa clé d'événement, une description et un exemple de charge utile. La réponse documente également l'enveloppe de charge utile partagée et les en-têtes de signature.

curl https://flash.socialhub.ai/api/v2/events/catalog \
  -H "Authorization: Bearer fl_live_..."

# { "data": { "events": [
#     { "event": "member.created", "label": "Member created",
#       "stage": "acquisition", "examplePayload": { ... } },
#     { "event": "loyalty.tier_upgraded", "label": "Tier upgraded",
#       "stage": "loyalty", "examplePayload": { ... } },
#     ...
#   ],
#   "payload": { "schema": { ... }, "headers": { ... } }
# } }

Lors de votre inscription, intégrez directement la clé event de l'événement dans le champ eventTypes array. Nécessite le périmètre webhooks:manage.

La diffusion

Une charge utile légère, sans données personnelles

Chaque livraison contient la même petite enveloppe : un élément stable id, l’événement type, un bloc created_at timestamp et un bloc compact data. La charge utile ne contient jamais de données personnelles : ni adresse e-mail, ni nom, ni numéro de téléphone, ni adresse postale. Lorsque vous avez besoin des informations du membre, récupérez-les via le bloc API authentifié à l’aide de member_ref. Ainsi, les informations personnelles restent dans la fiche du membre et ne sont pas enregistrées dans vos journaux de webhook.

POST https://hooks.your-app.com/flash
webhook-id:        evt_a1b2c3...              # stable across retries — dedupe on this
webhook-timestamp: 1767225600                 # unix seconds
webhook-signature: v1,K5x0mF...==             # base64 HMAC-SHA256 (may be space-separated during rotation)
Content-Type:      application/json

{
  "id": "evt_a1b2c3...",
  "type": "loyalty.tier_upgraded",
  "created_at": "2026-01-01T00:00:00.000Z",
  "data": {
    "resource_id": "mbr_...",
    "member_ref": "mbr_...",     // opaque member id — fetch PII via the API
    "tier": "Gold",              // present on loyalty / tier events
    "amount_band": "100-500"     // coarse band on commerce events — never the exact amount
  }
}
Sécurité

Vérifiez chaque signature

Flash signe chaque envoi avec le secret whsec_ de votre point de terminaison en utilisant Webhooks standard (HMAC-SHA256). Recalculez la signature sur {webhook-id}.{webhook-timestamp}.{body} et comparez-la, en temps constant, à l'en-tête webhook-signature. Rejetez tout envoi non conforme et rejetez un webhook-timestamp trop ancien pour se protéger contre les attaques par rejeu. La clé de signature correspond aux octets décodés en base64 du secret après le préfixe whsec_, conformément à la spécification. Lors d'une rotation du secret, l'en-tête contient plusieurs valeurs v1,… séparées par des espaces ; acceptez l'envoi si au moins correspond.

import crypto from "node:crypto";

// req.body must be the RAW, unparsed request body string.
function verifyFlashWebhook(headers, rawBody, whsec) {
  const id = headers["webhook-id"];
  const ts = headers["webhook-timestamp"];
  const sigHeader = headers["webhook-signature"]; // "v1,<b64> v1,<b64> ..."

  // reject stale deliveries (5 min tolerance)
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;

  const key = Buffer.from(whsec.replace(/^whsec_/, ""), "base64");
  const expected = crypto
    .createHmac("sha256", key)
    .update(`${id}.${ts}.${rawBody}`)
    .digest("base64");

  return sigHeader
    .split(" ")
    .map((p) => p.split(",")[1])
    .some((sig) =>
      sig &&
      sig.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)),
    );
}
Fiabilité

Tentatives de reconnexion, idempotence et journal de livraison

Retour rapide à 2xx

Accusez réception avec un 2xx et exécutez votre traitement de manière asynchrone. Un 429, un 5xx, un délai d'attente ou une erreur de connexion sont considérés comme pouvant faire l'objet d'une nouvelle tentative.

Nouvelle tentative automatique avec délai d'attente

Les échecs pouvant être traités ultérieurement sont gérés avec une temporisation exponentielle complète. Une erreur 3xx ou une erreur 4xx autre que 429 est considérée comme un échec définitif et n'est pas relancée.

Déduplication par webhook-id

La id est identique lors des nouvelles tentatives, garantissant ainsi une livraison au moins une fois : considérez une webhook-id répétée comme déjà traitée.

Journal de diffusion et relecture

Chaque tentative est enregistrée. Si le nombre de tentatives est épuisé, la livraison est considérée comme non aboutie. Vous pouvez consulter et revoir les livraisons depuis Paramètres → Webhooks.