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.
| Scope | Group | Action |
|---|---|---|
messages:send | messages | Send a single message (text or template) to one recipient. |
messages:bulk | messages | Bulk-send a template to many recipients and read campaign status. |
templates:read | templates | Read the company’s approved template catalog. |
templates:create | templates | Create WhatsApp templates and submit them to Meta. |
templates:update | templates | Edit an existing template (components, category, language, status). |
channels:read | channels | List channels (/v1/channels) and WhatsApp numbers (/v1/whatsapp/numbers). |
channels:connect | channels | Start and poll WhatsApp Business connect sessions from the CLI or your backend. |
webhooks:read | webhooks | List outbound webhook subscriptions and read delivery history. |
webhooks:manage | webhooks | Create, update, rotate secret, delete subscriptions, and fire test events. |
knowledge:read | knowledge | Read the knowledge base tree. |
knowledge:write | knowledge | Create folders and documents (markdown → BlockNote). |
knowledge:delete | knowledge | Delete nodes (folders and documents) from the knowledge base. |
knowledge:query | knowledge | Query the knowledge base with full-text, vector, or hybrid search. |
knowledge:assign | knowledge | Assign nodes of the knowledge base to an assistant’s workers. |
assistants:read | assistants | List and search active assistants in your company. |
scheduling:branches:read | scheduling | List branches and get details. |
scheduling:services:read | scheduling | List services and details (duration, restrictions, allowed professionals). |
scheduling:professionals:read | scheduling | List professionals and details by branch or service. |
scheduling:availability:read | scheduling | Query availability by date, by range, and next available slots. |
scheduling:appointments:read | scheduling | Get an appointment by id within the tenant. |
scheduling:appointments:create | scheduling | Create appointments with embedded customer data. |
scheduling:appointments:confirm | scheduling | Confirm appointments (pending → confirmed). |
scheduling:appointments:cancel | scheduling | Cancel appointments with an optional reason. |
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.Change a token’s scopes
You can’t edit scopes on an existing token. The pattern is:Mint a new token with the right scopes
From API Keys, click Create API Key and pick the new scopes.