Présentation
L'API répond en JSON sur HTTPS. Chaque chemin de cette page commence par cette URL de base :
https://app.meloraconnect.com/api/public/v1Pour être informé des changements au moment où ils se produisent, utilisez les webhooks. Pour utiliser les mêmes opérations depuis un client MCP, consultez le serveur MCP.
Qui peut l'utiliser
L'API est incluse dans toutes les formules Melora Connect. Les clés sont créées dans Melora Connect par le personnel qui peut gérer les paramètres de l'organisation. Si l'API est retirée de la formule de l'organisation, ses clés cessent de fonctionner à la requête suivante et fonctionnent à nouveau dès que la formule l'inclut, sauf si elles ont été révoquées ou ont expiré.
Authentification
Chaque requête porte une clé d'API dans l'en-tête Authorization, après le mot Bearer :
Authorization: Bearer melora_YOUR_KEYCréer une clé
- Dans Melora Connect, ouvrez Settings puis l'onglet API keys.
- Donnez à la clé le nom du système qui l'utilisera, choisissez ses permissions et sa date d'expiration, puis cliquez sur Make key.
- Copiez la clé et conservez-la sur votre serveur. Elle n'est affichée qu'une fois.
À propos des clés
- Une clé appartient à une seule organisation. Chaque requête agit dans cette organisation et aucune autre, et rien dans une requête ne peut en choisir une autre. Un enregistrement d'une autre organisation répond
404, comme s'il n'existait pas. - Melora Connect ne garde qu'une empreinte de la clé (un hachage SHA-256) et ne peut donc pas l'afficher à nouveau. Conservez-la comme un mot de passe, sur votre serveur, jamais dans une page web ni dans une application mobile.
- Les clés commencent par
melora_suivi de 43 caractères. L'onglet API keys affiche les 15 premiers caractères de chaque clé, pour les distinguer, et la date de dernière utilisation de chacune. - Une clé peut expirer après 30, 90 ou 365 jours, ou jamais, et peut être révoquée à tout moment avec Revoke. Une clé révoquée ou expirée est refusée dès la requête suivante.
- Une organisation peut avoir jusqu'à 25 clés actives (les clés révoquées et expirées ne comptent pas). Créez une clé par système, pour pouvoir en révoquer une sans toucher aux autres.
- Les permissions d'une clé sont fixées à sa création. Pour les changer, créez une nouvelle clé et révoquez l'ancienne.
Permissions
Chaque clé ne porte que les permissions choisies pour elle, parmi les permissions qu'utilisent les rôles du personnel dans Melora Connect. La personne qui crée une clé ne peut lui donner que des permissions qu'elle détient. Une requête que la clé n'autorise pas répond 403 avec le code permission_denied.
| Permission de la clé | Ce qu'elle permet |
|---|---|
members.read | Lire les membres : la liste des membres et un membre. |
members.write | Ajouter des membres, modifier les champs de membre indiqués et désinscrire un membre des emails marketing de l'organisation. |
events.read | Lire les événements, et un événement avec ses inscriptions. |
events.manage | Créer des événements en brouillon. |
members.billing.read | Lire les factures de cotisation. |
settings.manage | Abonner et désabonner des URL de webhooks (ce qu'utilise Zapier). |
Versions
La version figure dans le chemin, /v1. Au sein de v1, Melora Connect ne fait qu'ajouter : de nouveaux endpoints, de nouveaux paramètres facultatifs et de nouveaux champs dans les réponses ; votre code doit donc ignorer les champs qu'il ne connaît pas. Tout ce qui casserait une intégration qui fonctionne arrive dans une nouvelle version, et v1 continue de fonctionner en parallèle.
Limites
- Chaque clé peut faire 120 requêtes toutes les 60 secondes. Au-delà, la réponse est
429avec un en-têteRetry-Afteren secondes. - Toutes clés confondues, une organisation peut faire 600 requêtes toutes les 60 secondes. Au-delà, chaque clé reçoit
429jusqu'à ce que la fenêtre avance. - Une adresse qui présente plus de 30 clés inconnues en 10 minutes reçoit aussi
429. - Le corps d'une requête est en JSON, envoyé avec
Content-Type: application/json, et peut faire jusqu'à 64 Ko. Un corps plus grand reçoit413(payload_too_large) sans être lu.
Listes et formats
Chaque liste accepte page (à partir de 1) et per_page (de 1 à 100, 50 par défaut) et répond avec data, page, per_page et has_more. Demandez la page suivante tant que has_more est vrai.
Les membres arrivent du changement le plus ancien au plus récent. Pour garder une copie à jour, passez le updated_at le plus récent que vous avez comme updated_since : les enregistrements modifiés à ce moment ou après sont renvoyés. Les événements arrivent par heure de début, et les factures de cotisation de la plus ancienne à la plus récente.
Les heures sont au format ISO 8601 avec fuseau horaire (par exemple 2026-11-12T08:00:00-05:00), les dates au format YYYY-MM-DD, les montants en cents, et les id sont des UUID. Un id qui n'est pas un UUID répond 404.
Liste des endpoints
Chaque endpoint, la permission dont sa clé a besoin et ce qu'il fait. Chacun est expliqué plus bas avec un exemple.
| Requête | Permission requise | Ce qu'il fait |
|---|---|---|
GET /members | members.read | Lister les membres, du changement le plus ancien au plus récent. |
GET /members/{id} | members.read | Un membre. |
POST /members | members.write | Ajouter un membre. Répond 201 avec le nouveau membre. |
PATCH /members/{id} | members.write | Modifier les champs envoyés d'un membre. |
POST /members/{id}/email-preferences | members.write | Désinscrit un membre des emails marketing de l'organisation, comme le lien de désinscription d'une campagne. Répond 200. |
GET /events | events.read | Lister les événements par heure de début. |
GET /events/{id} | events.read | Un événement avec ses inscriptions. |
POST /events | events.manage | Créer un événement en brouillon. Répond 201 avec l'événement. |
GET /dues-invoices | members.billing.read | Lister les factures de cotisation, de la plus ancienne à la plus récente. |
POST /webhooks | settings.manage | Abonner une URL de webhook à des événements. C'est ce qu'utilise Zapier. |
DELETE /webhooks/{id} | settings.manage | Désabonner un webhook abonné par l'API. |
GET /api/public/v1/members
Lister les membres, du changement le plus ancien au plus récent.
Permission requise : members.read
Paramètres
status(facultatif) : active, pending, lapsed, expired, suspended, archived ou at_risk.membership_type_id(facultatif) : l'id d'un des types d'adhésion de l'organisation.updated_since(facultatif) : une date et une heure avec fuseau horaire. Seulement les membres modifiés à ce moment ou après.email_marketing_opt_out(facultatif) :trueliste seulement les membres désinscrits des emails marketing de l'organisation,falseseulement les autres.pageetper_page(facultatifs) : voir Listes et formats.
Chaque membre a les champs ci-dessous. custom_fields contient les champs de membre propres à l'organisation, sous forme de clé du champ et de valeur.
email_marketing_opt_out vaut true quand le membre s'est désinscrit des emails marketing de l'organisation, et email_marketing_opted_out_at indique quand (null tant qu'il ne l'a pas fait). C'est la lecture qu'utilisent les campagnes de Melora Connect : un lien de désinscription ou une plainte depuis l'adresse, pour cette organisation ou pour tout Melora Connect, ou l'interrupteur d'email du membre pour l'organisation désactivé (aussi depuis une audience Mailchimp connectée). Un rebond n'est pas une désinscription, et la désinscription d'une organisation ne désinscrit jamais le membre d'une autre. Une désinscription ne modifie pas updated_at : suivez les webhooks member.unsubscribed et member.resubscribed, et rapprochez de temps en temps avec email_marketing_opt_out=true.
Champs : id, name, first_name, last_name, email, company, title, industry, phone, website, linkedin_url, city, state, zip, bio, status, membership_type_id, membership_category, tier, join_date, renewal_date, tags, show_in_directory, chapter_id, created_at, updated_at, custom_fields, email_marketing_opt_out, email_marketing_opted_out_at.
Exemple de requête
curl "https://app.meloraconnect.com/api/public/v1/members?status=active&per_page=50&page=1" \
-H "Authorization: Bearer $MELORA_API_KEY"Exemple de réponse, HTTP 200
{
"data": [
{
"id": "8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21",
"name": "Ana Ruiz",
"first_name": "Ana",
"last_name": "Ruiz",
"email": "ana@example.org",
"company": "Ruiz Consulting",
"status": "active",
"membership_type_id": "0b7a3c62-7f3e-4d7c-8a57-25a1c0a9d7e4",
"join_date": "2026-03-02",
"renewal_date": "2027-03-02",
"tags": ["board"],
"updated_at": "2026-09-28T14:03:11.402Z",
"email_marketing_opt_out": false,
"email_marketing_opted_out_at": null
}
],
"page": 1,
"per_page": 50,
"has_more": false
}GET /api/public/v1/members/{id}
Un membre.
Permission requise : members.read
Paramètres
id(dans le chemin) : l'id du membre.
Le membre a les mêmes champs que dans la liste. Un membre qui n'existe pas, ou qui appartient à une autre organisation, répond 404.
Exemple de requête
curl "https://app.meloraconnect.com/api/public/v1/members/8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21" \
-H "Authorization: Bearer $MELORA_API_KEY"Exemple de réponse, HTTP 200
{
"data": {
"id": "8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21",
"name": "Ana Ruiz",
"first_name": "Ana",
"last_name": "Ruiz",
"email": "ana@example.org",
"company": "Ruiz Consulting",
"status": "active",
"membership_type_id": "0b7a3c62-7f3e-4d7c-8a57-25a1c0a9d7e4",
"join_date": "2026-03-02",
"renewal_date": "2027-03-02",
"tags": [
"board"
],
"updated_at": "2026-09-28T14:03:11.402Z",
"email_marketing_opt_out": false,
"email_marketing_opted_out_at": null,
"custom_fields": {
"member_since_year": 2019
}
}
}POST /api/public/v1/members
Ajouter un membre. Répond 201 avec le nouveau membre.
Permission requise : members.write
Paramètres
email(obligatoire) : un membre par adresse e-mail dans l'organisation.name, oufirst_nameetlast_name(obligatoire) : au moins l'un d'eux.status(facultatif) : active, la valeur par défaut, ou pending, lapsed, expired, suspended ou archived.join_dateetrenewal_date(facultatifs) : des dates au formatYYYY-MM-DD.membership_type_id(facultatif) : un des types d'adhésion de l'organisation.- Également facultatifs :
company,title,industry,phone,website,linkedin_url,city,state,zip,bioettags(une liste de mots). start_welcome_drips(facultatif) :truepour lancer les campagnes New member de l'organisation pour un membre actif.
Un membre actif occupe une des places de membres actifs de la formule ; quand il n'en reste plus, la réponse est 403 limit_reached. Une adresse e-mail qui appartient déjà à un membre de l'organisation répond 409 conflict, avec l'id de ce membre dans details.existing_member_id.
Un membre ajouté par l'API ne rejoint aucune campagne d'e-mails automatique de l'organisation : un système qui copie toute une liste de membres n'envoie donc pas de bienvenue à tout le monde. Pour accueillir un nouveau membre, envoyez start_welcome_drips à true : un membre actif rejoint alors les campagnes New member de l'organisation, comme un membre ajouté à la main, et la réponse contient welcome_drips.enrolled, le nombre de campagnes rejointes (0 pour un membre qui n'est pas actif).
phone doit compter de 7 à 15 chiffres et est enregistré sous forme de chiffres, en gardant un + initial (+1 (703) 555-0142 est enregistré comme +17035550142). website doit être une adresse http ou https et est enregistré avec son schéma (https:// est ajouté s'il manque). linkedin_url doit être une adresse https sur linkedin.com. Une valeur vide efface le champ. Une valeur non valide répond 422 validation_failed, et details nomme le champ.
Exemple de requête
curl -X POST "https://app.meloraconnect.com/api/public/v1/members" \
-H "Authorization: Bearer $MELORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"first_name":"Ana","last_name":"Ruiz","email":"ana@example.org","company":"Ruiz Consulting","status":"active","renewal_date":"2027-03-02","tags":["board"]}'Exemple de réponse, HTTP 201
{
"data": {
"id": "8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21",
"name": "Ana Ruiz",
"first_name": "Ana",
"last_name": "Ruiz",
"email": "ana@example.org",
"company": "Ruiz Consulting",
"status": "active",
"membership_type_id": "0b7a3c62-7f3e-4d7c-8a57-25a1c0a9d7e4",
"join_date": "2026-03-02",
"renewal_date": "2027-03-02",
"tags": [
"board"
],
"updated_at": "2026-09-28T14:03:11.402Z",
"email_marketing_opt_out": false,
"email_marketing_opted_out_at": null,
"custom_fields": {}
}
}PATCH /api/public/v1/members/{id}
Modifier les champs envoyés d'un membre.
Permission requise : members.write
Paramètres
id(dans le chemin) : l'id du membre.- Corps : n'importe lesquels de
name,first_name,last_name,email,company,title,industry,phone,website,linkedin_url,city,state,zip,bio,tags,membership_type_id,statusetrenewal_date. Envoyez-en au moins un.
Tout autre champ est refusé avec 422. Le statut at_risk est calculé par Melora Connect à partir de l'activité du membre et ne peut pas être fixé, et les points, l'engagement et les données de connexion ne peuvent pas être modifiés. membership_type_id doit être un des types d'adhésion de l'organisation.
Rendre un membre actif occupe une des places de membres actifs de la formule. Si le statut du membre a changé pendant le traitement de votre requête, la réponse est 409 conflict : relisez le membre et réessayez.
phone, website et linkedin_url sont vérifiés comme lors de l'ajout d'un membre. N'envoyez que les champs que vous modifiez : un enregistrement plus ancien peut contenir un numéro de téléphone qui ne passe pas les vérifications actuelles, et renvoyer tout l'enregistrement peut donc être refusé.
Exemple de requête
curl -X PATCH "https://app.meloraconnect.com/api/public/v1/members/8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21" \
-H "Authorization: Bearer $MELORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phone":"+1 555 0100","status":"lapsed"}'Exemple de réponse, HTTP 200
{
"data": {
"id": "8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21",
"name": "Ana Ruiz",
"first_name": "Ana",
"last_name": "Ruiz",
"email": "ana@example.org",
"company": "Ruiz Consulting",
"status": "lapsed",
"membership_type_id": "0b7a3c62-7f3e-4d7c-8a57-25a1c0a9d7e4",
"join_date": "2026-03-02",
"renewal_date": "2027-03-02",
"tags": [
"board"
],
"updated_at": "2026-10-04T10:12:45.118Z",
"email_marketing_opt_out": false,
"email_marketing_opted_out_at": null,
"phone": "+15550100"
}
}POST /api/public/v1/members/{id}/email-preferences
Désinscrit un membre des emails marketing de l'organisation, comme le lien de désinscription d'une campagne. Répond 200.
Permission requise : members.write
Paramètres
id(dans le chemin) : l'id du membre.- Corps :
email_marketing_opt_out(obligatoire),true. Tout autre champ est refusé avec422.
La prochaine campagne de l'organisation laisse le membre de côté, son interrupteur d'email pour l'organisation est désactivé et il quitte ses listes de newsletters. Les emails des autres organisations ne sont pas touchés. La réponse contient member_id, email_marketing_opt_out et email_marketing_opted_out_at ; redemander pour un membre déjà désinscrit ne change rien. Le changement figure dans le journal d'audit de l'organisation avec le nom de la clé. Un membre sans adresse email répond 422.
Une clé ne peut pas réinscrire un membre : false répond 422 validation_failed. Seul le membre peut réactiver les emails de l'organisation, dans Melora Connect, et member.resubscribed est alors envoyé.
Exemple de requête
curl -X POST "https://app.meloraconnect.com/api/public/v1/members/8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21/email-preferences" \
-H "Authorization: Bearer $MELORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email_marketing_opt_out":true}'Exemple de réponse, HTTP 200
{
"data": {
"member_id": "8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21",
"email_marketing_opt_out": true,
"email_marketing_opted_out_at": "2026-11-05T09:12:44.120Z"
}
}GET /api/public/v1/events
Lister les événements par heure de début.
Permission requise : events.read
Paramètres
status(facultatif) : draft, published, cancelled, completed ou archived.starts_after(facultatif) : une date et une heure avec fuseau horaire. Seulement les événements qui commencent à ce moment ou après.updated_since(facultatif) : seulement les événements modifiés à ce moment ou après.pageetper_page(facultatifs) : voir Listes et formats.
Chaque événement a les champs ci-dessous. Les prix sont en cents.
Champs : id, title, description, event_type, status, starts_at, ends_at, timezone, venue, address, is_virtual, capacity, ticket_price_cents, member_price_cents, highlights, slug, published_at, created_at, updated_at, tags.
Exemple de requête
curl "https://app.meloraconnect.com/api/public/v1/events?starts_after=2026-11-01T00:00:00Z&per_page=20" \
-H "Authorization: Bearer $MELORA_API_KEY"Exemple de réponse, HTTP 200
{
"data": [
{
"id": "5e0c1d8a-9b2f-4c1e-8f3a-6a7b8c9d0e1f",
"title": "Autumn networking breakfast",
"event_type": "networking",
"status": "published",
"starts_at": "2026-11-12T13:00:00+00:00",
"ends_at": "2026-11-12T14:30:00+00:00",
"timezone": "America/New_York",
"venue": "Harbor Hall",
"is_virtual": false,
"capacity": 80,
"ticket_price_cents": 2500,
"member_price_cents": 1500,
"published_at": "2026-10-01T15:00:00+00:00"
}
],
"page": 1,
"per_page": 20,
"has_more": false
}GET /api/public/v1/events/{id}
Un événement avec ses inscriptions.
Permission requise : events.read
Paramètres
id(dans le chemin) : l'id de l'événement.
Les champs de l'événement, plus host_committee_name (le comité qui l'organise, ou null) et registrations, chacune avec les champs ci-dessous. Dans une inscription, member_id est la fiche de membre de la personne inscrite, ou null pour un invité.
Champs : id, status, member_id, guest_name, guest_email, ticket_tier_id, checked_in_at, created_at.
Exemple de requête
curl "https://app.meloraconnect.com/api/public/v1/events/5e0c1d8a-9b2f-4c1e-8f3a-6a7b8c9d0e1f" \
-H "Authorization: Bearer $MELORA_API_KEY"Exemple de réponse, HTTP 200
{
"data": {
"id": "5e0c1d8a-9b2f-4c1e-8f3a-6a7b8c9d0e1f",
"title": "Autumn networking breakfast",
"status": "published",
"starts_at": "2026-11-12T13:00:00+00:00",
"capacity": 80,
"registrations": [
{
"id": "a1b2c3d4-0000-4000-8000-000000000001",
"status": "confirmed",
"member_id": "8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21",
"guest_name": null,
"guest_email": null,
"ticket_tier_id": null,
"checked_in_at": null,
"created_at": "2026-10-02T15:20:00+00:00"
}
]
}
}POST /api/public/v1/events
Créer un événement en brouillon. Répond 201 avec l'événement.
Permission requise : events.manage
Paramètres
title(obligatoire) : de 2 à 120 caractères.event_type(obligatoire) : le type d'événement, par exemple networking.format(obligatoire) : in_person, virtual ou hybrid.starts_at(obligatoire) etends_at(facultatif) : des dates et heures avec fuseau horaire.timezone(facultatif) : le nom d'un fuseau horaire comme America/New_York, la valeur par défaut.ticket_price_centsetmember_price_cents(facultatifs) : des prix en cents, 0 par défaut.capacity(facultatif) : le nombre de places.- Également facultatifs :
description,venue,address,highlights,tags(une liste de mots) etlanguage(en, es ou fr).
L'événement est enregistré en brouillon. Le personnel le relit et le publie dans Melora Connect, et y ajoute le lien de connexion d'un événement virtuel. Si les événements ne font pas partie de la formule de l'organisation, la réponse est 403 plan_required.
Exemple de requête
curl -X POST "https://app.meloraconnect.com/api/public/v1/events" \
-H "Authorization: Bearer $MELORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Autumn networking breakfast","event_type":"networking","format":"in_person","starts_at":"2026-11-12T08:00:00-05:00","ends_at":"2026-11-12T09:30:00-05:00","timezone":"America/New_York","venue":"Harbor Hall","capacity":80,"ticket_price_cents":2500,"member_price_cents":1500}'Exemple de réponse, HTTP 201
{
"data": {
"id": "5e0c1d8a-9b2f-4c1e-8f3a-6a7b8c9d0e1f",
"title": "Autumn networking breakfast",
"event_type": "networking",
"status": "draft",
"starts_at": "2026-11-12T13:00:00+00:00",
"ends_at": "2026-11-12T14:30:00+00:00",
"timezone": "America/New_York",
"venue": "Harbor Hall",
"is_virtual": false,
"capacity": 80,
"ticket_price_cents": 2500,
"member_price_cents": 1500,
"published_at": null
}
}GET /api/public/v1/dues-invoices
Lister les factures de cotisation, de la plus ancienne à la plus récente.
Permission requise : members.billing.read
Paramètres
status(facultatif) : open, paid, past_due, void, refunded ou failed.member_id(facultatif) : seulement les factures de ce membre.updated_since(facultatif) : seulement les factures modifiées à ce moment ou après.pageetper_page(facultatifs) : voir Listes et formats.
Chaque facture a les champs ci-dessous. Les montants sont en cents. Les factures sont en lecture seule : les paiements se font dans Melora Connect.
Champs : id, invoice_number, member_id, dues_subscription_id, status, amount_cents, subtotal_cents, discount_cents, discount_code, currency, period_start, period_end, due_at, paid_at, paid_via, voided_at, void_reason, replaces_invoice_id, created_at, updated_at.
Exemple de requête
curl "https://app.meloraconnect.com/api/public/v1/dues-invoices?status=paid&updated_since=2026-01-01T00:00:00Z" \
-H "Authorization: Bearer $MELORA_API_KEY"Exemple de réponse, HTTP 200
{
"data": [
{
"id": "c4a1e7b2-6d3f-4e8a-9b1c-2d3e4f5a6b7c",
"invoice_number": "INV-2026-0142",
"member_id": "8d2c6f0e-3f59-4a53-9c0e-0f6f5b3a1b21",
"dues_subscription_id": "f1e2d3c4-b5a6-4978-8a9b-0c1d2e3f4a5b",
"status": "paid",
"amount_cents": 25000,
"subtotal_cents": 25000,
"discount_cents": 0,
"discount_code": null,
"currency": "USD",
"period_start": "2026-03-02",
"period_end": "2027-03-01",
"due_at": "2026-03-02T00:00:00+00:00",
"paid_at": "2026-02-27T16:40:12+00:00",
"paid_via": "stripe",
"voided_at": null,
"void_reason": null,
"replaces_invoice_id": null,
"created_at": "2026-02-01T09:00:00+00:00",
"updated_at": "2026-02-27T16:40:12+00:00"
}
],
"page": 1,
"per_page": 50,
"has_more": false
}POST /api/public/v1/webhooks
Abonner une URL de webhook à des événements. C'est ce qu'utilise Zapier.
Permission requise : settings.manage
Paramètres
url(obligatoire) : une adresse https qui passe les vérifications de l'endpoint.events(obligatoire) : une liste d'un ou plusieurs événements de webhook.include_contact_details(facultatif) :truepour envoyer les coordonnées des membres. La clé a alors aussi besoin demembers.read.
Une nouvelle URL répond 201. Abonner à nouveau la même URL remplace ses événements et répond 200. Chaque URL compte dans les 10 endpoints qu'une organisation peut avoir ; au-delà, la réponse est 403 limit_reached.
Une URL que le personnel a déjà ajoutée dans l'onglet Webhooks répond 409 : supprimez-la d'abord à cet endroit. Si les webhooks ne font pas partie de la formule de l'organisation, la réponse est 403 plan_required.
La réponse contient id, url, events et include_contact_details de l'endpoint, mais pas de secret de signature. L'endpoint apparaît dans l'onglet Webhooks comme ajouté par l'API, où le personnel peut émettre un nouveau secret, affiché une fois, pour un récepteur qui vérifie les signatures.
Exemple de requête
curl -X POST "https://app.meloraconnect.com/api/public/v1/webhooks" \
-H "Authorization: Bearer $MELORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.example.com/melora/members","events":["member.created","member.status_changed"]}'Exemple de réponse, HTTP 201
{
"data": {
"id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"url": "https://hooks.example.com/melora/members",
"events": [
"member.created",
"member.status_changed"
],
"include_contact_details": false
}
}DELETE /api/public/v1/webhooks/{id}
Désabonner un webhook abonné par l'API.
Permission requise : settings.manage
Paramètres
id(dans le chemin) : l'id renvoyé par l'abonnement.
Répond 204 sans corps, et les envois vers cette URL s'arrêtent. Un endpoint que le personnel a ajouté dans l'onglet Webhooks, ou celui d'une autre organisation, répond 404 : une clé ne supprime jamais un endpoint configuré par le personnel.
Exemple de requête
curl -X DELETE "https://app.meloraconnect.com/api/public/v1/webhooks/2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e" \
-H "Authorization: Bearer $MELORA_API_KEY"Exemple de réponse, HTTP 204
Pas de corps.
Erreurs
Chaque erreur est un JSON avec un code qui ne change pas, un message destiné aux personnes et parfois details. Basez votre logique sur le code, pas sur le message.
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "permission_denied",
"message": "This API key does not have the members.write permission.",
"details": { "required_permission": "members.write" }
}
}| Statut HTTP | Code d'erreur | Signification |
|---|---|---|
| 401 | invalid_api_key | Pas de clé, une clé mal formée ou une clé que Melora Connect ne connaît pas. Envoyez la clé après Bearer dans l'en-tête Authorization. |
| 401 | api_key_revoked | La clé a été révoquée. Créez-en une nouvelle. |
| 401 | api_key_expired | La clé a dépassé sa date d'expiration. Créez-en une nouvelle. |
| 403 | plan_required | La formule n'inclut pas l'API (ou la fonctionnalité dont la requête a besoin), la requête est donc refusée. |
| 403 | permission_denied | La clé n'a pas la permission dont cette requête a besoin. details.required_permission la nomme. |
| 403 | billing_hold | Le compte Melora Connect est suspendu pour une facture impayée, ce qui met en pause ce type de requête. |
| 403 | account_restricted | Le compte est restreint : rien de nouveau ne peut être créé. |
| 403 | limit_reached | Une limite de la formule, par exemple le nombre de membres actifs, serait dépassée. |
| 404 | not_found | Cet enregistrement n'existe pas ici. Les enregistrements des autres organisations ne sont jamais montrés. |
| 422 | validation_failed | Le corps de la requête ou un paramètre de requête n'est pas valide. details liste chaque problème. |
| 409 | conflict | L'enregistrement entre en conflit avec un enregistrement existant. |
| 413 | payload_too_large | Le corps de la requête dépasse 64 Ko. Envoyez moins de champs ou divisez le travail. |
| 429 | rate_limited | Trop de requêtes. Attendez le nombre de secondes indiqué par l'en-tête Retry-After. |
| 500 | internal_error | Un problème est survenu du côté de Melora Connect. Réessayez la requête. |
Exemples de code
Node.js
Node.js 18 ou plus récent : lire tous les membres actifs, une page à la fois, en attendant quand la limite est atteinte.
// Node.js 18 or later: read every active member, a page at a time.
const base = "https://app.meloraconnect.com/api/public/v1";
const headers = { Authorization: `Bearer ${process.env.MELORA_API_KEY}` };
async function allActiveMembers() {
const members = [];
for (let page = 1; ; page++) {
const res = await fetch(`${base}/members?status=active&per_page=100&page=${page}`, { headers });
if (res.status === 429) {
await new Promise((r) => setTimeout(r, Number(res.headers.get("retry-after") ?? 60) * 1000));
page--;
continue;
}
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
members.push(...body.data);
if (!body.has_more) return members;
}
}Python
Python 3 avec requests : ajouter un membre, ou trouver celui qui a déjà cette adresse e-mail.
# Python 3 with requests: add a member, or find the one that already has the email.
import os, requests
base = "https://app.meloraconnect.com/api/public/v1"
headers = {"Authorization": f"Bearer {os.environ['MELORA_API_KEY']}"}
res = requests.post(f"{base}/members", headers=headers, json={
"first_name": "Ana", "last_name": "Ruiz", "email": "ana@example.org",
})
if res.status_code == 409:
member_id = res.json()["error"]["details"]["existing_member_id"]
else:
res.raise_for_status()
member_id = res.json()["data"]["id"]Bonnes pratiques
- Donnez à chaque clé seulement les permissions dont son système a besoin.
- Gardez les clés sur votre serveur. Révoquez immédiatement une clé qui a pu fuiter.
- Chaque modification faite avec une clé apparaît dans le journal d'audit de l'organisation avec le nom de la clé.
- Pour être informé des changements au moment où ils se produisent, plutôt que de redemander sans cesse, utilisez les webhooks.

Personnes · Événements · Communautés

