# Team roles and permissions

> See what each built-in role (Owner, Admin, Editor, Analyst, Viewer, Billing) can do, how custom roles work on Business, and how API tokens narrow access.

Access is built from **permissions**. A role is a set of permissions, and
every [API operation](/docs/api) and MCP tool declares the one permission
it needs.

## Permission matrix

This table is generated from the code that enforces it.

| Permission | Allows | Owner | Admin | Editor | Analyst | Viewer | Billing |
|---|---|---|---|---|---|---|---|
| `analytics.read` | View dashboards, stats, live data and reports | ✓ | ✓ | ✓ | ✓ | ✓ | - |
| `analytics.export` | Create exports and download data | ✓ | ✓ | ✓ | ✓ | - | - |
| `content.write` | Manage goals, funnels, segments, notes, alerts, email reports, links and dashboards | ✓ | ✓ | ✓ | ✓ | - | - |
| `sites.manage` | Create sites and change site settings, tracking, privacy, traffic rules, integrations and sharing | ✓ | ✓ | ✓ | - | - | - |
| `uptime.manage` | Manage uptime checks and status pages | ✓ | ✓ | ✓ | - | - | - |
| `members.manage` | Invite members and change roles and site access | ✓ | ✓ | - | - | - | - |
| `tokens.manage` | Create and revoke API tokens for anyone in the workspace (members can always manage their own) | ✓ | ✓ | - | - | - | - |
| `billing.manage` | Change plan, payment details and view invoices | ✓ | ✓ | - | - | - | ✓ |
| `workspace.manage` | Workspace settings, security, SSO, webhooks, white label, audit log and deletion | ✓ | ✓ | - | - | - | - |

A member with no access to a site can't see it anywhere, including in
lists, exports and the API.

## Built-in roles

- **Owner:** every permission. Each workspace has exactly one owner. Only
  the owner can transfer ownership, and the owner can't be removed or
  given another role. The owner can always log in with a password or a
  passkey, whatever the workspace's login rules say.
- **Admin:** every permission, the same as the owner.
- **Editor:** analytics, exports, content (goals, funnels, segments, notes,
  alerts, email reports, links and dashboards), sites and site settings,
  uptime checks and status pages. No members, billing, tokens for others
  or workspace settings.
- **Analyst:** analytics, exports and content. No site settings or uptime.
- **Viewer:** read-only analytics.
- **Billing:** plan, payment details and invoices only. No analytics.

Every built-in role is available on every plan. A member has one role,
plus access to all sites or to selected sites. The role decides what they
can do, and the site access decides where.

Nobody can hand out more than they hold: you can only give a role when you hold every
permission in it, and you can only change or remove a
member whose permissions and sites are within your own.

## Custom roles

On Business, **Workspace settings → Roles** shows what each role can do
and lets members with `members.manage` create custom roles. Choose **New
role**, then:

| Field | What it does |
|---|---|
| **Name** (`name`) | Shown wherever roles are listed. Up to 60 characters, unique in the workspace. |
| **Permissions** (`permissions`) | Any combination of the nine permissions in the matrix above. You can only tick permissions you hold yourself. |

Assign a custom role like a built-in one, when inviting or editing a
member. Editing a custom role changes what every member who holds it can
do. A role that members still hold can't be deleted. Deleting a role also
deletes pending invitations that use it.

Over the API, roles are at `/workspaces/<workspace id>/roles` and the MCP
tools are `roles_list`, `roles_create`, `roles_update` and `roles_delete`.
To give a member a custom role, send `role` as `custom` with the role's id
in `custom_role_id`.

## API tokens narrow, never widen

An [API token](/docs/api/authentication) belongs to a member. Its effective
access is:

- **permissions** = the member's role ∩ the permissions chosen for the
  token,
- **sites** = the member's sites ∩ the sites chosen for the token.

If the member's role or site access shrinks, their tokens shrink with it.
Members can always manage their own tokens, and `tokens.manage` lets admins
manage everyone's.
