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.
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "Forbidden",
    "details": {
      "required": ["messages:bulk"],
      "missing": ["messages:bulk"]
    }
  }
}
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.
ScopeGroupAction
messages:sendmessagesSend a single message (text or template) to one recipient.
messages:bulkmessagesBulk-send a template to many recipients and read campaign status.
templates:readtemplatesRead the company’s approved template catalog.
templates:createtemplatesCreate WhatsApp templates and submit them to Meta.
templates:updatetemplatesEdit an existing template (components, category, language, status).
channels:readchannelsList channels (/v1/channels) and WhatsApp numbers (/v1/whatsapp/numbers).
channels:connectchannelsStart and poll WhatsApp Business connect sessions from the CLI or your backend.
webhooks:readwebhooksList outbound webhook subscriptions and read delivery history.
webhooks:managewebhooksCreate, update, rotate secret, delete subscriptions, and fire test events.
knowledge:readknowledgeRead the knowledge base tree.
knowledge:writeknowledgeCreate folders and documents (markdown → BlockNote).
knowledge:deleteknowledgeDelete nodes (folders and documents) from the knowledge base.
knowledge:queryknowledgeQuery the knowledge base with full-text, vector, or hybrid search.
knowledge:assignknowledgeAssign nodes of the knowledge base to an assistant’s workers.
assistants:readassistantsList and search active assistants in your company.
scheduling:branches:readschedulingList branches and get details.
scheduling:services:readschedulingList services and details (duration, restrictions, allowed professionals).
scheduling:professionals:readschedulingList professionals and details by branch or service.
scheduling:availability:readschedulingQuery availability by date, by range, and next available slots.
scheduling:appointments:readschedulingGet an appointment by id within the tenant.
scheduling:appointments:createschedulingCreate appointments with embedded customer data.
scheduling:appointments:confirmschedulingConfirm appointments (pendingconfirmed).
scheduling:appointments:cancelschedulingCancel appointments with an optional reason.
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.

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.

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.