Agenda
Kadens envoie une requête HTTPS à votre point de terminaison chaque fois que quelque chose se passe dans votre compte. Chaque requête est signée, renvoyée jusqu'à sa réussite et listée dans votre journal des envois.
Un webhook est un message que Kadens envoie à une adresse web que vous choisissez chaque fois qu'un événement se produit sur votre compte : une commande est payée, un billet est émis, quelqu'un se présente à l'entrée. Votre système le reçoit et fait le reste, par exemple ajouter l'acheteur à votre liste de diffusion ou mettre à jour une feuille de calcul.
Vous utilisez Zapier, Make, n8n ou votre propre code ? Ils peuvent créer et supprimer des endpoints pour vous avec une clé API, via l'API REST.
Kadens peut héberger un récepteur de test pour vous. Choisissez Essayer avec un récepteur de test sur la page Webhooks : Kadens crée une adresse de test privée, connecte un endpoint qui reçoit chaque événement et lui envoie un événement de test. Chaque requête apparaît sur la page de cet endpoint en quelques secondes, avec ses en-têtes, son corps et si la signature correspondait.
Le récepteur de test conserve les 50 dernières requêtes pendant 7 jours, et les premiers 64 Ko de chaque corps.
Chaque événement arrive dans la même enveloppe JSON, version 2026-10-01. L'événement lui-même se trouve dans data.
| Champ | Type | Description |
|---|---|---|
id | string | Id unique de l'événement, commençant par evt_. La même valeur arrive dans l'en-tête webhook-id et reste identique à chaque nouvelle tentative, renvoi et relecture. |
type | string | Le type d'événement, par exemple order.paid. Le catalogue d'événements les liste tous. |
version | string | La version de contrat que suit la charge utile. Aujourd'hui, c'est 2026-10-01. |
occurred_at | string | Le moment où c'est arrivé, sous forme de date et heure ISO 8601. |
account | { id, name } | Le compte Kadens auquel appartient l'événement : son id et son nom. |
subject.type | string | Le type d'enregistrement concerné par l'événement, par exemple order, booking ou subscription. |
subject.id | string | L'id de cet enregistrement. Chaque événement concernant le même enregistrement porte le même id. |
subject.sequence | integer | null | Un nombre qui augmente à chaque modification du même enregistrement, pour savoir quel événement est le plus récent. null quand l'enregistrement n'a pas d'ordre de modifications. |
correlation_id | string | null | Relie les événements issus de la même action, quand il y en a une. Sinon null. |
livemode | boolean | true pour une activité réelle. false pour les événements de test, dont les id sont aussi marqués comme id de test. |
data | object | L'événement lui-même. Ses champs dépendent du type : ouvrez un exemple dans le catalogue d'événements. |
{
"id": "evt_2f8a1c7e9b3d4e5fa6c7d8e9f0a1b2c3",
"type": "order.paid",
"version": "2026-10-01",
"occurred_at": "2026-10-01T10:00:00Z",
"account": {
"id": "ent_1a0f",
"name": "Barcelona Salsa Studio"
},
"subject": {
"type": "order",
"id": "ord_91ac04",
"sequence": 2
},
"correlation_id": null,
"livemode": true,
"data": {
"order": {
"id": "ord_91ac04",
"status": "paid",
"created_at": "2026-10-01T09:58:02Z",
"paid_at": "2026-10-01T10:00:00Z",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
},
"totals": {
"gross": {
"amount": 12000,
"currency": "EUR"
},
"fees": {
"amount": 600,
"currency": "EUR"
},
"net": {
"amount": 11400,
"currency": "EUR"
},
"tax": {
"amount": 2083,
"currency": "EUR"
}
},
"buyer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"lines": [
{
"ticket_type_id": "tt_full_pass",
"name": "Full pass",
"quantity": 1,
"unit_price": {
"amount": 12000,
"currency": "EUR"
}
}
]
}
}
}Les requêtes suivent la spécification Standard Webhooks : les bibliothèques officielles les vérifient sans code propre à Kadens. Vérifiez toujours le corps brut.
| En-tête | Description |
|---|---|
webhook-id | Unique par événement. Utilisez-le pour ignorer une requête déjà traitée. |
webhook-timestamp | Secondes Unix de la signature de la requête. Refusez les requêtes de plus de 300 secondes. |
webhook-signature | Une ou plusieurs signatures v1 séparées par des espaces. Pendant 24 heures après le renouvellement d'un secret, l'ancien et le nouveau signent tous les deux. |
// npm install standardwebhooks
import { Webhook } from 'standardwebhooks';
const wh = new Webhook(process.env.KADENS_WEBHOOK_SECRET);
// Use the RAW request body, exactly as received (not re-serialized JSON).
app.post('/webhooks/kadens', express.raw({ type: 'application/json' }), (req, res) => {
try {
const event = wh.verify(req.body.toString('utf8'), req.headers);
// event.type, event.data
res.sendStatus(200);
} catch {
res.sendStatus(400);
}
});Le même événement peut arriver deux fois, en retard ou dans le désordre. Trois habitudes rendent votre récepteur sûr.
Stockez le webhook-id de chaque événement que vous traitez. Si le même arrive à nouveau après une nouvelle tentative, un renvoi ou une relecture, répondez 2xx et ignorez-le.
Une nouvelle tentative peut faire arriver un événement plus ancien après un plus récent. Quand subject.sequence est défini, conservez le plus élevé que vous avez traité pour chaque subject.id et ignorez tout ce qui est inférieur.
Répondez 2xx dès que l'événement est enregistré en toute sécurité, puis effectuez le travail long en arrière-plan. Une réponse qui prend plus de 10 secondes compte comme un échec et est retentée.
Répondez avec un statut 2xx pour confirmer un envoi. Tout autre statut, ou l'absence de réponse, compte comme un échec.
Un envoi en échec est renvoyé 10 fois de plus avec des délais croissants, sur environ 3 jours. Vous pouvez aussi le renvoyer ou rejouer une période depuis votre tableau de bord.
Si votre endpoint répond 410 Gone, il est désactivé immédiatement et ne reçoit plus rien jusqu'à ce que vous le réactiviez.
Un point de terminaison en échec pendant 5 jours sans un seul succès est désactivé, et vous êtes prévenu.
Les événements et les envois sont conservés 30 jours.
Chaque compte peut avoir jusqu'à 10 points de terminaison à lui. Ceux que créent Zapier, Make ou n8n ne comptent pas dans cette limite et ont leur propre plafond de 50.
| Nouvelle tentative | Quand |
|---|---|
Nouvelle tentative 1 | 30 secondes après la tentative précédente |
Nouvelle tentative 2 | 2 minutes après la tentative précédente |
Nouvelle tentative 3 | 10 minutes après la tentative précédente |
Nouvelle tentative 4 | 30 minutes après la tentative précédente |
Nouvelle tentative 5 | 1 heure après la tentative précédente |
Nouvelle tentative 6 | 3 heures après la tentative précédente |
Nouvelle tentative 7 | 6 heures après la tentative précédente |
Nouvelle tentative 8 | 12 heures après la tentative précédente |
Nouvelle tentative 9 | 24 heures après la tentative précédente |
Nouvelle tentative 10 | 24 heures après la tentative précédente |
Les noms et adresses e-mail des acheteurs, détenteurs de billets et participants sont des données personnelles. Par défaut, Kadens retire ces champs des données avant l'envoi, de sorte que l'endpoint reçoit l'événement sans eux.
Pour les recevoir, modifiez l'endpoint et activez Inclure les données personnelles. Une fois que les données quittent Kadens, les protéger de votre côté est de votre responsabilité.
| Action | Description |
|---|---|
Renouveler le secret | Crée un nouveau secret de signature. L'ancien continue de signer pendant 24 heures, pour que vous puissiez mettre à jour votre serveur sans manquer un événement. |
Renvoyer | Renvoie chaque événement d'une plage de dates que l'endpoint a manqué ou n'a pas reçu, jusqu'à 30 jours en arrière. |
Renvoyer | Renvoie une livraison, depuis le journal de livraisons de l'endpoint. |
Envoyer un événement de test | Envoie un exemple de n'importe quel type d'événement à cet endpoint uniquement, marqué comme test. |
Désactiver / Activer | Arrête les livraisons jusqu'à ce que vous réactiviez l'endpoint. Après l'avoir réactivé, rejouez la plage qu'il a manquée. |
Un endpoint qui échoue pendant 5 jours sans un seul succès est désactivé automatiquement, et vous êtes notifié.
Abonnez un point de terminaison aux événements dont il a besoin. Chacun montre les données qu'il transporte.
order.paidUne commande a été payée.
{
"order": {
"id": "ord_91ac04",
"status": "paid",
"created_at": "2026-10-01T09:58:02Z",
"paid_at": "2026-10-01T10:00:00Z",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
},
"totals": {
"gross": {
"amount": 12000,
"currency": "EUR"
},
"fees": {
"amount": 600,
"currency": "EUR"
},
"net": {
"amount": 11400,
"currency": "EUR"
},
"tax": {
"amount": 2083,
"currency": "EUR"
}
},
"buyer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"lines": [
{
"ticket_type_id": "tt_full_pass",
"name": "Full pass",
"quantity": 1,
"unit_price": {
"amount": 12000,
"currency": "EUR"
}
}
]
}
}order.refundedUne commande a été remboursée, totalement ou partiellement.
{
"order": {
"id": "ord_91ac04",
"status": "refunded",
"created_at": "2026-10-01T09:58:02Z",
"paid_at": "2026-10-01T10:00:00Z",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
},
"totals": {
"gross": {
"amount": 12000,
"currency": "EUR"
},
"fees": {
"amount": 600,
"currency": "EUR"
},
"net": {
"amount": 11400,
"currency": "EUR"
},
"tax": {
"amount": 2083,
"currency": "EUR"
}
},
"buyer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"lines": [
{
"ticket_type_id": "tt_full_pass",
"name": "Full pass",
"quantity": 1,
"unit_price": {
"amount": 12000,
"currency": "EUR"
}
}
]
},
"refund": {
"id": "ref_0c7d",
"amount": {
"amount": 12000,
"currency": "EUR"
},
"refunded_at": "2026-10-03T08:12:40Z"
}
}checkout.abandonedUn acheteur a commencé un paiement et est parti sans payer.
{
"checkout": {
"id": "pin_3c8e21",
"item": {
"kind": "course",
"id": "crs_9a20",
"name": "Bachata Foundations"
},
"buyer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"amount": {
"amount": 9900,
"currency": "EUR"
},
"started_at": "2026-10-01T09:40:00Z"
},
"abandoned_at": "2026-10-01T10:40:00Z"
}ticket.issuedUn billet a été émis à son titulaire.
{
"ticket": {
"id": "tkt_33d0e1",
"order_id": "ord_91ac04",
"status": "active",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
},
"ticket_type": {
"id": "tt_full_pass",
"name": "Full pass"
},
"holder": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"issued_at": "2026-10-01T10:00:01Z"
}
}ticket.reassignedUn billet a été transféré à un autre titulaire.
{
"ticket": {
"id": "tkt_33d0e1",
"order_id": "ord_91ac04",
"status": "active",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
},
"ticket_type": {
"id": "tt_full_pass",
"name": "Full pass"
},
"holder": {
"entity_id": "ent_8e40",
"name": "Marco Rossi",
"email": "marco@example.com"
},
"issued_at": "2026-10-01T10:00:01Z"
},
"previous_holder": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"reassigned_at": "2026-10-02T17:30:00Z"
}ticket.canceledUn billet a été annulé.
{
"ticket": {
"id": "tkt_33d0e1",
"order_id": "ord_91ac04",
"status": "canceled",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
},
"ticket_type": {
"id": "tt_full_pass",
"name": "Full pass"
},
"holder": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"issued_at": "2026-10-01T10:00:01Z"
},
"canceled_at": "2026-10-04T12:00:00Z"
}attendee.registeredUn participant a été inscrit à un événement.
{
"attendee": {
"ticket_id": "tkt_33d0e1",
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
}
},
"registered_at": "2026-10-01T10:05:00Z"
}attendee.checked_inUn participant a été enregistré à l'entrée.
{
"attendee": {
"ticket_id": "tkt_33d0e1",
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
}
},
"checked_in_at": "2026-10-10T19:02:11Z"
}attendee.check_in_revertedUn enregistrement à l'entrée a été annulé.
{
"attendee": {
"ticket_id": "tkt_33d0e1",
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
}
},
"reverted_at": "2026-10-10T19:04:30Z"
}attendee.no_showUn détenteur de billet ne s'est pas enregistré avant la fin de la séance.
{
"attendee": {
"ticket_id": "tkt_33d0e1",
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona 2026"
}
},
"finalized_at": "2026-10-10T23:30:00Z"
}event.endedUn de vos événements est terminé.
{
"edition": {
"id": "eed_2b71",
"name": "Salsa Congress Barcelona 2026",
"event": {
"id": "evt_7f3c2a",
"name": "Salsa Congress Barcelona"
},
"starts_at": "2026-10-09T16:00:00Z",
"ends_at": "2026-10-11T22:00:00Z",
"timezone": "Europe/Madrid"
},
"ended_at": "2026-10-11T22:00:00Z"
}booking.confirmedUne réservation à une séance a été confirmée.
{
"booking": {
"id": "reg_8e17c3",
"status": "reserved",
"session": {
"id": "ses_62f1a8",
"status": "scheduled",
"program": {
"id": "prg_0c4e",
"name": "Contemporary Technique, Level 2"
},
"starts_at": "2026-10-08T17:00:00Z",
"ends_at": "2026-10-08T18:30:00Z",
"timezone": "Europe/Madrid",
"location": {
"delivery_mode": "in_person",
"room": {
"id": "room_a1",
"name": "Studio A"
}
}
},
"attendee": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"confirmed_at": "2026-10-01T10:00:00Z"
}booking.declinedUne demande de réservation a été refusée.
{
"booking": {
"id": "reg_8e17c3",
"status": "cancelled",
"session": {
"id": "ses_62f1a8",
"status": "scheduled",
"program": {
"id": "prg_0c4e",
"name": "Contemporary Technique, Level 2"
},
"starts_at": "2026-10-08T17:00:00Z",
"ends_at": "2026-10-08T18:30:00Z",
"timezone": "Europe/Madrid",
"location": {
"delivery_mode": "in_person",
"room": {
"id": "room_a1",
"name": "Studio A"
}
}
},
"attendee": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"declined_at": "2026-10-01T10:00:00Z"
}booking.canceledUne réservation a été annulée ou a expiré.
{
"booking": {
"id": "reg_8e17c3",
"status": "cancelled",
"session": {
"id": "ses_62f1a8",
"status": "scheduled",
"program": {
"id": "prg_0c4e",
"name": "Contemporary Technique, Level 2"
},
"starts_at": "2026-10-08T17:00:00Z",
"ends_at": "2026-10-08T18:30:00Z",
"timezone": "Europe/Madrid",
"location": {
"delivery_mode": "in_person",
"room": {
"id": "room_a1",
"name": "Studio A"
}
}
},
"attendee": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"reason": "canceled",
"canceled_at": "2026-10-03T09:12:00Z"
}booking.movedUne réservation a été déplacée vers une autre séance.
{
"booking": {
"id": "reg_8e17c3",
"status": "reserved",
"session": {
"id": "ses_7b90d2",
"status": "scheduled",
"program": {
"id": "prg_0c4e",
"name": "Contemporary Technique, Level 2"
},
"starts_at": "2026-10-15T17:00:00Z",
"ends_at": "2026-10-15T18:30:00Z",
"timezone": "Europe/Madrid",
"location": {
"delivery_mode": "in_person",
"room": {
"id": "room_a1",
"name": "Studio A"
}
}
},
"attendee": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"previous_session": {
"id": "ses_62f1a8",
"status": "scheduled",
"program": {
"id": "prg_0c4e",
"name": "Contemporary Technique, Level 2"
},
"starts_at": "2026-10-08T17:00:00Z",
"ends_at": "2026-10-08T18:30:00Z",
"timezone": "Europe/Madrid",
"location": {
"delivery_mode": "in_person",
"room": {
"id": "room_a1",
"name": "Studio A"
}
}
},
"moved_at": "2026-10-04T11:40:00Z"
}booking.no_showUn participant réservé ne s'est pas enregistré avant la fin de la séance.
{
"booking": {
"id": "reg_8e17c3",
"status": "reserved",
"session": {
"id": "ses_62f1a8",
"status": "scheduled",
"program": {
"id": "prg_0c4e",
"name": "Contemporary Technique, Level 2"
},
"starts_at": "2026-10-08T17:00:00Z",
"ends_at": "2026-10-08T18:30:00Z",
"timezone": "Europe/Madrid",
"location": {
"delivery_mode": "in_person",
"room": {
"id": "room_a1",
"name": "Studio A"
}
}
},
"attendee": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"finalized_at": "2026-10-08T19:30:00Z"
}session.canceledUne séance programmée a été annulée.
{
"session": {
"id": "ses_62f1a8",
"status": "cancelled",
"program": {
"id": "prg_0c4e",
"name": "Contemporary Technique, Level 2"
},
"starts_at": "2026-10-08T17:00:00Z",
"ends_at": "2026-10-08T18:30:00Z",
"timezone": "Europe/Madrid",
"location": {
"delivery_mode": "in_person",
"room": {
"id": "room_a1",
"name": "Studio A"
}
}
},
"cancellation_reason": "Teacher unwell",
"canceled_at": "2026-10-07T08:00:00Z"
}session.rescheduledUne séance programmée a été déplacée à un autre horaire.
{
"session": {
"id": "ses_62f1a8",
"status": "scheduled",
"program": {
"id": "prg_0c4e",
"name": "Contemporary Technique, Level 2"
},
"starts_at": "2026-10-08T18:00:00Z",
"ends_at": "2026-10-08T19:30:00Z",
"timezone": "Europe/Madrid",
"location": {
"delivery_mode": "in_person",
"room": {
"id": "room_a1",
"name": "Studio A"
}
}
},
"previous_starts_at": "2026-10-08T17:00:00Z",
"previous_ends_at": "2026-10-08T18:30:00Z",
"rescheduled_at": "2026-10-06T15:20:00Z"
}pack.credits_lowUn forfait de cours est descendu sous son seuil bas de crédits.
{
"pack": {
"id": "pkp_1e90",
"product": {
"id": "pck_10cls",
"name": "10 class pack"
},
"holder": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"credits_remaining": 2,
"credits_total": 10,
"expires_at": "2027-01-31T23:59:59Z"
},
"threshold": 2,
"crossed_at": "2026-10-08T17:00:05Z"
}enrollment.createdUn étudiant a été inscrit à un cours.
{
"enrollment": {
"id": "crs_9a20:ent_31c7",
"course": {
"id": "crs_9a20",
"name": "Bachata Foundations"
},
"edition": {
"id": "ced_4b1e",
"name": "January 2027",
"starts_at": "2027-01-11T18:00:00Z",
"ends_at": "2027-03-29T20:00:00Z",
"timezone": "Europe/Madrid"
},
"student": {
"entity_id": "ent_31c7",
"name": "Lucia Fernandez",
"email": "lucia@example.com"
},
"source": "subscription"
},
"enrolled_at": "2026-12-02T10:15:00Z"
}enrollment.endedL'inscription d'un étudiant à un cours a pris fin.
{
"enrollment": {
"id": "crs_9a20:ent_31c7",
"course": {
"id": "crs_9a20",
"name": "Bachata Foundations"
},
"edition": {
"id": "ced_4b1e",
"name": "January 2027",
"starts_at": "2027-01-11T18:00:00Z",
"ends_at": "2027-03-29T20:00:00Z",
"timezone": "Europe/Madrid"
},
"student": {
"entity_id": "ent_31c7",
"name": "Lucia Fernandez",
"email": "lucia@example.com"
},
"source": "subscription"
},
"ended_at": "2027-02-02T10:15:00Z"
}enrollment.movedUn étudiant a été déplacé vers une autre édition du cours.
{
"enrollment": {
"id": "crs_9a20:ent_31c7",
"course": {
"id": "crs_9a20",
"name": "Bachata Foundations"
},
"edition": {
"id": "ced_7d02",
"name": "April 2027",
"starts_at": "2027-04-12T17:00:00Z",
"ends_at": "2027-06-28T19:00:00Z",
"timezone": "Europe/Madrid"
},
"student": {
"entity_id": "ent_31c7",
"name": "Lucia Fernandez",
"email": "lucia@example.com"
},
"source": "subscription"
},
"previous_edition": {
"id": "ced_4b1e",
"name": "January 2027",
"starts_at": "2027-01-11T18:00:00Z",
"ends_at": "2027-03-29T20:00:00Z",
"timezone": "Europe/Madrid"
},
"moved_at": "2026-12-20T09:00:00Z"
}lesson.completedUn étudiant a terminé une leçon de votre cours.
{
"enrollment": {
"id": "crs_9a20:ent_31c7",
"course": {
"id": "crs_9a20",
"name": "Bachata Foundations"
},
"edition": {
"id": "ced_4b1e",
"name": "January 2027",
"starts_at": "2027-01-11T18:00:00Z",
"ends_at": "2027-03-29T20:00:00Z",
"timezone": "Europe/Madrid"
},
"student": {
"entity_id": "ent_31c7",
"name": "Lucia Fernandez",
"email": "lucia@example.com"
},
"source": "subscription"
},
"lesson": {
"id": "itm_2f81",
"name": "Basic step and timing"
},
"completed_at": "2026-12-05T19:40:00Z"
}course.completedUn étudiant a terminé votre cours.
{
"enrollment": {
"id": "crs_9a20:ent_31c7",
"course": {
"id": "crs_9a20",
"name": "Bachata Foundations"
},
"edition": {
"id": "ced_4b1e",
"name": "January 2027",
"starts_at": "2027-01-11T18:00:00Z",
"ends_at": "2027-03-29T20:00:00Z",
"timezone": "Europe/Madrid"
},
"student": {
"entity_id": "ent_31c7",
"name": "Lucia Fernandez",
"email": "lucia@example.com"
},
"source": "subscription"
},
"completed_at": "2027-03-29T20:10:00Z"
}subscription.createdUn client a souscrit une formule d'abonnement.
{
"subscription": {
"id": "sub_4d2e9a",
"status": "active",
"plan": {
"id": "plan_7a10",
"name": "Monthly membership"
},
"price": {
"id": "price_2c3b",
"amount": {
"amount": 4900,
"currency": "EUR"
},
"interval": "month",
"interval_count": 1
},
"current_period_start": "2026-10-01T00:00:00Z",
"current_period_end": "2026-11-01T00:00:00Z",
"cancel_at_period_end": false,
"canceled_at": null,
"customer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
}
}subscription.renewedUn abonnement a été renouvelé et son paiement a abouti.
{
"subscription": {
"id": "sub_4d2e9a",
"status": "active",
"plan": {
"id": "plan_7a10",
"name": "Monthly membership"
},
"price": {
"id": "price_2c3b",
"amount": {
"amount": 4900,
"currency": "EUR"
},
"interval": "month",
"interval_count": 1
},
"current_period_start": "2026-11-01T00:00:00Z",
"current_period_end": "2026-12-01T00:00:00Z",
"cancel_at_period_end": false,
"canceled_at": null,
"customer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"invoice": {
"id": "in_1Q2w3E",
"amount": {
"amount": 4900,
"currency": "EUR"
}
},
"renewed_at": "2026-11-01T00:04:12Z"
}subscription.payment_failedLe paiement d'un abonnement a échoué.
{
"subscription": {
"id": "sub_4d2e9a",
"status": "past_due",
"plan": {
"id": "plan_7a10",
"name": "Monthly membership"
},
"price": {
"id": "price_2c3b",
"amount": {
"amount": 4900,
"currency": "EUR"
},
"interval": "month",
"interval_count": 1
},
"current_period_start": "2026-10-01T00:00:00Z",
"current_period_end": "2026-11-01T00:00:00Z",
"cancel_at_period_end": false,
"canceled_at": null,
"customer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"access_ends_at": "2026-11-08T00:04:12Z",
"failure_code": "card_declined",
"failed_at": "2026-11-01T00:04:12Z"
}subscription.canceledUn abonnement a été annulé.
{
"subscription": {
"id": "sub_4d2e9a",
"status": "active",
"plan": {
"id": "plan_7a10",
"name": "Monthly membership"
},
"price": {
"id": "price_2c3b",
"amount": {
"amount": 4900,
"currency": "EUR"
},
"interval": "month",
"interval_count": 1
},
"current_period_start": "2026-10-01T00:00:00Z",
"current_period_end": "2026-11-01T00:00:00Z",
"cancel_at_period_end": true,
"canceled_at": null,
"customer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"cancel_at_period_end": true,
"ends_at": "2026-11-01T00:00:00Z",
"canceled_at": "2026-10-15T09:30:00Z"
}subscription.reactivatedUn abonnement annulé a été réactivé.
{
"subscription": {
"id": "sub_4d2e9a",
"status": "active",
"plan": {
"id": "plan_7a10",
"name": "Monthly membership"
},
"price": {
"id": "price_2c3b",
"amount": {
"amount": 4900,
"currency": "EUR"
},
"interval": "month",
"interval_count": 1
},
"current_period_start": "2026-10-01T00:00:00Z",
"current_period_end": "2026-11-01T00:00:00Z",
"cancel_at_period_end": false,
"canceled_at": null,
"customer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"reactivated_at": "2026-10-20T18:00:00Z"
}subscription.plan_changedUn client est passé à une autre formule.
{
"subscription": {
"id": "sub_8f01bc",
"status": "active",
"plan": {
"id": "plan_9b22",
"name": "Full bundle"
},
"price": {
"id": "price_5d6e",
"amount": {
"amount": 8900,
"currency": "EUR"
},
"interval": "month",
"interval_count": 1
},
"current_period_start": "2026-10-01T00:00:00Z",
"current_period_end": "2026-11-01T00:00:00Z",
"cancel_at_period_end": false,
"canceled_at": null,
"customer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"previous_subscription_ids": [
"sub_4d2e9a"
],
"credit_applied": {
"amount": 2450,
"currency": "EUR"
},
"next_billing_at": "2026-11-15T00:00:00Z",
"changed_at": "2026-10-15T12:00:00Z"
}subscription.endedUn abonnement a pris fin et son accès s'est arrêté.
{
"subscription": {
"id": "sub_4d2e9a",
"status": "canceled",
"plan": {
"id": "plan_7a10",
"name": "Monthly membership"
},
"price": {
"id": "price_2c3b",
"amount": {
"amount": 4900,
"currency": "EUR"
},
"interval": "month",
"interval_count": 1
},
"current_period_start": "2026-10-01T00:00:00Z",
"current_period_end": "2026-11-01T00:00:00Z",
"cancel_at_period_end": false,
"canceled_at": "2026-11-01T00:00:00Z",
"customer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"reason": "cancellation_requested",
"ended_at": "2026-11-01T00:00:00Z"
}subscription.trial_endingL'essai gratuit d'un abonné se termine dans quelques jours.
{
"subscription": {
"id": "sub_4d2e9a",
"status": "trialing",
"plan": {
"id": "plan_7a10",
"name": "Monthly membership"
},
"price": {
"id": "price_2c3b",
"amount": {
"amount": 4900,
"currency": "EUR"
},
"interval": "month",
"interval_count": 1
},
"current_period_start": "2026-10-01T00:00:00Z",
"current_period_end": "2026-11-01T00:00:00Z",
"cancel_at_period_end": false,
"canceled_at": null,
"customer": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"trial_ends_at": "2026-10-15T00:00:00Z"
}certificate.issuedUn certificat a été délivré à son titulaire.
{
"certificate": {
"id": "icrt_4d19b2",
"number": "KD-2026-000142",
"status": "active",
"certificate": {
"id": "crt_7a02",
"name": "Contemporary Foundations"
},
"template": {
"id": "tpl_31c8",
"name": "2026 cohort"
},
"recipient": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"issued_at": "2026-10-01T10:00:00Z",
"expires_at": null,
"revoked_at": null,
"verification_url": "https://kadens.io/verify-certificate/KD-2026-000142"
}
}certificate.revokedUn certificat a été révoqué.
{
"certificate": {
"id": "icrt_4d19b2",
"number": "KD-2026-000142",
"status": "revoked",
"certificate": {
"id": "crt_7a02",
"name": "Contemporary Foundations"
},
"template": {
"id": "tpl_31c8",
"name": "2026 cohort"
},
"recipient": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"issued_at": "2026-10-01T10:00:00Z",
"expires_at": null,
"revoked_at": "2026-11-12T08:30:00Z",
"verification_url": "https://kadens.io/verify-certificate/KD-2026-000142"
},
"reason": "Issued to the wrong student",
"revoked_at": "2026-11-12T08:30:00Z"
}payout.paidUn versement est arrivé sur votre compte bancaire.
{
"payout": {
"id": "po_1Q2w3E4r",
"status": "paid",
"amount": {
"amount": 113400,
"currency": "EUR"
},
"arrival_date": "2026-10-06T00:00:00Z"
},
"paid_at": "2026-10-06T06:14:09Z"
}payout.failedUn versement a échoué et l'argent n'a pas été transféré.
{
"payout": {
"id": "po_1Q2w3E4r",
"status": "failed",
"amount": {
"amount": 113400,
"currency": "EUR"
},
"arrival_date": "2026-10-06T00:00:00Z"
},
"failure": {
"code": "account_closed",
"message": "The bank account has been closed."
},
"failed_at": "2026-10-06T06:14:09Z"
}lead.capturedUn nouveau lead a été capté.
{
"lead": {
"id": "lead_4a90",
"audience_id": "aud_12f0",
"email": "lucia@example.com",
"first_name": "Lucia",
"last_name": "Martin",
"consent_at": "2026-10-01T09:12:00Z",
"source": {
"site_id": "site_77a1",
"page_id": "page_home",
"block_id": "blk_newsletter",
"url": "https://salsa.example.com/"
}
},
"captured_at": "2026-10-01T09:12:00Z"
}form.submittedUn formulaire a été envoyé.
{
"submission": {
"id": "sub_61c2",
"form": {
"id": "frm_0d3e",
"title": "Audition application",
"type": "application"
},
"target": {
"scope": "course",
"id": "crs_19ab"
},
"submitter": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"answers": [
{
"field_id": "b2c1e8f0-3a4d-4c5e-9f60-1a2b3c4d5e6f",
"label": "Dance experience",
"type": "textarea",
"value": "Five years of salsa",
"display": "Five years of salsa"
},
{
"field_id": "c3d2f9a1-4b5e-4d6f-8a71-2b3c4d5e6f70",
"label": "Preferred role",
"type": "select",
"value": "follower",
"display": "Follower"
}
],
"submitted_at": "2026-10-02T11:40:00Z"
}
}application.decidedVous avez approuvé, rejeté ou mis en liste d'attente une candidature.
{
"submission": {
"id": "sub_61c2",
"form": {
"id": "frm_0d3e",
"title": "Audition application",
"type": "application"
},
"target": {
"scope": "course",
"id": "crs_19ab"
},
"submitter": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"submitted_at": "2026-10-02T11:40:00Z"
},
"decision": "approved",
"decided_at": "2026-10-06T09:00:00Z"
}exam.results_releasedUn candidat peut désormais voir les résultats de son examen.
{
"submission": {
"id": "sub_61c2",
"form": {
"id": "frm_0d3e",
"title": "Audition application",
"type": "exam"
},
"target": {
"scope": "course",
"id": "crs_19ab"
},
"submitter": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"submitted_at": "2026-10-02T11:40:00Z"
},
"result": {
"passed": true,
"score_percent": 86
},
"released_at": "2026-10-09T12:00:00Z"
}follower.addedQuelqu'un a commencé à vous suivre.
{
"follower": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"followed_at": "2026-10-01T08:00:00Z"
}community.member.joinedUn membre a rejoint l'une de vos communautés.
{
"membership": {
"member": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"source": "ticket_holder"
},
"joined_at": "2026-10-01T10:00:02Z"
}community.member.leftUn membre a quitté l'une de vos communautés.
{
"membership": {
"member": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"source": "ticket_holder"
},
"reason": "ticket_released",
"left_at": "2026-10-05T08:00:00Z"
}channel_automation.webhookUne automatisation a atteint une étape d’envoi de webhook pour un contact.
{
"automation": {
"id": "aut_2c81f0",
"step_id": "step_send_webhook",
"run_id": "run_8e41d7"
},
"contact": {
"id": "con_51a9e2",
"entity_id": null,
"username": "lucia.dances",
"email": "lucia@example.com",
"tag_ids": [
"tag_vip"
]
},
"channel": {
"type": "instagram",
"account_id": "cha_7d02b1"
},
"fired_at": "2026-10-01T10:00:00Z"
}review.submittedQuelqu'un a laissé un avis.
{
"review": {
"id": "rev_8d02",
"rating": 5,
"comment": "Clear, patient and fun.",
"target": {
"kind": "course",
"id": "crs_9a20",
"name": "Bachata Foundations"
},
"author": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"submitted_at": "2026-10-12T20:15:00Z"
}feedback.completedVous avez répondu à une demande de feedback d'un étudiant.
{
"request": {
"id": "fbr_51a7",
"offering": {
"id": "mnt_33c0",
"name": "Video feedback on your solo"
},
"student": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
}
},
"completed_at": "2026-10-14T10:30:00Z"
}reward.expiringUne récompense que vous avez offerte à quelqu'un expire bientôt.
{
"reward": {
"id": "grw_0a4f",
"name": "Free drop-in class",
"kind": "free_class",
"holder": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"expires_at": "2026-11-01T00:00:00Z"
}
}automation.step_reachedUne séquence a atteint une étape webhook pour une personne.
{
"automation": {
"id": "aut_3c81"
},
"run": {
"id": "run_9d42"
},
"step": {
"id": "s_hotlead",
"key": "hot_lead"
},
"person": {
"entity_id": "ent_5b21",
"name": "Lucia Martin",
"email": "lucia@example.com"
},
"reached_at": "2026-10-03T08:15:00Z"
}webhook.testUn événement de test que vous avez envoyé depuis Kadens.
{
"message": "This is a test event sent from Kadens."
}Vérifiez que l'endpoint est activé et abonné à l'événement, et que son adresse est publique et utilise HTTPS. Envoyez ensuite un événement de test et ouvrez la livraison pour voir ce que votre serveur a répondu.
Vérifiez sur le corps de requête brut, avant toute analyse JSON. Utilisez le secret de cet endpoint, et vérifiez l'horloge de votre serveur : les requêtes de plus de 300 secondes sont rejetées.
C'est attendu après une nouvelle tentative, un renvoi ou une relecture. Ignorez tout webhook-id que vous avez déjà traité.
Il a échoué pendant 5 jours sans succès, a répondu 410 Gone, ou quelqu'un l'a désactivé. Réparez le serveur, activez l'endpoint et rejouez la plage qu'il a manquée.
Les données personnelles sont retirées sauf si l'endpoint les inclut. Voir Données personnelles ci-dessus.
Cet article vous a-t-il aidé ?