> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boble.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Types d'événements

> Tous les événements que Boble peut envoyer, ce que chacun signifie pour votre business, et un exemple de payload complet.

Cette page est la référence des événements émis par Boble. Pour chacun, vous trouverez :

* **Quand il se déclenche** — en langage clair, avec la transition technique sous-jacente.
* **Ce que ça veut dire** — ce qui vient de se passer pour votre business.
* **Ce que vous pouvez en faire** — des idées concrètes que des créateurs utilisent aujourd'hui.
* **Payload complet** — un exemple réel, prêt à coller dans votre handler.

Tous les événements `user_promotion.*` partagent les mêmes objets imbriqués (`user`, `promotion`). Seuls le `type` au niveau racine, le `status` et les champs de dates changent entre les transitions. L'enveloppe commune est documentée dans [Structure du payload](/fr/webhooks/payload-structure).

***

## `user_promotion.access_granted`

Un acheteur vient d'obtenir l'accès à l'une de vos promotions.

### Quand il se déclenche

* Un acheteur a complété un checkout payant en one-off.
* Un acheteur a démarré un abonnement (Stripe `customer.subscription.created`).
* Un acheteur a réclamé une promotion gratuite.
* Vous avez accordé l'accès manuellement depuis votre dashboard.

### Ce que ça veut dire

Cette personne est désormais **membre actif** de cette promotion. Elle peut consommer le contenu, assister aux sessions, ou tout ce que la promotion débloque. C'est le moment où votre business a gagné un nouveau client sur ce produit.

### Ce que vous pouvez en faire

* Envoyer une notif "🎉 Nouvelle vente" à votre équipe sur Discord ou Slack avec le nom, l'email de l'acheteur et le titre de la promotion.
* Ajouter l'acheteur à une liste Mailchimp / Brevo / ConvertKit, taggé avec la promotion achetée, pour l'embarquer dans votre séquence d'onboarding.
* Lui donner un rôle sur votre Discord, un accès dans un workspace Notion ou toute autre ressource gatée derrière la promotion.
* Ajouter une nouvelle ligne dans une Google Sheet pour votre log des ventes.

### Payload

```json theme={null}
{
  "id": "0d6d31a3-2b9e-4d9f-9a51-3b9c3f8e6c10",
  "type": "user_promotion.access_granted",
  "api_version": "2026-01-01",
  "created": 1717497600,
  "livemode": true,
  "data": {
    "object": {
      "id": "f3e4c9e2-31a8-4d1c-9c4a-e8d2b3a17a44",
      "user_id": "2c47a8d4-5e3a-4b1c-9f8d-71a2b8c3d4e5",
      "promotion_id": "6a5c1b3e-2f8d-4a9b-9c7d-8e1f2a3b4c5d",
      "promotion_payment_id": "b9d8c7e6-5a4b-3c2d-1e0f-9a8b7c6d5e4f",
      "status": "active",
      "start_date": "2026-06-04T12:00:00.000Z",
      "end_date": null,
      "user": {
        "id": "2c47a8d4-5e3a-4b1c-9f8d-71a2b8c3d4e5",
        "email": "lea.martin@example.com",
        "firstname": "Léa",
        "lastname": "Martin",
        "username": "lea.m",
        "avatar": "https://cdn.boble.app/uploads/users/2c47.../avatar.jpg",
        "preferred_language": "fr",
        "created_at": "2026-04-12T09:31:00.000Z"
      },
      "promotion": {
        "id": "6a5c1b3e-2f8d-4a9b-9c7d-8e1f2a3b4c5d",
        "title": "Pro membership",
        "type": "subscription",
        "currency": "EUR",
        "amount": 19
      }
    }
  }
}
```

### Champs à retenir

* `status` vaut `active`.
* `start_date` est le moment exact où l'accès a commencé.
* `end_date` vaut `null` pour les abonnements ouverts et les accès en cours.
* `promotion.type` vous dit s'il s'agit d'une réclamation `free`, d'un achat `one_time` ou d'un démarrage d'abonnement `subscription`.
* `promotion_payment_id` vaut `null` pour les promotions gratuites et les attributions manuelles.

***

## `user_promotion.canceled`

L'accès d'un acheteur vient d'être annulé.

### Quand il se déclenche

* L'acheteur a annulé son abonnement depuis son compte.
* Vous avez annulé son accès manuellement depuis votre dashboard.
* Stripe a reporté l'abonnement comme supprimé (`customer.subscription.deleted`).

### Ce que ça veut dire

Cet acheteur **n'a plus accès** à la promotion. Pour un abonnement, c'est l'équivalent de "il s'est désabonné". Pour un one-off, c'est une révocation manuelle de votre côté.

### Ce que vous pouvez en faire

* Glisser une note discrète dans votre canal Discord/Slack pour savoir que quelqu'un a churné et lui écrire si vous le souhaitez.
* Retirer le tag de l'acheteur dans votre outil email, ou le déplacer dans un segment "ancien client" pour une séquence de win-back.
* Révoquer le rôle que vous lui aviez donné sur votre Discord, ou retirer son accès Notion.
* Mettre à jour votre dashboard de churn.

### Payload

```json theme={null}
{
  "id": "1b6e22c8-9d11-4f0e-8b2a-7c5d9e0f1a23",
  "type": "user_promotion.canceled",
  "api_version": "2026-01-01",
  "created": 1719312800,
  "livemode": true,
  "data": {
    "object": {
      "id": "f3e4c9e2-31a8-4d1c-9c4a-e8d2b3a17a44",
      "user_id": "2c47a8d4-5e3a-4b1c-9f8d-71a2b8c3d4e5",
      "promotion_id": "6a5c1b3e-2f8d-4a9b-9c7d-8e1f2a3b4c5d",
      "promotion_payment_id": "b9d8c7e6-5a4b-3c2d-1e0f-9a8b7c6d5e4f",
      "status": "canceled",
      "start_date": "2026-06-04T12:00:00.000Z",
      "end_date": "2026-06-25T08:13:20.000Z",
      "user": {
        "id": "2c47a8d4-5e3a-4b1c-9f8d-71a2b8c3d4e5",
        "email": "lea.martin@example.com",
        "firstname": "Léa",
        "lastname": "Martin",
        "username": "lea.m",
        "avatar": "https://cdn.boble.app/uploads/users/2c47.../avatar.jpg",
        "preferred_language": "fr",
        "created_at": "2026-04-12T09:31:00.000Z"
      },
      "promotion": {
        "id": "6a5c1b3e-2f8d-4a9b-9c7d-8e1f2a3b4c5d",
        "title": "Pro membership",
        "type": "subscription",
        "currency": "EUR",
        "amount": 19
      }
    }
  }
}
```

### Champs à retenir

* `status` vaut `canceled`.
* `end_date` est le moment exact où l'accès a pris fin.
* Le même `id` que l'`access_granted` d'origine — c'est le même `user_promotion`, juste passé à un autre statut.

***

## `user_promotion.expired`

Un abonnement est arrivé à terme sans être renouvelé.

### Quand il se déclenche

* Un abonnement coincé en `past_due` est définitivement abandonné (Stripe a arrêté d'essayer de le débiter).
* Un accès à durée fixe a atteint sa date de fin.

### Ce que ça veut dire

L'acheteur **a perdu l'accès** parce que son abonnement est arrivé au bout. C'est différent de `canceled` : l'acheteur n'a pas choisi d'annuler, l'accès s'est simplement éteint (le plus souvent après plusieurs tentatives de prélèvement infructueuses).

### Ce que vous pouvez en faire

* Déclencher une séquence email différente de celle de `canceled` — typiquement un rappel "votre abonnement a expiré, voici le lien pour vous réabonner" plutôt qu'un win-back.
* Retirer ses accès dans vos outils externes, comme pour `canceled`.
* Logguer l'expiration dans votre dashboard pour monitorer le succès de votre dunning.

### Payload

```json theme={null}
{
  "id": "2c7f33d9-ae22-501f-9c3b-8d6e0f1b2c34",
  "type": "user_promotion.expired",
  "api_version": "2026-01-01",
  "created": 1721904000,
  "livemode": true,
  "data": {
    "object": {
      "id": "f3e4c9e2-31a8-4d1c-9c4a-e8d2b3a17a44",
      "user_id": "2c47a8d4-5e3a-4b1c-9f8d-71a2b8c3d4e5",
      "promotion_id": "6a5c1b3e-2f8d-4a9b-9c7d-8e1f2a3b4c5d",
      "promotion_payment_id": "b9d8c7e6-5a4b-3c2d-1e0f-9a8b7c6d5e4f",
      "status": "expired",
      "start_date": "2026-06-04T12:00:00.000Z",
      "end_date": "2026-07-25T12:00:00.000Z",
      "user": {
        "id": "2c47a8d4-5e3a-4b1c-9f8d-71a2b8c3d4e5",
        "email": "lea.martin@example.com",
        "firstname": "Léa",
        "lastname": "Martin",
        "username": "lea.m",
        "avatar": "https://cdn.boble.app/uploads/users/2c47.../avatar.jpg",
        "preferred_language": "fr",
        "created_at": "2026-04-12T09:31:00.000Z"
      },
      "promotion": {
        "id": "6a5c1b3e-2f8d-4a9b-9c7d-8e1f2a3b4c5d",
        "title": "Pro membership",
        "type": "subscription",
        "currency": "EUR",
        "amount": 19
      }
    }
  }
}
```

### Champs à retenir

* `status` vaut `expired`.
* `end_date` est le moment où l'accès a effectivement pris fin (typiquement après la fenêtre de dunning).

***

## `user_promotion.suspended`

Un prélèvement récurrent a échoué et l'accès de l'acheteur est mis en pause.

### Quand il se déclenche

* Une facture d'abonnement n'a pas pu être débitée. Stripe reporte l'abonnement comme `past_due` et Boble suspend l'accès.

### Ce que ça veut dire

L'acheteur **existe toujours** en tant que client, mais son accès est **temporairement bloqué** jusqu'à ce que le paiement aboutisse. C'est votre fenêtre de dunning — la plupart du temps, les paiements repassent à la deuxième ou troisième tentative et vous recevrez un nouvel `access_granted` à ce moment-là. S'ils ne repassent jamais, vous recevrez finalement un `expired`.

<Note>
  Cet événement n'est émis qu'à l'entrée dans le statut `past_due`. Une reprise réussie ne redéclenche pas `suspended` — elle déclenche `access_granted`.
</Note>

### Ce que vous pouvez en faire

* Envoyer un email à l'acheteur avec un lien pour mettre à jour son moyen de paiement. C'est une des actions à plus fort ROI qu'on puisse brancher sur un webhook.
* Mettre en pause son accès dans vos outils externes, mais **sans le révoquer définitivement** — il y a de bonnes chances qu'il revienne.
* L'ajouter à un segment "dunning" dans votre CRM pour assurer le suivi.

### Payload

```json theme={null}
{
  "id": "3d8044ea-bf33-612a-ad4c-9e7f1a2c3d45",
  "type": "user_promotion.suspended",
  "api_version": "2026-01-01",
  "created": 1720008400,
  "livemode": true,
  "data": {
    "object": {
      "id": "f3e4c9e2-31a8-4d1c-9c4a-e8d2b3a17a44",
      "user_id": "2c47a8d4-5e3a-4b1c-9f8d-71a2b8c3d4e5",
      "promotion_id": "6a5c1b3e-2f8d-4a9b-9c7d-8e1f2a3b4c5d",
      "promotion_payment_id": "b9d8c7e6-5a4b-3c2d-1e0f-9a8b7c6d5e4f",
      "status": "past_due",
      "start_date": "2026-06-04T12:00:00.000Z",
      "end_date": null,
      "user": {
        "id": "2c47a8d4-5e3a-4b1c-9f8d-71a2b8c3d4e5",
        "email": "lea.martin@example.com",
        "firstname": "Léa",
        "lastname": "Martin",
        "username": "lea.m",
        "avatar": "https://cdn.boble.app/uploads/users/2c47.../avatar.jpg",
        "preferred_language": "fr",
        "created_at": "2026-04-12T09:31:00.000Z"
      },
      "promotion": {
        "id": "6a5c1b3e-2f8d-4a9b-9c7d-8e1f2a3b4c5d",
        "title": "Pro membership",
        "type": "subscription",
        "currency": "EUR",
        "amount": 19
      }
    }
  }
}
```

### Champs à retenir

* `status` vaut `past_due` (et non `suspended` — `suspended` est le nom de l'événement, le statut sous-jacent est `past_due`).
* `end_date` reste à `null` car l'accès est en pause, pas terminé.

***

## `webhook.test`

Un événement de test que vous avez déclenché manuellement depuis votre dashboard.

### Quand il se déclenche

Vous avez cliqué sur le bouton "Envoyer un événement de test" (ou appelé l'API correspondante). L'événement de test est envoyé **même si votre endpoint est désactivé**, pour que vous puissiez valider la connectivité avant de l'activer.

### Ce que ça veut dire

Rien ne s'est passé sur un vrai acheteur. C'est un test de bon fonctionnement pour confirmer que :

* Votre endpoint est joignable.
* Votre handler accepte une livraison de webhook Boble.
* Votre vérification de signature fonctionne.

### Ce que vous pouvez en faire

* L'utiliser après chaque déploiement de votre handler pour confirmer que tout marche encore, sans attendre une vraie vente.
* L'utiliser une fois au moment de l'intégration pour valider votre code de vérification.

### Payload

```json theme={null}
{
  "id": "8c00aabb-ccdd-eeff-1122-334455667788",
  "type": "webhook.test",
  "api_version": "2026-01-01",
  "created": 1717497600,
  "livemode": false,
  "data": {
    "object": {
      "message": "This is a test event",
      "endpoint_id": "8c12e3f4-1a2b-3c4d-5e6f-7a8b9c0d1e2f",
      "sent_at": "2026-06-04T12:00:00.000Z"
    }
  }
}
```

### Champs à retenir

* `data.object` est volontairement minimal — pas d'acheteur, pas de promotion, juste un marqueur indiquant qu'il s'agit d'un test.
* `livemode` vaut `false` en dehors de la production.
* La livraison de test apparaît quand même dans votre log d'événements, pour que vous puissiez inspecter ce que votre endpoint a répondu.
