Aller au contenu

Référence des événements

Chaque événement est un objet JSON contenant un type, un ID unique et les données de la ressource concernée. Abonnez-vous à ces événements lors de la création d’un endpoint webhook.

Les événements sont émis en mode livemode: true en production et livemode: false en sandbox. Un même endpoint ne reçoit que les événements du mode correspondant à sa clé API.

Idempotence — traitez chaque événement une seule fois

En cas de retry, le même événement peut être livré plusieurs fois avec le même id. Stockez les IDs d’événements déjà traités et ignorez les doublons pour garantir l’idempotence de votre handler.

Événements Paiements

ÉvénementDéclencheur
payment_intent.createdPaymentIntent créé.
payment_intent.succeededPaiement réussi — déclencher la livraison.
payment_intent.payment_failedPaiement échoué après la dernière tentative.
payment_intent.canceledPaymentIntent annulé manuellement.
checkout_session.completedSession checkout passée en statut complete.
checkout_session.expiredSession expirée sans paiement.
transaction.succeededTransaction finalisée côté opérateur.
transaction.failedTransaction échouée côté opérateur.
refund.createdRemboursement initié.
refund.succeededRemboursement restitué à l'acheteur.
refund.failedRemboursement échoué côté opérateur.
payment_link.paidLien de paiement utilisé avec succès.

Événements Clients

ÉvénementDéclencheur
customer.createdNouveau Customer créé.
customer.updatedDonnées client modifiées.
customer.deletedCustomer anonymisé (conformité RGPD).
payment_method.attachedMéthode de paiement ajoutée au client.
payment_method.detachedMéthode de paiement retirée du client.

Événements Abonnements

ÉvénementDéclencheur
subscription.createdNouvel abonnement créé.
subscription.updatedAbonnement modifié (plan, quantité…).
subscription.renewedRenouvellement réussi — facture réglée.
subscription.past_dueÉchec de renouvellement — déclencher relance.
subscription.canceledRésiliation effective.
subscription.trial_will_end3 jours avant la fin de la période d'essai.
invoice.createdFacture générée automatiquement.
invoice.finalizedFacture finalisée et envoyée au client.
invoice.paidFacture réglée.
invoice.payment_failedÉchec de paiement de la facture.

Événements Compte

ÉvénementDéclencheur
kyc.submittedDossier KYC soumis pour validation.
kyc.approvedKYC validé — compte pleinement opérationnel.
kyc.rejectedKYC rejeté — action requise du marchand.
payout.createdVirement vers le compte bancaire initié.
payout.paidVirement effectué avec succès.
payout.failedVirement échoué — vérifier les coordonnées bancaires.

Structure d’un événement

Response Objet Event
Structure commune à tous les événements Sangho.
json
{
  "id": "evt_xxxxxxxxxxxx",
  "object": "event",
  "type": "payment_intent.succeeded",
  "api_version": "v1",
  "created_at": "2026-03-01T10:05:00Z",
  "livemode": true,
  "data": {
    "object": {
      "id": "pi_xxxxxxxxxxxx",
      "object": "payment_intent",
      "amount": 15000,
      "currency": "XAF",
      "status": "succeeded",
      "customer": "cus_xxxx"
    }
  }
}

Implémenter un handler

Votre handler webhook doit répondre avec un code HTTP 2xx dans les 10 secondes. Pour les traitements longs, enfilez la tâche dans une queue asynchrone et répondez immédiatement.

Commencez toujours par vérifier la signature Sangho-Signature avant tout traitement. Consultez le guide de vérification de signature pour les exemples complets par langage.

Gestion des événements inconnus

Votre handler doit ignorer silencieusement les types d’événements qu’il ne reconnaît pas et retourner un 200. Sangho peut émettre de nouveaux types d’événements sans préavis — un handler qui retourne une erreur sur un type inconnu sera mis en retry inutilement.

Événement de test

Utilisez POST /webhooks/{id}/test/ pour envoyer un événement fictif à votre endpoint et valider votre intégration sans déclencher un vrai paiement. L’événement de test a livemode: false quel que soit l’environnement.

Gestionnaire Webhook

javascript
// Node.js / Express
app.post(
  '/webhook',
  express.raw({ type: 'application/json' }),
  async (req, res) => {
    const sig = req.headers['sangho-signature'];
    let event;


    try {
      event = sangho.webhooks.constructEvent(
        req.body,
        sig,
        process.env.WEBHOOK_SECRET,
      );
    } catch (err) {
      return res.status(400).send(`Signature invalide: ${err.message}`);
    }


    switch (event.type) {
      case 'payment_intent.succeeded':
        await fulfillOrder(event.data.object.metadata.order_id);
        break;
      case 'subscription.past_due':
        await sendDunningEmail(event.data.object.customer);
        break;
      case 'refund.succeeded':
        await notifyCustomerRefund(event.data.object);
        break;
      default:
        // Type inconnu — ignorer silencieusement
        break;
    }


    res.json({ received: true });
  },
);