Skip to main content
Every Personal Access Token (PAT) carries a set of scopes — the list of actions that token can perform against the public API. You pick scopes at creation time, and they’re immutable afterward — to change them, mint a new token and revoke the old one.

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.
Unlike auth errors (which are intentionally generic), authorization errors spell out which scope is missing — because you already authenticated successfully; you just lack permission.

Catalog

The catalog lives in the api_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 checkboxes in the Create API Key modal load live from the backend. A missing scope means it’s flagged is_active: false in the database.

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 in api_scopes), but once minted, the token uses its assigned scopes regardless of later changes to your role. That means:
  1. To create a token you need developer.manage_tokens on your role. Without it you don’t even see the API Keys screen.
  2. 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.
  3. To use new scopes, mint a new token. You can’t add scopes to an existing key.
Because scopes survive role changes, audit the API Keys table periodically and revoke tokens belonging to people who shouldn’t have access anymore. The Last used column helps find forgotten keys.

Least privilege by example

Pick the smallest scope set that does the job. Splitting messages: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.
CRM reads are company-wide. A crm:*:read scope returns records from every project in your company, not just the project the token was minted for. Writes stay scoped to the token’s project. See the CRM overview before handing a CRM token to a third party.

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.
This pattern gives you zero-downtime rotation.