Authentication and scopes
How an API key is sent, what it covers, the scopes it carries and what the account's plan changes.
API documentationGuides · Authentication and scopes
Sending the key
Every call carries the account key in the Authorization header, with the Bearer scheme:
curl https://api.mabellenote.com/v1/me \
-H "Authorization: Bearer mbn_live_..."
The key never goes in the URL or in the request body. Only GET /v1/health and GET /v1/openapi.json work without a key.
A key's lifecycle
- Creation: in the app, Settings › Integration, API & webhooks, by an owner or an admin. Every new key is announced by email to the account's owners and admins.
- Shown once: the full key only appears when it is created. It can never be retrieved afterwards, not even by support. The app only shows its visible prefix, such as
mbn_live_AbC1, so you can recognize it. - Coverage: a key covers the whole account, that is all its locations, current and future.
- Number: an account has at most 10 active keys.
- Expiration: optional, chosen at creation (30 days, 90 days, one year or never). After that date, the API answers
401 api_key_expired. - Revocation: immediate and final. The next call receives
401 api_key_revoked. - Ownership: a key belongs to the account, not to the person who created it. It keeps working if that person leaves the account, and the owners are told.
| Situation | Response |
|---|---|
No Authorization header, or no Bearer scheme | 401 authentication_required |
Unknown key, or a key that does not start with mbn_live_ | 401 invalid_api_key |
| Revoked key | 401 api_key_revoked |
| Expired key | 401 api_key_expired |
Scopes
A key carries the list of scopes chosen when it was created. The app offers templates: Read only (locations, reviews, statistics, private feedback), CRM (read access and customer base), Till (locations, contacts, visits and promo codes) or Custom. Scopes cannot be edited afterwards: to change them, create a new key, switch your integration to it, then revoke the old one.
An operation called without the scope it requires answers 403 insufficient_scope. The scope each operation requires is listed in the reference.
| Scope | What it allows | Operations |
|---|---|---|
account:read | Identify the account and the key behind the call. Always granted, whatever the key. | GET /v1/me |
establishments:read | Read locations, their Google connection and their review counters. | GET /v1/establishmentsGET /v1/establishments/{establishmentId} |
reviews:read | Read reviews, their published reply and their analysis. | GET /v1/reviewsGET /v1/reviews/{reviewId} |
stats:read | Read review statistics per day or per month. | GET /v1/establishments/{establishmentId}/stats |
feedbacks:read | Read private feedback left through your QR codes. Personal data. | GET /v1/feedbacksGET /v1/feedbacks/{feedbackId} |
contacts:read | Read the customer base: contact details, consents and visits. Personal data. | GET /v1/contactsGET /v1/contacts/{contactId} |
contacts:write | Create and update contacts, with their proof of consent. | POST /v1/contactsPATCH /v1/contacts/{contactId} |
visits:write | Record a customer's visit to a location. | POST /v1/visits |
replies:write | Submit a reply draft, to be reviewed in the app. | PUT /v1/reviews/{reviewId}/reply-draft |
replies:publish | Publish a reply on Google, for locations that allowed it. | POST /v1/reviews/{reviewId}/reply |
promo_codes:redeem | Redeem a promo code from a cash register. | POST /v1/promo-codes/redeem |
ai:generate | Request an AI-written reply draft, which uses credits. | POST /v1/reviews/{reviewId}/reply-drafts |
events:read | Read the account's event log. | GET /v1/eventsGET /v1/events/{eventId} |
webhooks:manage | Manage webhook endpoints. | GET /v1/webhook-endpointsPOST /v1/webhook-endpointsDELETE /v1/webhook-endpoints/{endpointId}POST /v1/webhook-endpoints/{endpointId}/test |
The contacts:read scope gives access to personal data: your customers' contact details, consents and history. Only grant it to tools that need it.
Two scopes require more than a ticked box:
contacts:write: when the key is created, the owner or admin certifies that the customers sent by the tool have given their consent. The writes guide details the consent proof.replies:publish: it only takes effect for locations that allowed publishing through the API in the app. See publishing on Google.
Plan and account state
- Pro plan: the API is included in the Pro plan, and during the free trial. An account without an effective Pro plan receives
403 plan_upgrade_required. Its keys are kept and work again, unchanged, as soon as the account is back on Pro. - Read-only account: with an effective Pro plan, a read-only account keeps answering reads and sending its webhooks. Writes receive
403 tenant_read_onlythere. Theaccount.readOnlyfield ofGET /v1/meshows this state.
The API checks, in this order: the key, the plan, the account state for a write, the scope, then the rate limit.
Isolation between accounts
The account always comes from the key: no path or parameter names it. An identifier that belongs to another account answers 404 not_found, exactly like an identifier that does not exist.
Checking a key
GET /v1/me answers for any valid key, whatever its other scopes. It is the call to use to test a connection from your tool: it returns the account, the effective plan, and the key's name, prefix, scopes and expiration date.
Good practices
- Create one key per integration, with a clear name: you will know which one to revoke.
- Grant only the scopes you need.
- Keep keys in a secrets manager or an environment variable, never in code.
- To replace a key without downtime, create the new one, deploy it, then revoke the old one.
Updated on October 25, 2026

