Back to docs

Webhooks

Webhooks

Recevez des notifications HTTP signées lorsque les liens, campagnes et publications changent dans votre espace de travail.

Les webhooks Styrar envoient des notifications HTTP signées lorsque des ressources de votre espace de travail changent. Utilisez-les pour synchroniser liens et clics avec un CRM, déclencher des automatisations dans votre stack, ou diffuser des événements de funnel vers un entrepôt de données.

Ceci remplace l'API de webhooks limitée aux liens, désormais retirée (/v1/link-webhooks). Les nouvelles intégrations doivent utiliser uniquement /v1/webhooks/*.

Mettre en place un webhook

Suivez ces étapes pour passer de zéro à un point de terminaison vérifié et prêt pour la production.

1. Préparez votre URL de réception

Votre serveur a besoin d'une URL HTTPS publique qui accepte des requêtes POST avec un corps JSON. En production, les URL de callback doivent utiliser HTTPS.

Votre gestionnaire doit :

  • Lire le corps brut de la requête sous forme de chaîne ou de buffer (ne pas analyser le JSON avant de vérifier la signature).
  • Lire les en-têtes Styrar-Signature, Styrar-Event-Id et Styrar-Event-Type.
  • Vérifier la signature (voir la section Vérifier les signatures ci-dessous).
  • Retourner un code 2xx rapidement une fois l'événement accepté. Mettez le traitement lourd en file d'attente de manière asynchrone.

Exemple de chemin : https://votre-app.com/webhooks/styrar

Styrar ne peut pas livrer vers des adresses privées ou loopback comme localhost.

2. Obtenez un accès à l'API (pour une configuration programmatique)

Si vous créez des points de terminaison via l'API plutôt que via le tableau de bord, vous avez besoin d'un jeton Bearer avec :

PortéeAccès
webhooks:readLister les points de terminaison, les livraisons et les types d'événements
webhooks:writeCréer, mettre à jour, supprimer, tester, faire tourner le secret, relancer les livraisons

Créez une clé API dans Paramètres → Clés API avec webhooks:read et webhooks:write, ou utilisez un jeton d'accès OAuth d'une application connectée avec les mêmes portées.

Pour les espaces de travail d'entreprise, transmettez companyId lors des requêtes de liste et de création.

3. Créez un point de terminaison dans le tableau de bord

  1. Connectez-vous et ouvrez Paramètres → Webhooks (/settings/webhooks).
  2. Sous Points de terminaison, saisissez votre URL de point de terminaison (le callback HTTPS public).
  3. Ajoutez éventuellement une Description (par exemple « Synchronisation CRM de production »).
  4. Sélectionnez les Événements souhaités (au moins un est requis). Choix courants :
    • link.clicked pour le suivi des clics
    • link.created / link.updated / link.deleted pour le cycle de vie des liens
    • post.published et campaign.created pour les événements de funnel
  5. Cliquez sur Ajouter un point de terminaison.

Après la création, Styrar affiche votre secret de signature (whsec_live_… ou whsec_test_…). Copiez-le immédiatement et stockez-le dans votre gestionnaire de secrets. Il n'est affiché qu'une seule fois. Si vous le perdez, utilisez Faire tourner le secret sur le point de terminaison et mettez à jour votre serveur.

4. Créez un point de terminaison via l'API

RequestPOST
Authorization: Bearer sty_live_your_api_key
Content-Type: application/json

{
  "companyId": "cmxyz_company",
  "url": "https://your-app.com/webhooks/styrar",
  "description": "Production CRM sync",
  "eventTypes": [
    "link.clicked",
    "link.created"
  ]
}
Response201 Created
{
  "id": "wh_ep_abc123",
  "url": "https://your-app.com/webhooks/styrar",
  "description": "Production CRM sync",
  "enabled": true,
  "eventTypes": [
    "link.clicked",
    "link.created"
  ],
  "secretPrefix": "whsec_l",
  "companyId": "cmxyz_company",
  "userId": null,
  "disabledAt": null,
  "createdAt": "2026-06-22T12:00:00.000Z",
  "updatedAt": "2026-06-22T12:00:00.000Z",
  "secret": "whsec_live_abc123onlyShownOnce"
}

Stockez secret immédiatement. Il n'est pas renvoyé lors des requêtes GET ultérieures. Un tableau eventTypes vide vous abonne à tous les types d'événements ; le tableau de bord exige au moins un événement explicite.

5. Envoyez un événement de test

Confirmez que votre serveur est accessible avant de vous fier au trafic réel.

Tableau de bord : Sur la ligne du point de terminaison, cliquez sur Envoyer un test. Styrar livre un événement webhook.test. Vous devriez voir une notification de succès avec le code de statut HTTP.

API :

RequestPOST
Authorization: Bearer sty_live_your_api_key
Response200 OK
{
  "ok": true,
  "statusCode": 200
}

Lorsque le test réussit, votre serveur devrait avoir reçu un événement webhook.test (voir Recevoir un événement sur votre serveur ci-dessous).

Consultez Livraisons récentes dans le tableau de bord (ou GET /v1/webhooks/deliveries) si le test échoue. Problèmes courants :

ProblèmeQue vérifier
Connexion refusée / délai dépasséL'URL est en HTTPS public, le pare-feu autorise Styrar, le tunnel est actif
HTTP 4xx/5xx depuis votre applicationLe gestionnaire renvoie 2xx après vérification ; journalisez le corps brut et les en-têtes
La vérification de signature échoueUtilisez le corps brut, le bon secret, une comparaison en temps constant
Point de terminaison désactivéRéactivez dans le tableau de bord ou corrigez ce qui a causé le HTTP 410

6. Vérifiez et traitez les livraisons

Pour chaque POST vers votre URL :

  1. Analysez Styrar-Signature pour en extraire l'horodatage t et le condensé v1.
  2. Rejetez si t est plus ancien que votre tolérance (5 minutes recommandées).
  3. Calculez le HMAC-SHA256 de "{t}.{raw_body}" avec le secret de votre point de terminaison.
  4. Comparez avec v1 en utilisant une vérification en temps constant.
  5. N'analysez le JSON qu'après réussite de la vérification.
  6. Dédupliquez sur Styrar-Event-Id (livraison au moins une fois).

Voir la section Vérifier les signatures ci-dessous pour un exemple en Node.js.

7. Passez en production

  • Gardez le point de terminaison Activé dans le tableau de bord.
  • Abonnez-vous uniquement aux événements dont vous avez besoin (réduit le bruit et le coût).
  • Surveillez les Livraisons récentes pour détecter les échecs et utilisez Relancer au besoin.
  • Faites tourner le secret s'il a pu être divulgué (Faire tourner le secret dans le tableau de bord ou POST …/rotate-secret).

Démarrage rapide

  1. Obtenez un accès à l'API avec les portées webhooks:read et webhooks:write (clé API ou OAuth).
  2. Exposez un récepteur HTTPS public et créez un point de terminaison dans Paramètres → Webhooks ou via POST /v1/webhooks/endpoints.
  3. Copiez le secret de signature lorsqu'il est affiché et stockez-le en sécurité.
  4. Envoyez un événement de test et confirmez que votre serveur vérifie Styrar-Signature et renvoie 2xx.
  5. Traitez les événements réels avec déduplication sur Styrar-Event-Id.

Authentification

La gestion des webhooks nécessite un jeton Bearer avec les portées listées à l'étape 2 ci-dessus. Les clés API avec les portées correspondantes fonctionnent de la même manière que les jetons d'accès OAuth.

Types d'événements

Appelez GET /v1/webhooks/event-types pour obtenir le catalogue en temps réel de votre environnement. Abonnez-vous à des types spécifiques par point de terminaison, ou transmettez un tableau eventTypes vide pour recevoir tous les événements.

webhook.test n'est envoyé que lorsque vous cliquez sur Envoyer un test ; il n'est pas émis par l'activité normale de l'espace de travail.

Enveloppe d'événement

Chaque livraison utilise la même structure de premier niveau. Les champs spécifiques à l'événement se trouvent sous data.object :

ChampTypeDescription
idstringIdentifiant unique de l'événement. Même valeur que l'en-tête Styrar-Event-Id.
typestringNom de l'événement (par exemple link.clicked).
api_versionstringVersion du schéma de charge utile (2026-06-22).
created_atstringHorodatage ISO 8601 de la création de l'événement.
workspace.typestringcompany ou personal.
workspace.company_idstring | nullIdentifiant d'entreprise lorsque workspace.type est company.
data.objectobjectCharge utile de l'événement (documentée par événement ci-dessous).

Exemple complet de livraison (enveloppe + charge utile link.created) :

JSON
{
  "id": "evt_outbox_abc123",
  "type": "link.created",
  "api_version": "2026-06-22",
  "created_at": "2026-06-22T12:00:00.000Z",
  "workspace": {
    "type": "company",
    "company_id": "cmxyz_company"
  },
  "data": {
    "object": {
      "id": "clink_abc123",
      "short_code": "summer",
      "title": "Summer sale",
      "original_url": "https://example.com/sale",
      "is_active": true,
      "company_id": "cmxyz_company",
      "campaign_id": "ccamp_abc",
      "link_group_id": null,
      "created_at": "2026-06-22T12:00:00.000Z"
    }
  }
}

Pour les espaces personnels, workspace.type vaut personal et workspace.company_id vaut null. La charge utile peut inclure company_id: null sur les objets de lien.

Résumé des événements

ÉvénementQuand il se déclencheVolume typique
link.createdUn lien court est créé (POST /v1/links, création en masse ou upsert en masse)Faible
link.updatedUn lien court est mis à jour (PATCH /v1/links/:id, mise à jour en masse ou upsert en masse)Faible
link.deletedUn lien court est supprimé de façon logicielle (DELETE /v1/links/:id ou suppression en masse)Faible
link.clickedUn clic suivi est enregistré (asynchrone, après la redirection via le worker de clics)Élevé
link.experiment.completedUne expérience A/B sur un lien est terminée et un gagnant est sélectionnéFaible
campaign.createdUne campagne est créée (POST /v1/campaigns)Faible
post.publishedUne publication sociale est publiée avec succès sur toutes les cibles de plateformeFaible
webhook.testVous exécutez Envoyer un test sur un point de terminaisonSur demande

link.created

Se déclenche lorsqu'un nouveau lien court est enregistré dans votre espace de travail.

Usages courants : Synchroniser les nouveaux liens vers un CRM, déclencher des automatisations de bienvenue, ou indexer les liens dans un moteur de recherche externe.

Champs de data.object :

ChampTypeDescription
idstringIdentifiant du lien
short_codestringCode court public
titlestring | nullTitre du lien
original_urlstring | nullURL de destination
is_activebooleanSi le lien est actif
company_idstring | nullEntreprise propriétaire (espace entreprise)
campaign_idstring | nullCampagne liée, si applicable
link_group_idstring | nullIdentifiant du dossier/groupe, si applicable
created_atstringHeure de création ISO 8601
JSON
{
  "id": "clink_abc123",
  "short_code": "summer",
  "title": "Summer sale",
  "original_url": "https://example.com/sale",
  "is_active": true,
  "company_id": "cmxyz_company",
  "campaign_id": "ccamp_abc",
  "link_group_id": null,
  "created_at": "2026-06-22T12:00:00.000Z"
}

link.updated

Se déclenche lorsqu'un lien court existant est modifié (destination, titre, tags, dossier, paramètres UTM, etc.).

Usages courants : Garder les systèmes externes synchronisés lorsqu'un lien change sans le recréer.

Champs de data.object : Identiques à link.created (voir ci-dessus).

JSON
{
  "id": "clink_abc123",
  "short_code": "summer",
  "title": "Summer sale (updated)",
  "original_url": "https://example.com/sale-v2",
  "is_active": true,
  "company_id": "cmxyz_company",
  "campaign_id": "ccamp_abc",
  "link_group_id": "lgrp_promos",
  "created_at": "2026-06-22T12:00:00.000Z"
}

link.deleted

Se déclenche lorsqu'un lien court est supprimé de façon logicielle (isActive mis à false). Le lien arrête de résoudre publiquement mais reste dans l'historique de votre espace de travail.

Usages courants : Retirer les liens des catalogues externes ou suspendre les automatisations liées à ce code court.

Champs de data.object : Même structure que link.created, avec is_active toujours à false.

ChampTypeDescription
idstringIdentifiant du lien
short_codestringCode court au moment de la suppression
titlestring | nullTitre du lien
original_urlstring | nullURL de destination
is_activebooleanfalse après suppression logicielle
company_idstring | nullEntreprise propriétaire
campaign_idstring | nullCampagne liée, si applicable
link_group_idstring | nullIdentifiant du dossier/groupe, si applicable
created_atstringHeure de création originale
JSON
{
  "id": "clink_abc123",
  "short_code": "summer",
  "title": "Summer sale",
  "original_url": "https://example.com/sale",
  "is_active": false,
  "company_id": "cmxyz_company",
  "campaign_id": "ccamp_abc",
  "link_group_id": null,
  "created_at": "2026-06-22T12:00:00.000Z"
}

link.clicked

Se déclenche après qu'un clic visiteur a été enregistré. Livré de manière asynchrone (pas sur le chemin de redirection), attendez-vous donc à un léger délai en cas de forte charge.

Usages courants : Analytics de clics en temps réel, routage géographique dans votre stack, flux d'activité CRM, ou ingestion en entrepôt de données.

Confidentialité : Les charges utiles incluent des dimensions de géolocalisation et d'appareil, pas d'adresses IP brutes.

Champs de data.object :

ChampTypeDescription
idstringIdentifiant du lien
link_idstringIdentique à id
short_codestringCode court qui a été cliqué
titlestring | nullTitre du lien
countrystring | nullCode pays ISO (recherche géo)
citystring | nullVille issue de la recherche géo
devicestring | nullClasse d'appareil (par exemple mobile, desktop)
browserstring | nullNom du navigateur
osstring | nullSystème d'exploitation
platformstring | nullIndice de plateforme issu de l'analyse du user agent
referrerstring | nullURL de provenance lorsque disponible
routing_rule_idstring | nullRègle de routage géo/appareil correspondante, si applicable
experiment_variant_idstring | nullIdentifiant de variante A/B lorsque le clic a traversé une expérience
clicked_atstringHeure de clic ISO 8601
JSON
{
  "id": "clink_abc123",
  "link_id": "clink_abc123",
  "short_code": "summer",
  "title": "Summer sale",
  "country": "NL",
  "city": "Amsterdam",
  "device": "mobile",
  "browser": "Chrome",
  "os": "iOS",
  "platform": null,
  "referrer": "https://instagram.com/",
  "routing_rule_id": null,
  "experiment_variant_id": null,
  "clicked_at": "2026-06-22T12:00:00.000Z"
}

link.experiment.completed

Se déclenche lorsqu'un test A/B sur un lien court est marqué comme terminé et qu'une variante gagnante est sélectionnée.

Usages courants : Journaliser les résultats d'expériences, mettre à jour des tableaux de bord, ou déclencher des campagnes de suivi en fonction du gagnant.

Champs de data.object :

ChampTypeDescription
idstringIdentifiant de l'expérience
link_idstringIdentifiant du lien parent
short_codestring | nullCode court du lien parent
statusstringcompleted
assignment_modestring | nullMode de répartition du trafic (par exemple pondéré)
winning_variant_idstring | nullIdentifiant de la variante gagnante
ended_atstring | nullHeure de fin ISO 8601
variantsarrayRésultats par variante (voir ci-dessous)

Chaque élément de variants :

ChampTypeDescription
idstringIdentifiant de la variante
labelstringLibellé lisible
weightnumberPoids de trafic utilisé dans le test
destination_urlstringURL vers laquelle cette variante envoyait le trafic
clicksnumberTotal des clics enregistrés pour cette variante
JSON
{
  "id": "lexp_abc123",
  "link_id": "clink_abc123",
  "short_code": "summer",
  "status": "completed",
  "assignment_mode": "weighted",
  "winning_variant_id": "lvar_b",
  "ended_at": "2026-06-22T14:00:00.000Z",
  "variants": [
    {
      "id": "lvar_a",
      "label": "Control",
      "weight": 50,
      "destination_url": "https://example.com/a",
      "clicks": 120
    },
    {
      "id": "lvar_b",
      "label": "Variant B",
      "weight": 50,
      "destination_url": "https://example.com/b",
      "clicks": 184
    }
  ]
}

campaign.created

Se déclenche lorsqu'une nouvelle campagne est créée dans votre espace de travail.

Usages courants : Provisionner des dossiers de campagne dans des outils externes, démarrer des workflows d'attribution, ou notifier des chargés de compte.

Champs de data.object :

ChampTypeDescription
idstringIdentifiant de la campagne
namestringNom de la campagne
descriptionstring | nullDescription de la campagne
company_idstring | nullEntreprise propriétaire
user_idstring | nullUtilisateur créateur (campagnes personnelles)
brand_idstring | nullPortée de marque lorsque définie
created_atstringHeure de création ISO 8601
JSON
{
  "id": "ccamp_abc123",
  "name": "Summer launch",
  "description": "Q2 product push",
  "company_id": "cmxyz_company",
  "user_id": null,
  "brand_id": "cbrand_abc",
  "created_at": "2026-06-22T12:00:00.000Z"
}

post.published

Se déclenche lorsqu'une publication planifiée ou immédiate est publiée avec succès sur toutes les cibles de plateforme configurées.

Usages courants : Notifier les systèmes en aval que le contenu est en ligne, clore la boucle des automatisations de campagne, ou synchroniser l'état de publication vers un entrepôt de données.

Remarque : N'est émis que lorsque chaque cible réussit. Les échecs partiels n'émettent pas cet événement aujourd'hui.

Champs de data.object :

ChampTypeDescription
idstringIdentifiant de la publication
post_idstringIdentique à id
statusstringPUBLISHED
company_idstring | nullEntreprise propriétaire
user_idstring | nullUtilisateur propriétaire (espace personnel)
brand_idstring | nullPortée de marque lorsque définie
campaign_idstring | nullCampagne liée lorsque définie
published_atstringHeure de publication ISO 8601
platform_countnumberNombre de cibles de plateforme sur la publication
JSON
{
  "id": "cpost_abc123",
  "post_id": "cpost_abc123",
  "status": "PUBLISHED",
  "company_id": "cmxyz_company",
  "user_id": null,
  "brand_id": "cbrand_abc",
  "campaign_id": "ccamp_abc123",
  "published_at": "2026-06-22T12:00:00.000Z",
  "platform_count": 3
}

webhook.test

Ping synthétique envoyé uniquement lorsque vous cliquez sur Envoyer un test dans le tableau de bord ou que vous appelez POST /v1/webhooks/endpoints/:id/test.

Usages courants : Valider votre URL de réception, le TLS, la vérification de signature et la gestion des réponses avant de passer en production.

Champs de data.object :

ChampTypeDescription
endpoint_idstringPoint de terminaison qui a reçu le test
messagestringMessage fixe : Styrar webhook test ping
JSON
{
  "endpoint_id": "wh_ep_abc123",
  "message": "Styrar webhook test ping"
}

Exemples d'API

Lister les points de terminaison

RequestGET
Authorization: Bearer sty_live_your_api_key
Response200 OK
[
  {
    "id": "wh_ep_abc123",
    "url": "https://your-app.com/webhooks/styrar",
    "description": "Production CRM sync",
    "enabled": true,
    "eventTypes": ["link.clicked", "link.created"],
    "secretPrefix": "whsec_l",
    "companyId": "cmxyz_company",
    "userId": null,
    "disabledAt": null,
    "createdAt": "2026-06-22T12:00:00.000Z",
    "updatedAt": "2026-06-22T12:00:00.000Z"
  }
]

Recevoir un événement sur votre serveur

Lorsqu'un événement abonné se déclenche, Styrar envoie un POST à l'URL de votre point de terminaison. Voici la charge utile que reçoit votre gestionnaire :

RequestPOST
Content-Type: application/json
Styrar-Event-Id: evt_outbox_abc123
Styrar-Event-Type: link.clicked
Styrar-Signature: t=1719052800,v1=8f4b2c1a9e0d3f7b6a5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3
User-Agent: Styrar-Webhooks/1.0

{
  "id": "evt_outbox_abc123",
  "type": "link.clicked",
  "api_version": "2026-06-22",
  "created_at": "2026-06-22T12:00:00.000Z",
  "workspace": {
    "type": "company",
    "company_id": "cmxyz_company"
  },
  "data": {
    "object": {
      "id": "clink_abc123",
      "link_id": "clink_abc123",
      "short_code": "summer",
      "title": "Summer sale",
      "country": "NL",
      "city": "Amsterdam",
      "device": "mobile",
      "browser": "Chrome",
      "os": "iOS",
      "referrer": "https://instagram.com/",
      "routing_rule_id": null,
      "experiment_variant_id": null,
      "clicked_at": "2026-06-22T12:00:00.000Z"
    }
  }
}
Response200 OK
{
  "received": true
}

Le corps de votre réponse peut être vide. Renvoyez n'importe quel statut 2xx après avoir vérifié la signature et accepté l'événement. Styrar relance en cas de réponse non-2xx.

Charge utile du ping de test

Une action Envoyer un test livre webhook.test avec une charge utile plus petite :

RequestPOST
Content-Type: application/json
Styrar-Event-Id: evt_test_abc123
Styrar-Event-Type: webhook.test
Styrar-Signature: t=1719052800,v1=...

{
  "id": "evt_test_abc123",
  "type": "webhook.test",
  "api_version": "2026-06-22",
  "created_at": "2026-06-22T12:00:00.000Z",
  "workspace": {
    "type": "company",
    "company_id": "cmxyz_company"
  },
  "data": {
    "object": {
      "endpoint_id": "wh_ep_abc123",
      "message": "Styrar webhook test ping"
    }
  }
}
Response200 OK

Lister les livraisons récentes

RequestGET
Authorization: Bearer sty_live_your_api_key
Response200 OK
[
  {
    "id": "wh_del_abc123",
    "endpointId": "wh_ep_abc123",
    "outboxEventId": "wh_out_abc123",
    "eventType": "link.clicked",
    "status": "delivered",
    "attemptCount": 1,
    "lastStatusCode": 200,
    "lastError": null,
    "durationMs": 142,
    "nextAttemptAt": null,
    "deliveredAt": "2026-06-22T12:00:01.000Z",
    "createdAt": "2026-06-22T12:00:00.500Z"
  }
]

Gérer les points de terminaison

Plain text
GET    /v1/webhooks/endpoints?companyId={id}
POST   /v1/webhooks/endpoints
GET    /v1/webhooks/endpoints/:id
PATCH  /v1/webhooks/endpoints/:id
DELETE /v1/webhooks/endpoints/:id
POST   /v1/webhooks/endpoints/:id/test
POST   /v1/webhooks/endpoints/:id/rotate-secret
ChampDescription
urlURL de callback HTTPS
descriptionLibellé optionnel
eventTypesTableau des types d'événements abonnés ; vide signifie tous les événements
enabledtrue par défaut

Le secret de signature (whsec_live_… / whsec_test_…) est renvoyé exactement une fois à la création et lors de rotate-secret. Vous pouvez enregistrer jusqu'à 25 points de terminaison par portée d'espace de travail.

Livraisons

Plain text
GET  /v1/webhooks/deliveries?endpointId={id}
GET  /v1/webhooks/deliveries/:id
POST /v1/webhooks/deliveries/:id/retry

Chaque ligne de livraison suit status, attemptCount, nextAttemptAt, lastStatusCode, lastError et deliveredAt. Examinez les échecs dans le tableau de bord sous Paramètres → Webhooks ou relancez via l'API.

Format de livraison

Chaque événement réel est un POST HTTP vers votre URL de callback. Les en-têtes et le corps sont présentés dans Recevoir un événement sur votre serveur ci-dessus.

En-têteDescription
Styrar-Event-IdIdentifiant unique de l'événement (utilisez-le pour la déduplication)
Styrar-Event-Typepar exemple link.clicked
Styrar-Signaturet={unix_ts},v1={hmac_sha256_hex}
User-AgentStyrar-Webhooks/1.0

Champs de l'enveloppe :

ChampDescription
idIdentifiant de l'événement (correspond à Styrar-Event-Id)
typeChaîne de type d'événement
api_versionVersion du schéma de charge utile
created_atHorodatage ISO 8601
workspacePortée company ou personal
data.objectCharge utile spécifique à l'événement

Les charges utiles de clics incluent des dimensions de géolocalisation et d'appareil, pas d'adresses IP brutes.

Vérifier les signatures

La signature suit un schéma de type Stripe. Elle signe "{timestamp}.{raw_body}" avec HMAC-SHA256 en utilisant le secret de votre point de terminaison.

  1. Analysez Styrar-Signature pour en extraire t (horodatage unix) et v1 (condensé hexadécimal).
  2. Rejetez si t est hors de votre tolérance (nous recommandons 5 minutes).
  3. Calculez le condensé attendu et comparez-le avec v1 en utilisant une vérification en temps constant.
JavaScript
import crypto from 'node:crypto'

function verifyStyrarWebhook(secret, signatureHeader, rawBody, toleranceSeconds = 300) {
  const parts = Object.fromEntries(
    signatureHeader.split(',').map((part) => part.trim().split('=')),
  )

  const timestamp = Number(parts.t)
  const receivedDigest = parts.v1 || ''

  if (!Number.isFinite(timestamp)) return false
  if (Math.abs(Date.now() / 1000 - timestamp) > toleranceSeconds) return false

  const expectedDigest = crypto
    .createHmac('sha256', secret)
    .update(\`${timestamp}.${rawBody}\`)
    .digest('hex')

  try {
    return crypto.timingSafeEqual(
      Buffer.from(expectedDigest, 'utf8'),
      Buffer.from(receivedDigest, 'utf8'),
    )
  } catch {
    return false
  }
}

Vérifiez toujours par rapport au corps brut de la requête avant d'analyser le JSON.

Fiabilité

  • Les livraisons sont au moins une fois. Dédupliquez en utilisant Styrar-Event-Id ou l'id de l'enveloppe.
  • Les livraisons en échec sont relancées avec un backoff exponentiel jusqu'au succès ou au nombre maximal de tentatives.
  • Si votre serveur renvoie HTTP 410, Styrar désactive automatiquement le point de terminaison.
  • Répondez avec un code 2xx dès que vous avez accepté l'événement ; traitez le travail lourd de manière asynchrone.

Limites

  • HTTPS requis en production pour les URL de callback.
  • 25 points de terminaison par portée d'espace de travail personnel ou entreprise.
  • Les secrets de signature ne sont affichés qu'une fois à la création et lors de la rotation ; stockez-les dans votre gestionnaire de secrets.

Liens utiles

Join the beta waitlist

By signing up you agree to receive marketing email. See our Privacy Policy.