
# API Webhooks

Les webhooks permettent à la plateforme de notifier vos autres systèmes dès qu'un événement se produit : un nouveau contact, une réponse, un rendez-vous réservé, et plus encore. Cette API gère les **abonnements** eux-mêmes : quelles URL reçoivent quels événements. Pour savoir comment recevoir et vérifier les charges utiles que votre point de terminaison reçoit, consultez [Webhooks](../integrations/webhooks.md).

Tous les chemins ci-dessous sont relatifs à l'URL de base de l'API :

```
https://api.youraiconnector.com/v1
```

Chaque requête doit être authentifiée. Consultez [Authentification](authentication.md) pour connaître les quatre méthodes acceptées. Les exemples ici utilisent l'en-tête `X-API-Key` (et une forme de paramètre de requête pour cURL).

::: note
**Remarque :** Les webhooks doivent être activés pour votre compte. S'ils ne le sont pas, ces points de terminaison renvoient une `403`.
:::


---

## Comment les abonnements sont adressés

Chaque abonnement possède un `id` et un `name` optionnel. L'un ou l'autre peut être utilisé comme `{webhookId}` dans le chemin pour la mise à jour, la suppression, le test, l'état de santé et la réactivation.

> **Privilégiez le nom.** Les identifiants d'abonnement sont positionnels, ils peuvent donc changer après la suppression d'un autre abonnement. Si vous définissez un `name` stable lors de la création d'un abonnement, adressez-le par son nom pour éviter les surprises.

---

## Lister les abonnements

`GET /webhooks`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/webhooks",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Réponse**

```json
{
  "success": true,
  "webhooks": [
    {
      "id": "0",
      "name": "Order updates hook",
      "url": "https://hooks.example.com/incoming",
      "subscribed_to": ["Contact Created", "Replies"],
      "subscribed_to_tags": [],
      "created_at": "2026-06-09T12:00:00.000Z",
      "signing_enabled": true,
      "signing_secret_created_at": "2026-07-15T09:30:00.000Z",
      "retries_enabled": true,
      "enabled": true,
      "apply_to_sub_accounts": false
    }
  ]
}
```

`signing_enabled` et `retries_enabled` sont des options activables par abonnement, toutes deux désactivées par défaut. Voir [Charges utiles signées](#signed-payloads) et [Nouvelles tentatives](#retries).

`apply_to_sub_accounts` est l'option d'héritage d'agence — voir [Un abonnement pour tous les comptes clients](#one-subscription-for-all-client-accounts-agencies). Désactivé par défaut, et inerte sur les comptes qui n'ont pas de comptes clients.

`enabled` est l'interrupteur marche/arrêt de l'abonnement — voir [Désactivation d'un abonnement](#switching-a-subscription-off). Les abonnements désactivés sont toujours listés ici.

Le secret de signature lui-même n'est jamais inclus ici — lisez-le depuis [`GET /webhooks/{id}/signing-secret`](#read-the-signing-secret).

---

## Lister les types d'événements abonnables

Renvoie les chaînes exactes que vous pouvez utiliser dans `subscribed_to`. Utilisez ceci pour découvrir les noms d'événements valides plutôt que de les coder en dur.

`GET /webhooks/events`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/webhooks/events" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/events", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/webhooks/events",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Réponse**

La réponse est `{"success": true, "events": [...]}`, où `events` contient actuellement 22 chaînes exactes : Contact Created, Human Alerted, Appointment Booked, Replies, Reads, Deliveries, Credits Spent, Credits Recharged, Low Credit Balance, Contact Paused, Contact Do Not Disturb, Contact Unarchived, New Message, Contact Resumed, Chat Concluded, Task Created, Task Updated, Task Completed, Daily Summary Created, Channel Connected, Broadcast Started et Broadcast Completed (Channel Connected est accepté dans `subscribed_to` mais rien ne l'émet actuellement, donc ne développez rien en vous basant dessus).

Pour connaître la signification de chaque événement et le code `event` qu'il envoie dans la charge utile, consultez [Les 22 événements Webhook](../integrations/webhooks.md#the-22-webhook-events). Ce point de terminaison constitue la liste faisant autorité à tout moment — lisez-la en direct plutôt que de coder les noms en dur.

---

## Créer un abonnement

`POST /webhooks`

| Champ | Requis | Description |
|---|---|---|
| `url` | Oui | URL HTTPS qui recevra les charges utiles d'événements via `POST`. Doit être accessible publiquement. |
| `subscribed_to` | Oui | Un tableau non vide de noms d'événements (voir `/webhooks/events`). |
| `name` | Non | Un nom d'affichage. Également utilisable comme `{webhookId}` plus tard. Par défaut, un nom horodaté. |
| `subscribed_to_tags` | Non | Identifiants de balises qui restreignent les balises produisant une notification de résumé de conversation. Cela ne limite pas les événements de l'abonnement à ces balises — pour recevoir une requête lorsqu'une balise spécifique est appliquée, définissez une URL de webhook sur cette balise dans l'onglet **Balises** de l'agent (ou de la campagne). |
| `retries_enabled` | Non | Booléen, par défaut `false`. Activez les [nouvelles tentatives](#retries) en cas d'échec de livraison. |
| `generate_signing_secret` | Non | Booléen, par défaut `false`. Générez un [secret de signature](#signed-payloads) HMAC avec l'abonnement. Le secret est renvoyé une seule fois, en tant que `signing_secret` de premier niveau dans la réponse. |
| `enabled` | Non | Booléen, par défaut `true`. Passez `false` pour créer l'abonnement désactivé. Voir [Désactivation d'un abonnement](#switching-a-subscription-off). |
| `apply_to_sub_accounts` | Non | Booléen, par défaut `false`. Sur un compte d'agence, `true` permet à cet abonnement de recevoir également les événements de chaque compte client — voir [Un abonnement pour tous les comptes clients](#one-subscription-for-all-client-accounts-agencies). |

> **Règles d'URL :** L'URL doit utiliser `https://` et être accessible publiquement. Les adresses `http://` simples, `localhost`, les adresses de réseau privé et les adresses internes à la plateforme sont rejetées avec une `400`.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "name": "Order updates hook"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://hooks.example.com/incoming",
    subscribed_to: ["Contact Created", "Replies"],
    name: "Order updates hook",
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/webhooks",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "url": "https://hooks.example.com/incoming",
        "subscribed_to": ["Contact Created", "Replies"],
        "name": "Order updates hook",
    },
)
data = res.json()
```

**Réponse**

```json
{
  "success": true,
  "webhook_id": "1",
  "webhook": {
    "id": "1",
    "name": "Order updates hook",
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "subscribed_to_tags": [],
    "created_at": "2026-06-09T12:00:00.000Z"
  }
}
```

---

## Mettre à jour un abonnement

Fournissez au moins l'un des éléments suivants : `url`, `subscribed_to`, `name`, `subscribed_to_tags`, `retries_enabled`, `enabled` ou `apply_to_sub_accounts`. Les champs omis conservent leurs valeurs actuelles. `subscribed_to` et `subscribed_to_tags` sont des remplacements, pas des fusions.

`PUT /webhooks/{webhookId}`

> La mise à jour d'un abonnement ne perturbe jamais son secret de signature — gérez-le via les [routes de secret de signature](#signed-payloads).

> Lorsque l'URL change, la distribution pour la nouvelle URL est automatiquement réactivée, ce qui donne un nouveau départ à un point de terminaison précédemment défaillant.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/Order%20updates%20hook" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/v2/incoming",
    "subscribed_to": ["Replies", "Chat Concluded"]
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  `https://api.youraiconnector.com/v1/webhooks/${encodeURIComponent("Order updates hook")}`,
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      url: "https://hooks.example.com/v2/incoming",
      subscribed_to: ["Replies", "Chat Concluded"],
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/webhooks/Order updates hook",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "url": "https://hooks.example.com/v2/incoming",
        "subscribed_to": ["Replies", "Chat Concluded"],
    },
)
data = res.json()
```

**Réponse**

```json
{
  "success": true,
  "webhook_id": "0",
  "webhook": {
    "id": "0",
    "name": "Order updates hook",
    "url": "https://hooks.example.com/v2/incoming",
    "subscribed_to": ["Replies", "Chat Concluded"],
    "subscribed_to_tags": [],
    "created_at": "2026-06-09T12:00:00.000Z"
  }
}
```

Un identifiant ou un nom inconnu renvoie `404` avec `{ "success": false, "error": "Webhook not found" }`.

---

## Supprimer un abonnement

Supprime l'abonnement afin que son URL cesse de recevoir des charges utiles. Ses compteurs d'état de distribution sont réinitialisés, de sorte que la réajout de la même URL plus tard commence avec un historique vierge.

`DELETE /webhooks/{webhookId}`

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/webhooks/0",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Réponse**

```json
{
  "success": true
}
```

---

## Envoyer une charge utile de test

Envoie un exemple de charge utile à l'URL de l'abonnement afin que vous puissiez vérifier votre récepteur de bout en bout. Passez éventuellement un `event` pour contrôler le type d'événement que l'exemple simule. Les livraisons de test n'affectent jamais les compteurs de santé de l'abonnement.

`POST /webhooks/{webhookId}/test`

La réponse renvoie toujours `200` et signale le résultat avec un indicateur `delivered` — un test échoué ne renvoie **pas** de statut d'erreur. Lorsque `delivered` est `false`, la réponse inclut les détails de l'échec.

| Champ | Requis | Description |
|---|---|---|
| `event` | Non | Type d'événement à simuler (doit être l'un des `/webhooks/events`). Par défaut, il s'agit d'un événement de livraison. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/test?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "event": "Contact Created" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/test", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ event: "Contact Created" }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/webhooks/0/test",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"event": "Contact Created"},
)
data = res.json()
```

**Réponse** (livré)

```json
{
  "success": true,
  "webhook_id": "0",
  "delivered": true
}
```

**Réponse** (échec)

```json
{
  "success": true,
  "webhook_id": "0",
  "delivered": false,
  "failure_type": "permanent",
  "status_code": 404,
  "error_message": "Request failed with status code 404"
}
```

`failure_type` est l'un des `permanent`, `temporary`, `timeout`, `network` ou `unknown`.

---

## Vérifier la santé de la livraison

Renvoie l'enregistrement de santé de la livraison pour l'URL de l'abonnement : combien de livraisons ont réussi et échoué, si la livraison est actuellement suspendue après des échecs répétés, et les détails du dernier échec. Renvoie `"health": null` lorsqu'aucune livraison n'a encore été tentée.

`GET /webhooks/{webhookId}/health`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/webhooks/0/health" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/health", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/webhooks/0/health",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Réponse**

```json
{
  "success": true,
  "webhook_id": "0",
  "url": "https://hooks.example.com/incoming",
  "health": {
    "consecutive_failures": 0,
    "total_failures": 2,
    "total_successes": 120,
    "is_disabled": false,
    "disabled_at": null,
    "disabled_reason": null,
    "last_failure": null,
    "last_success_at": "2026-06-09T12:00:00.000Z",
    "created_at": "2026-05-01T08:00:00.000Z",
    "updated_at": "2026-06-09T12:00:00.000Z"
  }
}
```

Lorsque `is_disabled` est `true`, la livraison vers l'URL a été suspendue automatiquement après des échecs répétés. Corrigez votre récepteur, puis réactivez-la (ci-dessous).

---

## Réactiver la livraison

Reprend la livraison pour un webhook dont l'URL a été suspendue automatiquement après des échecs répétés. Cela réinitialise l'indicateur de suspension et les compteurs d'échecs, mais ne tente **pas** de livraison — utilisez le point de terminaison de test par la suite pour confirmer que votre récepteur est à nouveau opérationnel.

`POST /webhooks/{webhookId}/reenable`

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/reenable?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/webhooks/0/reenable", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/webhooks/0/reenable",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Réponse**

```json
{
  "success": true,
  "webhook_id": "0"
}
```

---

## Désactivation d'un abonnement

`enabled` est l'interrupteur marche/arrêt propre à l'abonnement. Le désactiver arrête les livraisons tout en conservant l'URL, la liste des événements et le secret de signature intacts.

```bash
# Off
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

# Back on
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'
```

- **L'absence signifie activé.** Un abonnement créé avant l'existence de ce champ n'a aucune valeur `enabled` stockée et effectue les livraisons normalement. `GET /webhooks` renvoie toujours un booléen concret.
- Les abonnements désactivés sont **toujours listés** par `GET /webhooks` — c'est ainsi que vous les trouvez pour les réactiver.
- Une [nouvelle tentative](#retries) mise en file d'attente avant la désactivation ne reprend pas : la nouvelle tentative relit l'abonnement au moment de l'envoi et l'abandonne s'il est désactivé.
- Rien de ce qui a été supprimé pendant la désactivation n'est rejoué lorsque vous le réactivez.

> Distinct de la désactivation automatique après des échecs répétés, qui est signalée par [`GET /webhooks/{id}/health`](#check-delivery-health) comme `is_disabled` et effacée avec [`POST /webhooks/{id}/reenable`](#re-enable-delivery). `enabled` est l'interrupteur du compte ; `is_disabled` est le nôtre. Aucun ne remplace l'autre — un abonnement doit être à la fois activé et ne pas être désactivé automatiquement pour effectuer des livraisons.

---

## Un abonnement pour tous les comptes clients (agences)

Sur un compte d'agence, définissez `apply_to_sub_accounts: true` sur un abonnement (au moment de la création ou via `PUT`) et il recevra également les événements qui se produisent sur chacun des comptes clients de l'agence — un seul point de terminaison couvre toute l'agence, au lieu de recréer l'abonnement sur chaque compte client.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"apply_to_sub_accounts": true}'
```

Fonctionnement :

- **Le bloc `user` permet de distinguer les comptes.** Le bloc `user` de chaque charge utile identifie le compte sur lequel l'événement s'est réellement produit, afin que votre récepteur puisse effectuer le routage par client.
- **Les paramètres propres à l'abonnement de l'agence s'appliquent partout.** Sa liste d'événements, son [secret de signature](#signed-payloads) et son option de [nouvelle tentative](#retries) sont également utilisés pour les livraisons héritées.
- **L'abonnement propre à un compte client vers la même URL est prioritaire.** Si un compte client possède son propre abonnement pointant vers la même URL, celui-ci est utilisé pour les événements de ce compte — le même événement n'est jamais livré deux fois à un point de terminaison.
- **Les comptes clients ne le voient pas.** Les abonnements hérités n'apparaissent pas dans la liste des webhooks d'un compte client, et le client ne peut pas les désactiver — seule l'agence les gère.
- **L'état de santé de la livraison est suivi par compte client.** Un point de terminaison qui continue d'échouer est automatiquement désactivé pour le compte dont les livraisons ont échoué, et non pour toute l'agence.
- **`subscribed_to_tags` n'est pas hérité.** La liste des balises fait référence aux balises propres à l'agence, qui n'existent pas sur les comptes clients — la restriction du résumé de conversation ne s'applique qu'aux événements propres à l'agence.
- **Inerte ailleurs.** Sur un compte sans compte client, l'indicateur est stocké correctement et n'a aucun effet.

---

## En-têtes sur chaque livraison

Ces trois en-têtes sont envoyés à chaque livraison, que l'abonnement soit signé ou non :

| En-tête | Signification |
|---|---|
| `X-Webhook-Delivery` | Identifiant stable pour l'événement logique. Identique lors des tentatives — utilisez-le pour la déduplication. |
| `X-Webhook-Attempt` | Numéro de tentative commençant à 1. |
| `X-Webhook-Event` | Le nom de l'événement. |

---

## Charges utiles signées

La signature est facultative, désactivée par défaut et définie par abonnement. Lorsqu'un abonnement possède un secret de signature, chaque livraison comporte deux en-têtes supplémentaires en plus des trois envoyés à chaque livraison (`X-Webhook-Delivery`, `X-Webhook-Attempt` et `X-Webhook-Event`) :

| En-tête | Signification |
|---|---|
| `X-Webhook-Signature` | `v1=<hex>` — HMAC-SHA256 de la chaîne `"<timestamp>.<raw request body>"`, chiffrée avec le secret de signature par webhook que vous générez et faites pivoter sur `GET/POST/DELETE /v1/webhooks/{webhookId}/signing-secret`. |
| `X-Webhook-Timestamp` | Heure d'envoi, en secondes Unix. Intégrée à la signature, elle ne peut donc pas être modifiée indépendamment. |

Pour vérifier, recalculez le HMAC-SHA256 sur le corps brut avec votre secret et comparez-le à l'en-tête. Vérifiez par rapport au corps de la requête **brut**. La re-sérialisation du JSON analysé modifie les octets et rompt la comparaison. Rejetez les livraisons dont l'horodatage est en dehors d'une fenêtre de fraîcheur (300s est une valeur par défaut raisonnable) pour empêcher la relecture, et comparez avec une fonction sécurisée contre les attaques temporelles.

Voir [Charges utiles signées](../integrations/webhooks.md#signed-payloads-verifying-a-webhook-really-came-from-us) pour des exemples complets de vérification en Node et Python.

> **La signature n'est pas la même chose que l'authentification API.** L'API REST elle-même s'authentifie avec des clés API plutôt qu'avec OAuth (OAuth 2.1 existe pour les serveurs MCP que vous enregistrez en tant qu'outils de bot), et il n'existe pas encore de paquets SDK officiels npm ou PyPI — appelez les points de terminaison avec n'importe quel client HTTP.

### Lire le secret de signature

`GET /webhooks/{id}/signing-secret`

```bash
curl "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
```

**Réponse**

```json
{
  "success": true,
  "webhook_id": "0",
  "signing_enabled": true,
  "signing_secret": "whsec_1a2b3c...",
  "signing_secret_created_at": "2026-07-15T09:30:00.000Z"
}
```

Lorsque la signature est désactivée, `signing_enabled` est `false` et `signing_secret` est `null`.

### Générer ou faire pivoter le secret de signature

`POST /webhooks/{id}/signing-secret`

Crée un secret (en activant la signature) ou remplace le secret existant. Renvoie le nouveau secret.

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
```

**Réponse**

```json
{
  "success": true,
  "webhook_id": "0",
  "signing_enabled": true,
  "signing_secret": "whsec_9f8e7d...",
  "signing_secret_created_at": "2026-07-15T10:00:00.000Z"
}
```

La rotation prend effet immédiatement — la prochaine livraison est signée uniquement avec le nouveau secret. Acceptez brièvement les deux secrets pendant que vous déployez le changement sur un point de terminaison en production.

Vous pouvez également générer un secret lors de la création en passant `"generate_signing_secret": true` à `POST /webhooks` ; la réponse inclut alors un champ `signing_secret` de premier niveau.

### Désactiver la signature

`DELETE /webhooks/{id}/signing-secret`

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/webhooks/0/signing-secret?apiKey=YOUR_API_KEY"
```

**Réponse**

```json
{
  "success": true,
  "webhook_id": "0",
  "signing_enabled": false
}
```

> Les trois routes de secret de signature nécessitent l'autorisation **edit** (modification) des intégrations, y compris `GET` — le secret est un identifiant qui peut falsifier des livraisons, il n'est donc pas exposé aux rôles en lecture seule.

---

## Tentatives de renvoi

Optionnel, désactivé par défaut, et défini par abonnement via le booléen `retries_enabled` sur `POST /webhooks` ou `PUT /webhooks/{id}`.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/webhooks/0?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"retries_enabled": true}'
```

Lorsqu'elle est activée, une livraison échouée est relancée à **1m, 5m, 30m et 2h** après la première tentative (environ 2h40m de couverture).

- **Relancé :** réponses 5xx, délais d'attente et échecs de connexion.
- **Non relancé :** toute erreur 4xx. Le récepteur rejette la requête elle-même, donc la rejouer sans modification ne fait que reproduire le rejet.

Les réessais rendent possible la livraison en double — un point de terminaison qui a traité un événement mais a expiré avant de répondre le recevra à nouveau. Effectuez la déduplication sur `X-Webhook-Delivery`, qui reste constant entre les tentatives. C'est pourquoi les réessais sont facultatifs.

Les compteurs [delivery-health](#check-delivery-health) comptent une livraison entière, et non chaque tentative : un échec n'est enregistré qu'une fois que toutes les tentatives sont épuisées, donc l'activation des tentatives de renvoi ne déclenche pas la désactivation automatique plus rapidement.

---

## Erreurs

Toutes les erreurs utilisent l'enveloppe standard :

```json
{
  "success": false,
  "error": "Webhook not found"
}
```

Cas courants : une URL non autorisée, un `subscribed_to` vide/invalide ou des champs manquants renvoient `400` ; un identifiant ou un nom inconnu renvoie `404` ; et un `403` signifie que les webhooks ne sont pas activés pour votre compte. Consultez la section [Erreurs](errors-and-pagination.md) pour obtenir la liste complète.

---

## Étapes suivantes

- [Webhooks (réception de charges utiles)](../integrations/webhooks.md) — configurez votre récepteur et comprenez la structure de la charge utile.
- [Authentification](authentication.md) — les quatre méthodes pour authentifier une requête.
- [Erreurs et limites de débit](errors-and-pagination.md) — codes d'état et limite de 300 req/min.
