Permissions and scopes
The permission catalogue, what the built-in roles hold, how visibility and field masking layer on top, and which scopes apps may request.
Last updated
Three layers
- Permissions gate endpoints. API keys and app tokens carry a list; people get theirs from a role.
- Visibility per resource:
all,team,inbox,assigned,unassigned, with a verb. Lists, search and single reads are filtered in SQL by the same predicate. Keys and apps seeall. - Fields tagged PII (email, phone, address, identity document), payment, internal note, agent identity, IP address are
visible,maskedorhiddenper role, on built-in fields, custom attributes and files marked with them. Keys and apps see everything their permissions reach, which is why only someone who sees everything in clear may create one that reads conversations or contacts.
Catalogue
| Permission | Admin | Supervisor | Agent | Restricted | Viewer |
|---|---|---|---|---|---|
conversations:read | ✓ | ✓ | ✓ | ✓ | ✓ |
conversations:reply | ✓ | ✓ | ✓ | ✓ | · |
conversations:assign | ✓ | ✓ | ✓ | · | · |
conversations:manage | ✓ | ✓ | ✓ | · | · |
conversations:delete | ✓ | ✓ | · | · | · |
messages:write_private | ✓ | ✓ | ✓ | ✓ | · |
contacts:read | ✓ | ✓ | ✓ | ✓ | ✓ |
contacts:write | ✓ | ✓ | ✓ | · | · |
contacts:merge, contacts:export, contacts:delete, contacts:import | ✓ | ✓ | · | · | · |
inboxes:manage, teams:manage, tags:manage, custom_attributes:manage, canned_responses:manage, automations:manage, webhooks:manage, bots:manage, views:manage, branding:manage, audit:read, sensitive:reveal, ai:manage, activity:read, flows:manage, knowledge:manage, connectors:manage, integrations:read | ✓ | ✓ | · | · | · |
ai:use | ✓ | ✓ | ✓ | · | · |
knowledge:read | ✓ | ✓ | ✓ | ✓ | ✓ |
reports:read | ✓ | ✓ | · | · | ✓ |
reports:share | ✓ | ✓ | · | · | · |
agents:manage, roles:manage, settings:manage, api_keys:manage, plugins:manage, apps:manage, audit:exempt_views, integrations:manage, conversations:export, imports:manage, security:keys | ✓ | · | · | · | · |
Generated from the code as docs/authz-matrix.md in the repository; a test fails when it is stale. New permissions added by an upgrade are granted to the built-in roles automatically. In the app, the Roles page shows each permission by a readable name with a one-line hint, in the person's language, with the key in the tooltip.
A few that are easy to miss: sensitive:reveal lets a role that sees a field masked read one value in clear through POST /sensitive/reveal (audited, see security); ai:manage covers Settings, AI and its usage, and ai:use the AI assist in conversations (AI assist); single sign-on providers are managed with settings:manage; contacts:import runs CSV imports (with contacts:write) and conversations:export exports a whole view (exports); imports:manage covers the Chatwoot import history and wizard under Settings › Import (Administrator only; a workspace that wants its administrators out of imports makes a custom role without it); security:keys creates, unlocks and locks the workspace's tenant-held key (experimental, a signed-in person only; security); reports:share shares a saved Reports view with the workspace (saved views); integrations:manage and integrations:read cover the Marketplace, and plugins:manage alone opens Installed for the core modules' settings; the Assignment tab of Automation shows to teams:manage, inboxes:manage or agents:manage; custom attributes and files tagged as personal data follow each role's field grants (roles and personal data); a send_webhook step in a rule or macro needs webhooks:manage as well as automations:manage to save, while applying such a macro needs only what applying the macro needs.
Field grants of the built-in roles
| Tag | Admin | Supervisor | Agent | Restricted | Viewer |
|---|---|---|---|---|---|
pii.email, pii.phone | visible | visible | visible | masked | masked |
pii.address | visible | visible | visible | hidden | hidden |
pii.identity_doc, payment | visible | visible | masked | hidden | hidden |
internal_note | visible | visible | visible | visible | hidden |
agent_identity, ip_address | visible | visible | visible | visible | visible |
Row visibility of the built-in roles: Administrator and Supervisor see every conversation and contact and may manage them; Agent sees their inboxes' and may reply; Restricted agent sees the conversations assigned to them (reply) and those contacts (read); Viewer sees their teams' (read). The personal-data tags also apply to custom attributes and files marked with them; Settings › Access shows the result per person.
Nobody can grant more than they hold
Creating or changing a custom role, changing a member's role, removing a member, inviting someone, creating an API key, approving an app's scopes and managing single sign-on providers all follow one rule: the caller can only grant what they hold themselves, and roles or members that hold more are out of their reach. The rule covers all three layers:
- permissions: a subset of the caller's;
- visibility:
allcoversinbox, which coversunassigned, and every scope coversassigned(teamandinboxare not comparable); verbs are orderedread<reply<manage; - fields:
hidden<masked<visible.
A request that goes beyond the caller answers 403 naming each missing item, and the agent app disables those controls. The Administrator role can never lose a permission.
Scopes for apps and keys
Any permission above may be requested by an app manifest or chosen for a key. A key cannot hold what its creator lacks; an app only holds what an administrator approved. For most integrations: conversations:read and contacts:read to observe, conversations:reply to answer, conversations:manage to route, webhooks:manage to self-register hooks.
Every claim on these pages is covered by a test in the repository, and the API reference is generated from the same contract every server serves at /api/openapi. Corrections to [email protected].