Journal des changements

Chaque modification du contrat public de l'API v1, datée, la plus récente en tête.

Documentation de l'APIJournal des changements

Une version publiée n'évolue que par ajout : le guide de versionnage détaille ce qui peut changer et ce qui ne change jamais.

27 octobre 2026

Empreinte de la description OpenAPI : sha256:a65a25a7b626

  • Nouveau champ externalId sur les contacts : l'identifiant du contact dans votre CRM ou votre caisse, 128 caractères au plus et unique par établissement. Il se transmet à POST /v1/contacts et se modifie ou s'efface par PATCH /v1/contacts/{contactId}. POST /v1/contacts reconnaît d'abord un contact existant par cet identifiant, avant l'email et le téléphone. Il est renvoyé dans les objets Contact et EventContact, recherchable par GET /v1/contacts?externalId= et suivi par contact.updated. Les réponses d'enquête (SurveyResponse, événement survey_response.completed) portent deux nouveaux champs, contactExternalId et visitExternalId (l'identifiant externe du passage qui a déclenché l'enquête), et leur champ channel prend deux nouvelles valeurs : qr et nfc, pour les réponses arrivées par le QR code ou la puce NFC de l'enquête. Ces réponses sont anonymes : leur contactId vaut null.

Empreinte de la description OpenAPI : sha256:190efdd4e278

  • Les événements de contact (contact.created, contact.updated, contact.unsubscribed) ne portent plus le téléphone : leur objet suit la nouvelle forme EventContact, identique à Contact sans phone. Le téléphone se lit par GET /v1/contacts/{contactId} avec le droit contacts:read. Les charges utiles déjà conservées ont été expurgées. Par ailleurs, un avis (GET /v1/reviews, GET /v1/reviews/{reviewId}) porte un nouveau champ draft, le brouillon de réponse en cours (ReplyDraft) ou null, présent seulement pour une clé qui a replies:write ou ai:generate et jamais dans les événements : un outil peut relire le brouillon qu'il vient de déposer ou de générer.

26 octobre 2026

Empreinte de la description OpenAPI : sha256:100319d11a31

  • Nouvel événement survey_response.completed (API /v1/events et webhooks) : un client a terminé une enquête de satisfaction. L'objet porté est la réponse dans sa nouvelle forme publique SurveyResponse (enquête, contact, canal, langue, note de recommandation et catégorie NPS, réponses question par question). Les réponses partielles et les envois de test ne produisent aucun événement.

25 octobre 2026

Empreinte de la description OpenAPI : sha256:d8eb6b6fb75e

  • Les événements de contact (contact.created, contact.updated, contact.unsubscribed), qui portent des données personnelles, exigent désormais aussi le droit contacts:read : sans ce droit, GET /v1/events les omet, et GET /v1/events?types=contact.…, GET /v1/events/{eventId} sur un événement de contact et POST /v1/webhook-endpoints abonné à un type contact.* répondent 403 insufficient_scope. Une clé ne lit plus par les événements une base clients qu'elle ne peut pas lire par GET /v1/contacts.

Empreinte de la description OpenAPI : sha256:e186712a1523

  • Les opérations de lecture des établissements, de leurs statistiques, des avis, des retours privés et des contacts passent en version stable (x-stability: stable), comme GET /v1/health, GET /v1/openapi.json et GET /v1/me. Elles ne subiront plus aucun changement cassant en v1, et toute dépréciation sera annoncée 12 mois à l'avance. Le journal d'événements, les webhooks, les écritures et la publication sur Google restent en bêta.

Empreinte de la description OpenAPI : sha256:6137c9c2b9c0

  • Publication sur Google, en version bêta : POST /v1/reviews/{reviewId}/reply (scope replies:publish) publie une réponse par le même chemin que l'application et renvoie l'avis répondu. L'établissement doit avoir autorisé la publication par l'API dans l'application (403 google_publishing_not_authorized), l'en-tête Idempotency-Key est obligatoire (400 invalid_request sans lui), une réponse sensible exige acknowledgedSensitivity: true (422 unprocessable), les écritures Google d'un établissement sont limitées (429 rate_limited) et la publication par l'API peut être coupée pour tous les comptes (503 google_publishing_disabled). Les opérations de brouillon et de publication sont regroupées sous l'étiquette « Réponses aux avis ».

Empreinte de la description OpenAPI : sha256:2af79d83939e

  • Écritures, en version bêta, toutes refusées en 403 tenant_read_only sur un compte en lecture seule et rejouables avec Idempotency-Key : POST /v1/contacts (crée un contact dans la base clients d'un établissement, 201, ou complète celui qui a le même email ou téléphone, 200 ; scope contacts:write), PATCH /v1/contacts/{contactId} (scope contacts:write), POST /v1/visits (enregistre un passage, un seul par externalId dans un établissement même sans Idempotency-Key : 201 puis 200 ; scope visits:write), POST /v1/promo-codes/redeem (valide un code promo comme au comptoir ; 409 promo_code_already_redeemed, 409 promo_code_expired, 404 not_found, tentatives limitées par clé ; scope promo_codes:redeem), POST /v1/reviews/{reviewId}/reply-drafts (brouillon IA, une unité du crédit IA mensuel, 402 ai_credits_exhausted ; scope ai:generate, coût de débit 5) et PUT /v1/reviews/{reviewId}/reply-draft (brouillon rédigé, 201 ou 200 ; scope replies:write). Tout consentement transmis exige sa preuve (collectedAt, proofText), sinon 400 invalid_request ; une désinscription prime toujours. Nouvelle origine api dans les sources de consentement des contacts et des passages, et contact.created d'origine api pour un contact créé par l'API.

24 octobre 2026

Empreinte de la description OpenAPI : sha256:c3243efa00eb

  • Webhooks, en version bêta (scope webhooks:manage) : GET /v1/webhook-endpoints, POST /v1/webhook-endpoints (renvoie une seule fois le secret de signature whsec_…), DELETE /v1/webhook-endpoints/{endpointId} et POST /v1/webhook-endpoints/{endpointId}/test (envoie un événement webhook.test et renvoie le résultat). Un point de réception reçoit les événements choisis de tous les établissements du compte, en POST HTTPS signé au format Standard Webhooks (webhook-id, webhook-timestamp, webhook-signature), au moins une fois et sans garantie d'ordre, relancé pendant 72 heures puis désactivé. Au plus 10 points de réception par compte (409 webhook_endpoint_limit_reached) ; une adresse non HTTPS, une IP, un nom interne ou une adresse privée sont refusés (422 unprocessable). Les événements sont désormais produits dès qu'une clé API ou un point de réception du compte est actif.

Empreinte de la description OpenAPI : sha256:d60253b81fe9

  • Journal d'événements, en version bêta : GET /v1/events et GET /v1/events/{eventId} (scope events:read). Chaque fait du compte (nouvel avis, avis modifié ou supprimé de la plateforme, réponse publiée, retour privé reçu, contact créé, modifié ou désinscrit) produit un seul événement, quel que soit le chemin qui l'a causé, avec son origine (sync, import, app, autopilot, api, system) et l'objet concerné dans sa forme publique. Les événements se lisent dans l'ordre de publication à partir de la position after ; nextCursor n'est jamais null et se conserve d'une synchronisation à l'autre. Filtres types et establishmentId, rétention de 30 jours.
  • Le champ type des erreurs pointe vers la documentation publique https://mabellenote.com/developers/errors#<code>.

Empreinte de la description OpenAPI : sha256:91914f649b48

  • Toute opération à clé peut répondre 503 service_unavailable avec Retry-After quand l'admission de la requête échoue de façon passagère, par exemple sous une forte rafale d'appels simultanés. La requête n'a eu aucun effet : la renvoyer après le délai indiqué. La limite de 120 appels par minute et par clé se compte désormais par minute calendaire (UTC) : RateLimit-Reset donne le nombre de secondes jusqu'à la minute suivante.

Empreinte de la description OpenAPI : sha256:64146cc11f26

  • Lecture des ressources du compte, en version bêta : GET /v1/establishments, GET /v1/establishments/{establishmentId} et GET /v1/establishments/{establishmentId}/stats (scope establishments:read, stats:read pour les statistiques), GET /v1/reviews et GET /v1/reviews/{reviewId} (reviews:read), GET /v1/feedbacks et GET /v1/feedbacks/{feedbackId} (feedbacks:read), GET /v1/contacts et GET /v1/contacts/{contactId} (contacts:read). Les listes sont paginées par curseur opaque (limit jusqu'à 100, nextCursor), les dates sont au format ISO 8601 en UTC, et un établissement déconnecté reste lisible jusqu'à sa date de purge scheduledPurgeAt.

Empreinte de la description OpenAPI : sha256:e00be79eda1d

  • Authentification par clé API du compte (Authorization: Bearer mbn_live_…) et GET /v1/me, qui décrit le compte, la clé et sa limite de débit. Limite de 120 appels par minute et par clé, annoncée par les en-têtes RateLimit-Limit, RateLimit-Remaining et RateLimit-Reset, Retry-After en cas de dépassement.

Empreinte de la description OpenAPI : sha256:1d7914e551eb

  • Socle de l'API : GET /v1/health et GET /v1/openapi.json?lang=fr|en, erreurs au format application/problem+json, identifiant de requête X-Request-Id sur chaque réponse.