Configurer un endpoint
- Dans Melora Connect, ouvrez Settings puis l'onglet Webhooks. Vous avez besoin de la permission de gérer les paramètres de l'organisation.
- Saisissez l'adresse https de l'endpoint, choisissez ses événements et, si vous les voulez, cochez Include member contact details. Cliquez ensuite sur Add endpoint.
- Copiez le secret de signature et conservez-le comme un mot de passe. Il n'est affiché qu'une fois.
Une organisation peut avoir jusqu'à 10 endpoints, comme l'indique la section 3.5 des Conditions d'utilisation. Le même onglet met en pause et réactive un endpoint, envoie un message de test, émet un nouveau secret et affiche chaque message avec son résultat. Un message en échec peut y être renvoyé, et le journal des envois est conservé 30 jours.
Un système peut aussi abonner et désabonner son propre endpoint avec une clé d'API, par POST /webhooks et DELETE /webhooks/{id} de l'API REST.
L'adresse doit utiliser https, sur le port 443 ou 8443, avec un nom d'hôte public. Les adresses d'un réseau privé, de boucle locale et de lien local (y compris les adresses de métadonnées cloud) sont refusées à l'ajout de l'endpoint, puis vérifiées à nouveau avant chaque message, car le DNS d'un hôte peut changer. Les redirections ne sont pas suivies.
Ce qui est envoyé
Chaque message est un POST avec ces en-têtes et un corps JSON :
POST /your/endpoint HTTP/1.1
Content-Type: application/json
User-Agent: Melora-Webhooks/1.0
Melora-Signature: t=1791000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
Melora-Event: member.status_changed
Melora-Event-Id: 8a1f0c1e-2f7b-4a55-9b3e-0d2b6f1c9e41
Melora-Delivery: 3c9d2a70-51f4-4e0b-8f7e-6a1d2c3b4e5f{
"id": "8a1f0c1e-2f7b-4a55-9b3e-0d2b6f1c9e41",
"type": "member.status_changed",
"created_at": "2026-10-01T14:03:22.418Z",
"organization_id": "5d0c7a4e-1b2f-4c3d-9e8f-0a1b2c3d4e5f",
"data": {
"member_id": "0f9e8d7c-6b5a-4938-8271-605f4e3d2c1b",
"status": "lapsed",
"previous_status": "active"
}
}Melora-Eventest le type d'événement, aussi présent dans le corps commetype.Melora-Event-Idest l'id de l'événement, aussi présent dans le corps commeid. Il reste le même à chaque nouvelle tentative : utilisez-le pour ignorer un message déjà traité.Melora-Deliveryidentifie ce message pour cet endpoint et correspond au journal des envois de l'onglet Webhooks.Melora-Signatureporte la signature, expliquée plus bas.organization_idest votre organisation. Un message ne porte que les enregistrements de votre propre organisation.
Événements
Chaque endpoint reçoit les événements choisis pour lui. Les coordonnées des membres sont omises sauf si l'option Include member contact details est cochée pour l'endpoint : sans elle, email, phone, city, state, zip, company, title, industry, website, linkedin_url, tags, show_in_directory, donor_email, guest_email ne sont pas envoyés, et un message member.updated dont les seuls changements portaient sur ces champs n'est pas envoyé du tout. Le tableau montre les champs avec les coordonnées activées.
| Événement | Quand il est envoyé | Champs de data |
|---|---|---|
member.created | Une fiche de membre est créée. | member: id, status, name, first_name, last_name, email, phone, company, title, industry, city, state, zip, website, linkedin_url, tier, membership_type_id, membership_category, chapter_id, corporate_membership_id, join_date, renewal_date, tags, show_in_directory, archived_at, user_id |
member.updated | Les coordonnées ou les données d'adhésion d'un membre changent. changed ne contient que les champs du membre qui ont changé, avec leurs nouvelles valeurs. | member_id, changed |
member.status_changed | Le statut d'un membre change (active, lapsed, expired et les autres), avec le statut précédent. | member_id, status, previous_status |
member.unsubscribed | Un membre se désinscrit de vos emails marketing : un lien de désinscription, une plainte, son interrupteur d'email, Mailchimp ou l'API. Envoyé une fois, seulement quand la désinscription change ; email_marketing_opted_out_at indique quand. | member_id, email_marketing_opt_out, email_marketing_opted_out_at, email |
member.resubscribed | Un membre qui s'était désinscrit peut de nouveau recevoir vos emails marketing, par exemple après les avoir réactivés lui-même. Envoyé une fois, seulement quand la désinscription change ; email_marketing_opted_out_at vaut null. | member_id, email_marketing_opt_out, email_marketing_opted_out_at, email |
event.registration.created | Quelqu'un s'inscrit à l'un de vos événements. | registration: id, event_id, user_id, status, tier_id, guest_name, guest_email, group_order_id, created_at |
dues_invoice.paid | Une facture de cotisation est payée, en ligne ou enregistrée par le personnel. previous_status est le statut précédent de la facture. | invoice: id, invoice_number, member_id, user_id, dues_subscription_id, amount_cents, currency, paid_at, paid_via, period_start, period_end, due_at; previous_status |
donation.completed | Un don est enregistré ou un don par carte aboutit. Son statut est received ou completed. Pour un donateur anonyme, donor_name, donor_email et user_id sont omis. | donation: id, amount_cents, currency, status, fundraiser_id, campaign, designation, received_at, source, anonymous, donor_name, donor_email, user_id |
webhook.test n'est envoyé que par le bouton Send test, avec data.message.
Vérifier la signature
L'en-tête Melora-Signature se présente ainsi :
Melora-Signature: t=1791000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd- Prenez
t(secondes Unix) et chaque valeurv1de l'en-tête. - Refusez le message si
ts'écarte de plus de 300 secondes de votre horloge. L'horodatage fait partie de ce qui est signé : c'est ce qui empêche de rejouer un ancien message. - Calculez un HMAC-SHA-256, avec votre secret de signature complet comme clé (préfixe
whsec_compris), surt, un point, puis le corps brut de la requête exactement tel que reçu. Encodez-le en hexadécimal. - Acceptez le message si une valeur
v1est égale à votre résultat. Comparez en temps constant.
Vérifiez le corps brut avant de l'analyser : resérialiser le JSON change les octets, et la signature ne correspondra pas.
Node.js
import crypto from "node:crypto";
// header: the Melora-Signature request header
// rawBody: the request body exactly as received, as a string (before JSON.parse)
// secret: the endpoint's signing secret (it starts with whsec_)
export function verifyMeloraSignature(header, rawBody, secret, toleranceSeconds = 300) {
const parts = String(header || "").split(",").map((p) => p.trim());
const t = parts.find((p) => p.startsWith("t="))?.slice(2);
const signatures = parts.filter((p) => p.startsWith("v1=")).map((p) => p.slice(3));
if (!t || !/^\d+$/.test(t) || signatures.length === 0) return false;
if (Math.abs(Date.now() / 1000 - Number(t)) > toleranceSeconds) return false;
const expected = crypto.createHmac("sha256", secret).update(t + "." + rawBody).digest("hex");
return signatures.some(
(s) =>
s.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(s), Buffer.from(expected)),
);
}Python
import hashlib
import hmac
import time
def verify_melora_signature(header, raw_body, secret, tolerance_seconds=300):
"""header: the Melora-Signature header. raw_body: the request body as bytes,
exactly as received. secret: the endpoint's signing secret (it starts with whsec_)."""
parts = [p.strip() for p in (header or "").split(",")]
t = next((p[2:] for p in parts if p.startswith("t=")), None)
signatures = [p[3:] for p in parts if p.startswith("v1=")]
if not t or not t.isdigit() or not signatures:
return False
if abs(time.time() - int(t)) > tolerance_seconds:
return False
signed = t.encode() + b"." + raw_body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return any(hmac.compare_digest(s, expected) for s in signatures)Réponses, nouvelles tentatives et ordre
Répondez avec n'importe quel statut 2xx en moins de 8 secondes. Toute autre réponse, un délai dépassé ou une redirection compte comme une tentative échouée, et le message est renvoyé après 1 minute, 5 minutes, 30 minutes, 2 heures et 6 heures : 6 tentatives au total. Ensuite, il est marqué en échec dans le journal des envois, où le personnel peut le renvoyer.
Si 5 messages de suite échouent à toutes leurs tentatives, Melora Connect met l'endpoint en pause, l'indique dans l'onglet Webhooks et prévient une fois le personnel qui gère les paramètres de l'organisation, dans l'application et par e-mail. Pendant la pause, aucun nouveau message n'est mis en file pour cet endpoint ; les messages déjà en attente sont envoyés quand il est réactivé.
L'ordre d'arrivée des messages ne suit pas forcément celui des changements, et un message peut arriver plus d'une fois. Utilisez created_at et l'id de l'événement, et lisez l'enregistrement actuel par l'API REST quand l'ordre compte.
Changer le secret
Émettre un nouveau secret dans l'onglet Webhooks affiche le nouveau secret de signature une fois. Pendant les 24 heures suivantes, chaque message porte deux valeurs v1, une pour le nouveau secret et une pour l'ancien, pour que vous puissiez basculer sans manquer de message. Ensuite, seul le nouveau secret signe.

Personnes · Événements · Communautés

