> ## Documentation Index
> Fetch the complete documentation index at: https://docs.keebai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Scopes

> Scopes define exactly what a Personal Access Token can do. Catalog stored in MongoDB and validated endpoint-by-endpoint.

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 theme={null}
HTTP/1.1 403 Forbidden
Content-Type: application/json
```

```json theme={null}
{
  "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.

| Scope                             | Group      | Action                                                                                                                                                                                                                                                                                                                  |
| --------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `messages:send`                   | messages   | [Send a single message](/dev/endpoints/messages-send) of any type, on any connected channel.                                                                                                                                                                                                                            |
| `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).                                                                                                                                                                                                                                                     |
| `flows:read`                      | flows      | [List](/dev/endpoints/flows-list) and [read](/dev/endpoints/flows-get) [WhatsApp Flows](/dev/messaging/flows).                                                                                                                                                                                                          |
| `flows:write`                     | flows      | [Create](/dev/endpoints/flows-create), [update](/dev/endpoints/flows-update), [publish](/dev/endpoints/flows-publish) and [delete](/dev/endpoints/flows-delete) WhatsApp Flows.                                                                                                                                         |
| `contacts:read`                   | contacts   | [List](/dev/endpoints/contacts-list) and [read](/dev/endpoints/contacts-get) the messaging contacts of your company.                                                                                                                                                                                                    |
| `contacts:write`                  | contacts   | [Create](/dev/endpoints/contacts-create) and [update](/dev/endpoints/contacts-update) contacts, including custom fields.                                                                                                                                                                                                |
| `contacts:delete`                 | contacts   | [Delete contacts](/dev/endpoints/contacts-delete) and their change history. Permanent.                                                                                                                                                                                                                                  |
| `channels:read`                   | channels   | List channels (`/v1/channels`) and WhatsApp numbers (`/v1/whatsapp/numbers`).                                                                                                                                                                                                                                           |
| `channels:connect`                | channels   | Start and poll [WhatsApp Business connect sessions](/dev/endpoints/channels-whatsapp-connect) from the CLI or your backend.                                                                                                                                                                                             |
| `webhooks:read`                   | webhooks   | List [outbound webhook](/dev/webhooks/overview) 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](/dev/endpoints/knowledge-tree).                                                                                                                                                                                                                                                          |
| `knowledge:write`                 | knowledge  | Create [folders](/dev/endpoints/knowledge-folder-create) and [documents](/dev/endpoints/knowledge-document-create) (markdown → BlockNote).                                                                                                                                                                              |
| `knowledge:delete`                | knowledge  | [Delete nodes](/dev/endpoints/knowledge-node-delete) (folders and documents) from the knowledge base.                                                                                                                                                                                                                   |
| `knowledge:query`                 | knowledge  | Query the knowledge base with [full-text, vector, or hybrid search](/dev/endpoints/knowledge-search).                                                                                                                                                                                                                   |
| `knowledge:assign`                | knowledge  | [Assign nodes](/dev/endpoints/knowledge-assign) of the knowledge base to an assistant's workers.                                                                                                                                                                                                                        |
| `assistants:read`                 | assistants | [List assistants](/dev/endpoints/assistants-list), [read the blocks that make up their prompt](/dev/endpoints/assistants-blocks-list), [read block content](/dev/endpoints/blocks-content-get) and [version history](/dev/endpoints/blocks-versions-list), and [list webhook functions](/dev/endpoints/functions-list). |
| `assistants:write`                | assistants | [Create](/dev/endpoints/assistants-create) and [configure assistants](/dev/endpoints/assistants-update), [create](/dev/endpoints/blocks-create-personification) and [edit prompt blocks](/dev/endpoints/blocks-content-save), and [manage the webhook functions](/dev/endpoints/functions-create) they can call.        |
| `scheduling:branches:read`        | scheduling | [List branches](/dev/endpoints/scheduling-branches-list) and [get details](/dev/endpoints/scheduling-branch-get).                                                                                                                                                                                                       |
| `scheduling:services:read`        | scheduling | [List services](/dev/endpoints/scheduling-services-list) and [details](/dev/endpoints/scheduling-service-get) (duration, restrictions, allowed professionals).                                                                                                                                                          |
| `scheduling:professionals:read`   | scheduling | [List professionals](/dev/endpoints/scheduling-professionals-list) and [details](/dev/endpoints/scheduling-professional-get) by branch or service.                                                                                                                                                                      |
| `scheduling:availability:read`    | scheduling | Query availability [by date](/dev/endpoints/scheduling-availability), [by range](/dev/endpoints/scheduling-availability-range), and [next available slots](/dev/endpoints/scheduling-availability-next).                                                                                                                |
| `scheduling:appointments:read`    | scheduling | [Get an appointment](/dev/endpoints/scheduling-appointment-get) by id within the tenant.                                                                                                                                                                                                                                |
| `scheduling:appointments:create`  | scheduling | [Create appointments](/dev/endpoints/scheduling-appointment-create) with embedded customer data.                                                                                                                                                                                                                        |
| `scheduling:appointments:confirm` | scheduling | [Confirm appointments](/dev/endpoints/scheduling-appointment-confirm) (`pending` → `confirmed`).                                                                                                                                                                                                                        |
| `scheduling:appointments:cancel`  | scheduling | [Cancel appointments](/dev/endpoints/scheduling-appointment-cancel) with an optional reason.                                                                                                                                                                                                                            |
| `crm:customers:read`              | crm        | [List](/dev/endpoints/crm-customers-list) and [read](/dev/endpoints/crm-customer-get) CRM customers.                                                                                                                                                                                                                    |
| `crm:customers:write`             | crm        | [Create](/dev/endpoints/crm-customer-create) and [update](/dev/endpoints/crm-customer-update) customers, including custom fields and tags.                                                                                                                                                                              |
| `crm:customers:delete`            | crm        | [Delete customers](/dev/endpoints/crm-customer-delete). Permanent.                                                                                                                                                                                                                                                      |
| `crm:tickets:read`                | crm        | [List with filters](/dev/endpoints/crm-tickets-list) and [read](/dev/endpoints/crm-ticket-get) CRM tickets.                                                                                                                                                                                                             |
| `crm:tickets:write`               | crm        | [Create](/dev/endpoints/crm-ticket-create), [update](/dev/endpoints/crm-ticket-update), and [move between pipeline stages](/dev/endpoints/crm-ticket-stage).                                                                                                                                                            |
| `crm:tickets:delete`              | crm        | [Delete tickets](/dev/endpoints/crm-ticket-delete). Permanent.                                                                                                                                                                                                                                                          |
| `crm:tasks:read`                  | crm        | [List](/dev/endpoints/crm-tasks-list) and [read](/dev/endpoints/crm-task-get) CRM tasks.                                                                                                                                                                                                                                |
| `crm:tasks:write`                 | crm        | [Create](/dev/endpoints/crm-task-create) and [update](/dev/endpoints/crm-task-update) tasks (status, priority, assignee, due date).                                                                                                                                                                                     |
| `crm:tasks:delete`                | crm        | [Delete tasks](/dev/endpoints/crm-task-delete). Permanent.                                                                                                                                                                                                                                                              |
| `crm:notes:read`                  | crm        | [List](/dev/endpoints/crm-notes-list) and [read](/dev/endpoints/crm-note-get) CRM notes.                                                                                                                                                                                                                                |
| `crm:notes:write`                 | crm        | [Create](/dev/endpoints/crm-note-create) and [update](/dev/endpoints/crm-note-update) notes. The author is the token's owner.                                                                                                                                                                                           |
| `crm:notes:delete`                | crm        | [Delete notes](/dev/endpoints/crm-note-delete). Permanent.                                                                                                                                                                                                                                                              |
| `ecommerce:products:read`         | ecommerce  | [List](/dev/endpoints/ecommerce-products-list) and [read](/dev/endpoints/ecommerce-product-get) the product catalog.                                                                                                                                                                                                    |
| `ecommerce:carts:read`            | ecommerce  | [List](/dev/endpoints/ecommerce-carts-list) and [read](/dev/endpoints/ecommerce-cart-get) carts, including abandoned ones.                                                                                                                                                                                              |
| `ecommerce:sales:read`            | ecommerce  | [List](/dev/endpoints/ecommerce-sales-list) and [read](/dev/endpoints/ecommerce-sale-get) sales, with amounts and payment state.                                                                                                                                                                                        |
| `loyalty:read`                    | loyalty    | [Read programs](/dev/endpoints/loyalty-programs-list), [templates](/dev/endpoints/loyalty-templates-list), [memberships](/dev/endpoints/loyalty-memberships-list), balances and [ledger movements](/dev/endpoints/loyalty-ledger-list).                                                                                 |
| `loyalty:write`                   | loyalty    | [Enroll customers](/dev/endpoints/loyalty-membership-enroll), [move points and stamps](/dev/endpoints/loyalty-ledger-record), [issue wallet passes](/dev/endpoints/loyalty-pass-google) and [notify the customer's card](/dev/endpoints/loyalty-pass-notify).                                                           |
| `projects:read`                   | projects   | [List the projects](/dev/endpoints/me) of your company the token can reach.                                                                                                                                                                                                                                             |

<Tip>
  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.
</Tip>

## The MCP server uses the same scopes

The [MCP server](/dev/mcp/overview) 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](/dev/mcp/tools) 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.

<Warning>
  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.
</Warning>

## 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.

<CardGroup cols={2}>
  <Card title="Transactional backend (1:1 notifications)">
    Only needs to send single messages.

    `messages:send`.
  </Card>

  <Card title="Marketing tool / outbound CRM">
    Needs to launch campaigns and check status.

    `messages:bulk`, `templates:read`.
  </Card>

  <Card title="Template viewer">
    Read-only browser of the approved catalog.

    `templates:read`.
  </Card>

  <Card title="Template provisioning">
    Creates and maintains the company's templates without using the portal.

    `templates:read`, `templates:create`, `templates:update`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="CLI-driven provisioning">
    Automated onboarding: connects channels, registers webhooks, verifies.

    `channels:read`, `channels:connect`, `webhooks:read`, `webhooks:manage`.
  </Card>

  <Card title="Webhook-based integration">
    Your backend receives realtime events and inspects delivery history.

    `webhooks:read`, `webhooks:manage`, `channels:read`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="External RAG / search">
    An external app queries your knowledge base as retrieval for its own LLM.

    `knowledge:read`, `knowledge:query`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="Storefront pricing widget">
    Your website shows live prices and stock. It never touches customer data.

    `ecommerce:products:read`.
  </Card>

  <Card title="Abandoned-cart recovery">
    Finds pending carts and messages the customer with the recovery link.

    `ecommerce:carts:read`, `contacts:read`, `messages:send`.
  </Card>

  <Card title="Sales reporting">
    A BI job pulls closed sales nightly. Read-only, no catalog, no carts.

    `ecommerce:sales:read`.
  </Card>

  <Card title="Loyalty terminal">
    Your point of sale enrolls customers, accrues on purchase, and hands out the wallet card.

    `loyalty:read`, `loyalty:write`.
  </Card>

  <Card title="Loyalty balance display">
    A kiosk or a customer-facing screen shows the balance and nothing more. Cannot move points or push notifications.

    `loyalty:read`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="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`.
  </Card>

  <Card title="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`.
  </Card>
</CardGroup>

<Warning>
  **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](/dev/crm/overview#tenancy-is-implicit) before handing a CRM token to a third party.
</Warning>

## Change a token's scopes

You can't edit scopes on an existing token. The pattern is:

<Steps>
  <Step title="Mint a new token with the right scopes">
    From [API Keys](https://app.keebai.com/system-settings/api-keys), click **Create API Key** and pick the new scopes.
  </Step>

  <Step title="Update your integration">
    Swap the old token for the new one in your secret manager.
  </Step>

  <Step title="Revoke the old">
    Once the integration is happily on the new token, revoke the old one.
  </Step>
</Steps>

This pattern gives you zero-downtime rotation.
