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

# Événements

> Les 12 événements Pulses : quand ils partent, ce qu'ils contiennent, avec un exemple pour chacun.

Chaque envoi est une requête `POST` JSON avec la même enveloppe :

```json theme={null}
{
  "id": "evt_3f9c0a71d2b84e5a",
  "event": "sale.completed",
  "created_at": "2026-10-29T16:17:10.000Z",
  "store": { "id": "cm1store01", "name": "Ma boutique" },
  "data": { }
}
```

`id` est **stable** : le même événement garde le même identifiant, même s'il est relancé. C'est votre clé de dédoublonnage. Le contenu de `data` dépend de l'événement ; les objets `sale`, `license` et `product` ont exactement la même forme que dans l'[API](https://docs.pulse-sell.com/api-reference/introduction).

## Vue d'ensemble

| Événement | Groupe | Quand |
| - | - | - |
| [`sale.completed`](#sale-completed) | Ventes | Un paiement est confirmé. |
| [`sale.failed`](#sale-failed) | Ventes | Un paiement échoue, est refusé ou expire. |
| [`sale.abandoned`](#sale-abandoned) | Ventes | Une commande reste impayée (détectée après une heure). |
| [`sale.refunded`](#sale-refunded) | Ventes | Un paiement est remboursé. |
| [`order.created`](#order-created) | Ventes | Une commande est créée (paiement pas encore confirmé). |
| [`license.issued`](#license-issued) | Licences | Une clé est attribuée après un achat. |
| [`license.activated`](#license-activated) | Licences | Une clé est activée sur un appareil. |
| [`license.expiring`](#license-expiring) | Licences | Une licence expire dans 7 jours ou moins. |
| [`license.expired`](#license-expired) | Licences | Une licence vendue vient d'expirer. |
| [`license.revoked`](#license-revoked) | Licences | Une licence est révoquée. |
| [`affiliate.joined`](#affiliate-joined) | Affiliation | Un affilié génère son premier lien pour l'un de vos produits. |
| [`product.published`](#product-published) | Catalogue | Un produit passe en ligne. |

> [!TIP]
>
> Abonnez-vous à `*` pour recevoir **tous** les événements, y compris ceux que nous ajouterons plus tard. Ignorez simplement ceux que votre code ne connaît pas : c'est la manière la plus sûre de ne rien manquer.

## Ventes

### sale.completed

Le paiement est confirmé : c'est le signal pour livrer, facturer, notifier votre équipe. C'est le seul signal fiable d'un paiement réussi (ne vous fiez pas à la page de retour du client).

```json theme={null}
{
  "id": "evt_3f9c0a71d2b84e5a",
  "event": "sale.completed",
  "created_at": "2026-10-29T16:17:10.000Z",
  "store": { "id": "cm1store01", "name": "Ma boutique" },
  "data": {
    "sale": {
      "id": "cm1sale001", "number": "PS-20261029-0042", "status": "completed", "payment_status": "completed",
      "amount": { "total": { "value": 20000, "formatted": "20 000 F CFA", "currency": "XOF" } },
      "items": [ { "product_id": "cm1prod001", "name": "Guide complet", "quantity": 1 } ]
    },
    "customer": { "email": "awa@example.com", "name": "Awa Koné", "phone": "+2250700000000" }
  }
}
```

### sale.failed

Sert à relancer le client ou à comprendre un problème de moyen de paiement. `data.failure.reason` donne la cause quand elle est connue (300 caractères maximum).

```json theme={null}
{ "event": "sale.failed", "data": { "sale": { "id": "cm1sale002", "payment_status": "failed" }, "customer": { "email": "awa@example.com" }, "failure": { "reason": "failed" } } }
```

### sale.abandoned

Un client a commencé une commande sans payer. Détecté par une tâche périodique, au bout d'une heure ; un seul événement par commande. Idéal pour une relance WhatsApp ou e-mail.

```json theme={null}
{ "event": "sale.abandoned", "data": { "sale": { "id": "cm1sale003", "payment_status": "pending" }, "customer": { "email": "awa@example.com" }, "abandoned": { "since": "2026-10-29T15:10:00.000Z" } } }
```

### sale.refunded

Un paiement est remboursé (depuis le tableau de bord).

```json theme={null}
{ "event": "sale.refunded", "data": { "sale": { "id": "cm1sale001" }, "customer": { "email": "awa@example.com" }, "refund": { "payment_id": "cm1pay001", "amount": 20000, "reason": "Demande du client" } } }
```

### order.created

Une commande existe mais n'est pas encore payée. Utile pour réserver du stock ou suivre l'entonnoir. Pour savoir qu'elle est payée, attendez `sale.completed`.

## Licences

Tous les événements de licence contiennent `license`, `product` et `customer.email`, plus `sale.id` quand la licence vient d'une commande.

### license.issued

Une clé est attribuée à un client après son achat.

```json theme={null}
{
  "event": "license.issued",
  "data": {
    "license": { "id": "cm1lic001", "key": "ABCD-1234-EFGH-5678", "status": "active", "max_activations": 3, "activations_count": 0, "expires_at": "2027-10-29T00:00:00.000Z" },
    "product": { "id": "cm1prod002", "name": "Mon logiciel" },
    "customer": { "email": "awa@example.com" },
    "sale": { "id": "cm1sale001" }
  }
}
```

### license.activated

Une clé est activée sur un appareil. `license.activations` liste les appareils actuels.

### license.expiring

Une licence expire dans **7 jours ou moins**. `data.days_until_expiry` donne le nombre de jours restants : parfait pour déclencher un rappel de renouvellement. Un seul événement par date d'expiration : si vous prolongez la licence, un nouvel événement pourra partir pour la nouvelle date.

```json theme={null}
{ "event": "license.expiring", "data": { "license": { "id": "cm1lic001", "expires_at": "2026-11-04T00:00:00.000Z" }, "product": { "id": "cm1prod002", "name": "Mon logiciel" }, "customer": { "email": "awa@example.com" }, "days_until_expiry": 6 } }
```

### license.expired

Une licence **vendue** vient d'expirer (dans les 48 dernières heures). Les clés jamais vendues ou déjà révoquées n'envoient rien.

### license.revoked

Une licence est révoquée, par vous ou à la suite d'un remboursement. `data.reason` donne la raison quand elle est connue.

## Affiliation

### affiliate.joined

Un affilié génère son premier lien pour l'un de vos produits. Un seul événement par affilié.

```json theme={null}
{ "event": "affiliate.joined", "data": { "affiliate": { "id": "cm1aff001", "name": "Awa", "email": "awa@example.com", "code": "AWA10" }, "product": { "id": "cm1prod001", "name": "Guide complet" } } }
```

## Catalogue

### product.published

Un produit passe en ligne. `data.product` a la forme complète d'un [produit de l'API](https://docs.pulse-sell.com/guides/products.md). Republier un produit plus tard envoie un nouvel événement.

## Envoyer un événement de test

Dans le tableau de bord (**Tester**) ou par `POST /pulses/{id}/test`, Pulse-Sell envoie immédiatement un événement `pulse.test` clairement marqué : il utilise la même signature et la même enveloppe, avec des données fictives. Il n'influence pas le compteur d'échecs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.