> For the complete documentation index, see [llms.txt](https://boundaryai.gitbook.io/boundaryai-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://boundaryai.gitbook.io/boundaryai-docs/boundaryai-docs-fr/api-et-webhooks/webhooks.md).

# Webhooks

Abonnez-vous aux événements, vérifiez les signatures et gérez les nouvelles tentatives.

Les webhooks envoient des événements à vos systèmes dès qu’ils se produisent, vous n’avez donc jamais à interroger. Les abonnements sont gérés dans le tableau de bord sous **Intégrations → Outils développeur → Webhooks** (réservé aux admins) : définissez une URL cible, choisissez les événements, et vous obtenez un HMAC **secret de signature**, affiché une seule fois (vous pouvez le régénérer à tout moment avec *Régénérer le secret*). Une organisation peut avoir jusqu’à 10 abonnements, et chacun peut être mis en pause et repris depuis le même écran.

Les URL cibles doivent être **HTTPS**, et les livraisons sont signées afin que vous puissiez prouver qu’elles proviennent de BAI Analytics. Utilisez *Webhook de test* sur un abonnement pour recevoir une livraison signée avec `"event": "test"` avant de connecter de vrais événements.

***

### Les événements

| Événement            | Déclenché lorsque                                                                                                                                                                                                                                                                         |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `content.pushed`     | Un push via l’API a déposé des éléments dans une source.                                                                                                                                                                                                                                  |
| `series.created`     | Un groupe de feedback a été créé via l’API.                                                                                                                                                                                                                                               |
| `survey.created`     | Une source a été créée via l’API.                                                                                                                                                                                                                                                         |
| `survey.published`   | Une source a été publiée et peut recevoir du contenu.                                                                                                                                                                                                                                     |
| `analysis.completed` | Une passe d’analyse est terminée ; les résultats sont lisibles via le point de terminaison d’analyse.                                                                                                                                                                                     |
| `flag.raised`        | Un moniteur Custom Monitoring a franchi son seuil d’alerte. Se déclenche sous la même condition que les alertes de moniteur par e-mail/SMS, donc il nécessite un paramètre de notifications de moniteur activé avec la fonctionnalité d’alertes ; un abonnement seul ne le déclenche pas. |
| `report.ready`       | Un abonnement de rapport de fin de période a produit son rapport.                                                                                                                                                                                                                         |
| `invites.completed`  | Une distribution d’invitations déclenchée par l’API est terminée, avec les totaux finaux.                                                                                                                                                                                                 |
| `invite.bounced`     | Une invitation envoyée par l’API a rebondi ou a suscité une plainte pour spam.                                                                                                                                                                                                            |

Les noms d’événements utilisent le vocabulaire classique de l’API (`series` = groupe de feedback, `survey` = source, `flag` = moniteur) ; ce sont des contrats de transport et ils restent stables. `GET /me` répertorie les événements auxquels l’organisation de votre clé peut s’abonner. Les schémas complets des payloads et un exemple pour chaque événement se trouvent dans la section **Webhooks** de la référence de l’API.

***

### À quoi ressemble une livraison

```
POST <votre URL>
Content-Type: application/json
X-Boundary-Event: analysis.completed
X-Boundary-Signature: sha256=8f2ab0...
User-Agent: BoundaryAI-Webhook/1.0

{"event": "analysis.completed",
 "timestamp": "2026-07-12T09:45:12Z",
 "data": {"survey_series_id": 1842, "survey_id": 9021,
          "analysis_id": 55710, "survey_name": "Tickets d’assistance (synchronisation CRM)"}}
```

Chaque livraison utilise la même enveloppe : `événement`, `horodatage` (UTC ISO-8601), et un champ `data` objet.

***

### Vérification de la signature

`X-Boundary-Signature` est `sha256=` suivi du HMAC-SHA256 hexadécimal du **corps brut de la requête**, associé au secret de votre abonnement. Calculez-le sur les octets exacts reçus, avant tout parsing JSON, et comparez en temps constant.

{% tabs %}
{% tab title="Python" %}

```python
import hashlib, hmac

def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature_header)
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const crypto = require("crypto");

function verify(rawBody, signatureHeader, secret) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected), Buffer.from(signatureHeader));
}
```

{% endtab %}
{% endtabs %}

Rejetez tout ce qui ne se vérifie pas. Si vous faites tourner le secret, les livraisons sont immédiatement signées avec le nouveau.

***

### Sémantique des livraisons

* **Répondez avec un code 2xx en moins de 30 secondes.** Accusez réception d’abord, traitez ensuite ; effectuez le travail lourd hors du chemin de la requête.
* **Les redirections ne sont pas suivies.** Une réponse 3xx compte comme une livraison échouée, donc pointez l’abonnement vers l’URL finale.
* **Tentatives de reprise**: une réponse non-2xx ou un délai d’attente expiré est retenté après environ 1 minute puis à nouveau après environ 5 minutes, pour 3 tentatives au total. Chaque tentative échouée incrémente le compteur d’échecs de l’abonnement, que vous pouvez voir dans le tableau de bord ; une livraison réussie le réinitialise.
* **Mise en pause automatique**: après 10 échecs consécutifs, l’abonnement est désactivé et cesse de recevoir des événements jusqu’à ce que vous le réactiviez dans le tableau de bord. Corrigez d’abord le point de terminaison, puis *Activer le webhook*.
* **Concevez pour au moins une fois.** Considérez les livraisons comme idempotentes : le `data` payload plus votre propre état doit rendre toute rediffusion sans effet.
* **L’ordre n’est pas garanti** entre les événements ; utilisez le `horodatage` et vos propres identifiants plutôt que l’ordre d’arrivée.

{% hint style="success" %}
La combinaison la plus utile : l’envoi push avec `POST /feedback/push`, puis agissez sur `analysis.completed` au lieu d’interroger le point de terminaison d’analyse. Votre intégration reste pilotée par les événements de bout en bout.
{% endhint %}
