Changelog

Every change to the public contract of the v1 API, dated, newest first.

API documentationChangelog

A published version only grows by addition: the versioning guide details what may change and what never does.

October 27, 2026

OpenAPI description fingerprint: sha256:a65a25a7b626

  • New externalId field on contacts: the contact identifier in your CRM or POS, at most 128 characters and unique per establishment. It is sent to POST /v1/contacts and changed or cleared through PATCH /v1/contacts/{contactId}. POST /v1/contacts first recognises an existing contact by this identifier, before the email and phone. It is returned in the Contact and EventContact objects, searchable through GET /v1/contacts?externalId= and tracked by contact.updated. Survey responses (SurveyResponse, survey_response.completed event) carry two new fields, contactExternalId and visitExternalId (the external identifier of the visit that triggered the survey), and their channel field takes two new values: qr and nfc, for answers that came through the survey's QR code or NFC tag. These answers are anonymous: their contactId is null.

OpenAPI description fingerprint: sha256:190efdd4e278

  • Contact events (contact.created, contact.updated, contact.unsubscribed) no longer carry the phone number: their object follows the new EventContact shape, identical to Contact without phone. The phone number is read through GET /v1/contacts/{contactId} with the contacts:read scope. Payloads already stored have been redacted. In addition, a review (GET /v1/reviews, GET /v1/reviews/{reviewId}) carries a new draft field, the reply draft in progress (ReplyDraft) or null, present only for a key with replies:write or ai:generate and never in events: a tool can read back the draft it has just written or generated.

October 26, 2026

OpenAPI description fingerprint: sha256:100319d11a31

  • New survey_response.completed event (/v1/events API and webhooks): a customer completed a satisfaction survey. The carried object is the answer in its new public SurveyResponse shape (survey, contact, channel, language, recommendation score and NPS category, question-by-question answers). Partial answers and test sends produce no event.

October 25, 2026

OpenAPI description fingerprint: sha256:d8eb6b6fb75e

  • Contact events (contact.created, contact.updated, contact.unsubscribed), which carry personal data, now also require the contacts:read scope: without it, GET /v1/events leaves them out, and GET /v1/events?types=contact.…, GET /v1/events/{eventId} on a contact event and POST /v1/webhook-endpoints subscribed to a contact.* type answer 403 insufficient_scope. A key no longer reads through events a customer base it cannot read through GET /v1/contacts.

OpenAPI description fingerprint: sha256:e186712a1523

  • Read operations for establishments, their statistics, reviews, private feedback and contacts are now stable (x-stability: stable), like GET /v1/health, GET /v1/openapi.json and GET /v1/me. They will no longer receive any breaking change in v1, and any deprecation will be announced 12 months in advance. The event log, webhooks, writes and publishing to Google remain in beta.

OpenAPI description fingerprint: sha256:6137c9c2b9c0

  • Publishing to Google, in beta: POST /v1/reviews/{reviewId}/reply (replies:publish scope) publishes a reply through the same path as the application and returns the answered review. The establishment must have authorized publishing through the API in the application (403 google_publishing_not_authorized), the Idempotency-Key header is required (400 invalid_request without it), a sensitive reply requires acknowledgedSensitivity: true (422 unprocessable), Google writes of an establishment are limited (429 rate_limited) and publishing through the API can be switched off for every account (503 google_publishing_disabled). Draft and publishing operations are grouped under the "Review replies" tag.

OpenAPI description fingerprint: sha256:2af79d83939e

  • Writes, in beta, all refused with 403 tenant_read_only on a read-only account and replayable with Idempotency-Key: POST /v1/contacts (creates a contact in an establishment's customer base, 201, or completes the one with the same email or phone, 200; contacts:write scope), PATCH /v1/contacts/{contactId} (contacts:write scope), POST /v1/visits (records a visit, a single one per externalId within an establishment even without Idempotency-Key: 201 then 200; visits:write scope), POST /v1/promo-codes/redeem (redeems a promo code as at the counter; 409 promo_code_already_redeemed, 409 promo_code_expired, 404 not_found, attempts limited per key; promo_codes:redeem scope), POST /v1/reviews/{reviewId}/reply-drafts (AI draft, one unit of the monthly AI credit, 402 ai_credits_exhausted; ai:generate scope, rate limit cost 5) and PUT /v1/reviews/{reviewId}/reply-draft (written draft, 201 or 200; replies:write scope). Every transmitted consent requires its proof (collectedAt, proofText), otherwise 400 invalid_request; an opt-out always prevails. New api origin in the consent sources of contacts and in visit sources, and contact.created with the api origin for a contact created through the API.

October 24, 2026

OpenAPI description fingerprint: sha256:c3243efa00eb

  • Webhooks, in beta (webhooks:manage scope): GET /v1/webhook-endpoints, POST /v1/webhook-endpoints (returns the whsec_… signing secret only once), DELETE /v1/webhook-endpoints/{endpointId} and POST /v1/webhook-endpoints/{endpointId}/test (sends a webhook.test event and returns the result). An endpoint receives the chosen events of every establishment of the account, as signed HTTPS POST requests in the Standard Webhooks format (webhook-id, webhook-timestamp, webhook-signature), at least once and without ordering guarantee, retried for 72 hours then disabled. At most 10 endpoints per account (409 webhook_endpoint_limit_reached); a non-HTTPS address, an IP, an internal name or a private address are refused (422 unprocessable). Events are now produced as soon as an API key or an endpoint of the account is active.

OpenAPI description fingerprint: sha256:d60253b81fe9

  • Event log, in beta: GET /v1/events and GET /v1/events/{eventId} (events:read scope). Every fact of the account (new review, review edited or deleted from the platform, reply published, private feedback received, contact created, updated or unsubscribed) produces a single event, whatever the path that caused it, with its origin (sync, import, app, autopilot, api, system) and the related object in its public shape. Events are read in publication order from the after position; nextCursor is never null and is kept from one synchronisation to the next. types and establishmentId filters, 30-day retention.
  • The type field of errors points to the public documentation https://mabellenote.com/developers/errors#<code>.

OpenAPI description fingerprint: sha256:91914f649b48

  • Every keyed operation may answer 503 service_unavailable with Retry-After when admitting the request fails transiently, for instance under a heavy burst of concurrent calls. The request had no effect: send it again after the given delay. The limit of 120 calls per minute and per key is now counted per calendar minute (UTC): RateLimit-Reset gives the number of seconds until the next minute.

OpenAPI description fingerprint: sha256:64146cc11f26

  • Read access to the account resources, in beta: GET /v1/establishments, GET /v1/establishments/{establishmentId} and GET /v1/establishments/{establishmentId}/stats (establishments:read scope, stats:read for statistics), GET /v1/reviews and GET /v1/reviews/{reviewId} (reviews:read), GET /v1/feedbacks and GET /v1/feedbacks/{feedbackId} (feedbacks:read), GET /v1/contacts and GET /v1/contacts/{contactId} (contacts:read). Lists are paginated with an opaque cursor (limit up to 100, nextCursor), dates use the ISO 8601 format in UTC, and a disconnected establishment stays readable until its scheduledPurgeAt purge date.

OpenAPI description fingerprint: sha256:e00be79eda1d

  • Authentication with the account API key (Authorization: Bearer mbn_live_…) and GET /v1/me, which describes the account, the key and its rate limit. Limit of 120 calls per minute and per key, announced by the RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers, with Retry-After when exceeded.

OpenAPI description fingerprint: sha256:1d7914e551eb

  • API foundation: GET /v1/health and GET /v1/openapi.json?lang=fr|en, errors in the application/problem+json format, X-Request-Id request identifier on every response.