How they’re validated
On every request, the auth guard loads the token and puts its scopes on the request context. Each endpoint declares the scope it needs with@RequireScopes('messages:send'). If the scope is missing, the response is 403 Forbidden with code: INSUFFICIENT_SCOPE.
Catalog
The catalog lives in theapi_scopes MongoDB collection. The portal pulls it via GET /api/v1/api-scopes and builds the create-token modal dynamically, so adding a new scope doesn’t require a frontend deploy.
The MCP server uses the same scopes
The MCP server does not have a scope system of its own. Each of its 101 tools requires exactly the scope its REST counterpart does —keebai_crm_ticket_create needs crm:tickets:write, keebai_contacts_list needs contacts:read, and so on. The tool catalogue lists the mapping.
One difference matters when you hand a token to an agent: a missing scope is not a 403. Every tool stays visible in tools/list regardless of your scopes, and the call comes back as a tool error carrying INSUFFICIENT_SCOPE. An agent will happily try something it cannot do and discover the limit afterwards, so pick the scope set deliberately rather than relying on the agent not to reach for a tool.
Scopes are independent from role permissions
Scopes are independent from the role permissions of the user who creates the token. The backend validates what scopes you’re allowed to assign at creation time (each scope must exist and be active inapi_scopes), but once minted, the token uses its assigned scopes regardless of later changes to your role.
That means:
- To create a token you need
developer.manage_tokenson your role. Without it you don’t even see the API Keys screen. - Once created, a token’s scopes are fixed. If your role is later trimmed, the token keeps working with its original scopes. To revoke access, revoke the key explicitly.
- To use new scopes, mint a new token. You can’t add scopes to an existing key.
Least privilege by example
Pick the smallest scope set that does the job. Splittingmessages:send and messages:bulk exists exactly for this — bulk is higher-risk (Meta cost, sender reputation, abuse potential), so isolate it in a key the marketing tool owns, not the transactional backend.
Transactional backend (1:1 notifications)
Only needs to send single messages.
messages:send.Marketing tool / outbound CRM
Needs to launch campaigns and check status.
messages:bulk, templates:read.Template viewer
Read-only browser of the approved catalog.
templates:read.Template provisioning
Creates and maintains the company’s templates without using the portal.
templates:read, templates:create, templates:update.Full-stack integration (internal)
The whole combo, when it’s under your team’s direct control.
messages:send, messages:bulk, templates:read, templates:create, templates:update.CLI-driven provisioning
Automated onboarding: connects channels, registers webhooks, verifies.
channels:read, channels:connect, webhooks:read, webhooks:manage.Webhook-based integration
Your backend receives realtime events and inspects delivery history.
webhooks:read, webhooks:manage, channels:read.Knowledge-base sync
Your CMS or docs pipeline publishes documents and assigns them to assistants automatically.
knowledge:read, knowledge:write, knowledge:delete, knowledge:assign, assistants:read.External RAG / search
An external app queries your knowledge base as retrieval for its own LLM.
knowledge:read, knowledge:query.Scheduling — read-only catalog and availability
Your public website or client app shows branches, services, professionals, and available times — no booking.
scheduling:branches:read, scheduling:services:read, scheduling:professionals:read, scheduling:availability:read.Scheduling — full booking flow
Your integration creates, confirms, and cancels appointments end-to-end.
scheduling:branches:read, scheduling:services:read, scheduling:professionals:read, scheduling:availability:read, scheduling:appointments:read, scheduling:appointments:create, scheduling:appointments:confirm, scheduling:appointments:cancel.CRM — reporting and dashboards
A BI tool or dashboard reads the pipeline without ever writing to it.
crm:customers:read, crm:tickets:read, crm:tasks:read, crm:notes:read.CRM — two-way sync, no deletes
Your external CRM or ERP keeps records in step with Keebai. Deletes stay out so a sync bug cannot erase history.
crm:customers:read, crm:customers:write, crm:tickets:read, crm:tickets:write, crm:tasks:read, crm:tasks:write, crm:notes:read, crm:notes:write.CRM — activity logger
A dialer or email tool writes call and email records onto the right ticket, and nothing else.
crm:tickets:read, crm:notes:write.Storefront pricing widget
Your website shows live prices and stock. It never touches customer data.
ecommerce:products:read.Abandoned-cart recovery
Finds pending carts and messages the customer with the recovery link.
ecommerce:carts:read, contacts:read, messages:send.Sales reporting
A BI job pulls closed sales nightly. Read-only, no catalog, no carts.
ecommerce:sales:read.Loyalty terminal
Your point of sale enrolls customers, accrues on purchase, and hands out the wallet card.
loyalty:read, loyalty:write.Loyalty balance display
A kiosk or a customer-facing screen shows the balance and nothing more. Cannot move points or push notifications.
loyalty:read.Assistant provisioning
Your onboarding flow creates an assistant per client and writes its prompt blocks from a template you keep in git.
assistants:read, assistants:write.Prompt auditor
A reviewer reads every assistant’s blocks and their history to check what the bots are told to say. Cannot change a word, and webhook secrets stay masked.
assistants:read.Contact sync
Your CRM or ERP keeps the contact directory in step with Keebai. Deletes stay out so a sync bug cannot erase people.
contacts:read, contacts:write.AI agent over MCP
An agent that answers with your knowledge base, replies on WhatsApp, and logs what it did — without being able to destroy anything.
knowledge:query, contacts:read, messages:send, crm:tickets:read, crm:tickets:write, crm:notes:write.Change a token’s scopes
You can’t edit scopes on an existing token. The pattern is:1
Mint a new token with the right scopes
From API Keys, click Create API Key and pick the new scopes.
2
Update your integration
Swap the old token for the new one in your secret manager.
3
Revoke the old
Once the integration is happily on the new token, revoke the old one.