# Permissions

> Every permission, which roles hold it, and how API key scopes use the same list.

Every operation, over the API or MCP, checks a `resource:action` permission. A signed-in person gets permissions from
their role; an API key from the scopes it was minted with (none means the workspace's full authority); an OAuth
client from the person's role, cut down to what they approved.

A `403` names the permission that was missing. `GET /api/v1/api-keys/permissions` serves this list at runtime.

Roles nest: an owner holds everything an admin does, an admin everything a manager does, and a manager everything a
member does.

| Permission               | Owner | Admin | Manager | Member |
| ------------------------ | ----- | ----- | ------- | ------ |
| `organization:read`      | ✓     | ✓     | ✓       | ✓      |
| `organization:update`    | ✓     | ✓     |         |        |
| `organization:delete`    | ✓     |       |         |        |
| `member:read`            | ✓     | ✓     | ✓       | ✓      |
| `member:create`          | ✓     | ✓     |         |        |
| `member:update`          | ✓     | ✓     |         |        |
| `member:delete`          | ✓     | ✓     |         |        |
| `invitation:read`        | ✓     | ✓     |         |        |
| `invitation:create`      | ✓     | ✓     |         |        |
| `invitation:cancel`      | ✓     | ✓     |         |        |
| `team:create`            | ✓     | ✓     |         |        |
| `team:update`            | ✓     | ✓     |         |        |
| `team:delete`            | ✓     | ✓     |         |        |
| `ac:create`              | ✓     | ✓     |         |        |
| `ac:read`                | ✓     | ✓     | ✓       | ✓      |
| `ac:update`              | ✓     | ✓     |         |        |
| `ac:delete`              | ✓     | ✓     |         |        |
| `post:read`              | ✓     | ✓     | ✓       | ✓      |
| `post:create`            | ✓     | ✓     | ✓       | ✓      |
| `post:update`            | ✓     | ✓     | ✓       | ✓      |
| `post:delete`            | ✓     | ✓     | ✓       | ✓      |
| `post:publish`           | ✓     | ✓     | ✓       |        |
| `tag:read`               | ✓     | ✓     | ✓       | ✓      |
| `tag:create`             | ✓     | ✓     | ✓       |        |
| `tag:update`             | ✓     | ✓     | ✓       |        |
| `tag:delete`             | ✓     | ✓     | ✓       |        |
| `hashtagSet:read`        | ✓     | ✓     | ✓       | ✓      |
| `hashtagSet:create`      | ✓     | ✓     | ✓       | ✓      |
| `hashtagSet:update`      | ✓     | ✓     | ✓       | ✓      |
| `hashtagSet:delete`      | ✓     | ✓     | ✓       | ✓      |
| `campaign:read`          | ✓     | ✓     | ✓       | ✓      |
| `campaign:create`        | ✓     | ✓     | ✓       | ✓      |
| `campaign:update`        | ✓     | ✓     | ✓       | ✓      |
| `campaign:delete`        | ✓     | ✓     | ✓       | ✓      |
| `account:read`           | ✓     | ✓     | ✓       | ✓      |
| `account:connect`        | ✓     | ✓     | ✓       |        |
| `account:disconnect`     | ✓     | ✓     | ✓       |        |
| `account:update`         | ✓     | ✓     | ✓       |        |
| `media:read`             | ✓     | ✓     | ✓       | ✓      |
| `media:create`           | ✓     | ✓     | ✓       | ✓      |
| `media:delete`           | ✓     | ✓     | ✓       | ✓      |
| `comment:read`           | ✓     | ✓     | ✓       | ✓      |
| `comment:create`         | ✓     | ✓     | ✓       | ✓      |
| `comment:update`         | ✓     | ✓     | ✓       | ✓      |
| `comment:delete`         | ✓     | ✓     | ✓       | ✓      |
| `comment:manageAny`      | ✓     | ✓     | ✓       |        |
| `approval:read`          | ✓     | ✓     | ✓       | ✓      |
| `approval:request`       | ✓     | ✓     | ✓       | ✓      |
| `approval:decide`        | ✓     | ✓     | ✓       |        |
| `inbox:read`             | ✓     | ✓     | ✓       | ✓      |
| `inbox:reply`            | ✓     | ✓     | ✓       | ✓      |
| `inbox:update`           | ✓     | ✓     | ✓       | ✓      |
| `teamInbox:read`         | ✓     | ✓     | ✓       | ✓      |
| `teamInbox:create`       | ✓     | ✓     | ✓       |        |
| `teamInbox:update`       | ✓     | ✓     | ✓       |        |
| `teamInbox:delete`       | ✓     | ✓     | ✓       |        |
| `inboxStatus:read`       | ✓     | ✓     | ✓       | ✓      |
| `inboxStatus:update`     | ✓     | ✓     | ✓       | ✓      |
| `inboxStatus:manageAny`  | ✓     | ✓     | ✓       |        |
| `analytics:read`         | ✓     | ✓     | ✓       | ✓      |
| `analytics:readAny`      | ✓     | ✓     | ✓       |        |
| `apiKey:read`            | ✓     | ✓     | ✓       | ✓      |
| `apiKey:create`          | ✓     | ✓     |         |        |
| `apiKey:delete`          | ✓     | ✓     |         |        |
| `webhook:read`           | ✓     | ✓     | ✓       | ✓      |
| `webhook:create`         | ✓     | ✓     |         |        |
| `webhook:update`         | ✓     | ✓     |         |        |
| `webhook:delete`         | ✓     | ✓     |         |        |
| `billing:read`           | ✓     | ✓     | ✓       | ✓      |
| `billing:manage`         | ✓     | ✓     |         |        |
| `integration:read`       | ✓     | ✓     | ✓       | ✓      |
| `integration:connect`    | ✓     | ✓     | ✓       |        |
| `integration:disconnect` | ✓     | ✓     | ✓       |        |
| `integration:update`     | ✓     | ✓     | ✓       |        |
| `auditLog:read`          | ✓     | ✓     |         |        |
| `brandVoice:read`        | ✓     | ✓     | ✓       | ✓      |
| `brandVoice:seed`        | ✓     | ✓     | ✓       | ✓      |
| `brandVoice:update`      | ✓     | ✓     | ✓       |        |
| `linkTracking:read`      | ✓     | ✓     | ✓       | ✓      |
| `linkTracking:update`    | ✓     | ✓     | ✓       |        |
| `postingSchedule:read`   | ✓     | ✓     | ✓       | ✓      |
| `postingSchedule:update` | ✓     | ✓     | ✓       |        |
| `publicProfile:read`     | ✓     | ✓     | ✓       | ✓      |
| `publicProfile:update`   | ✓     | ✓     | ✓       |        |
| `calendarFeed:read`      | ✓     | ✓     | ✓       | ✓      |
| `calendarFeed:create`    | ✓     | ✓     | ✓       | ✓      |
| `calendarFeed:update`    | ✓     | ✓     | ✓       | ✓      |
| `calendarFeed:delete`    | ✓     | ✓     | ✓       | ✓      |
| `calendarFeed:manageAny` | ✓     | ✓     |         |        |
| `ai:use`                 | ✓     | ✓     | ✓       | ✓      |
| `autoDm:read`            | ✓     | ✓     | ✓       | ✓      |
| `autoDm:create`          | ✓     | ✓     | ✓       | ✓      |
| `autoDm:update`          | ✓     | ✓     | ✓       |        |
| `autoDm:delete`          | ✓     | ✓     | ✓       |        |

On plans without approval workflows (Standard and Pro), members also hold `post:publish`, since there's nobody set up
to review their posts.
