# Permission reference

Every permission the API recognizes, grouped by what it governs. Nearly every operation in
the [reference](/reference) names the permission it requires; this page works in the other
direction, from a permission to what it opens.

## How to read a row

- **Permission.** The string a role grants and a key is scoped to. It reads
  `<resource>:<verb>`, where the resource is the noun the API serves it under. `view` covers
  reading one record and listing many, and `delete` is the only destructive verb.
- **Lets someone.** What holding it opens, in the app and over the API alike.

Some permissions need a **module** on the workspace's plan as well as the role. Where that
applies, the note under the table says so; a table with no such note needs only the role.

A module is enforced in one of two ways, and the refusal code tells you which. An operation
that names a module answers `license_required`. Elsewhere the permission itself is dropped
from the session before the request is made, so the answer is `forbidden`: the role grants
it, and the session does not hold it. Where a module covers part of a resource rather than
all of it (building an agent rather than using one), the note under that table says which
part.

A few operations require no permission at all: a shared catalog, the list a chat user picks
an agent or a saved prompt from, and anything scoped to the caller's own session. They name
no permission in the reference, and nothing on this page opens or closes them.

See [roles and permissions](/roles-and-permissions) for the grammar, and for how roles,
plans and key scope combine into what a request may do.

## Conversations

| Permission | Lets someone |
|---|---|
| `thread:view` | Open a conversation and list them. |
| `thread:create` | Start one. |
| `thread:edit` | Rename one, change who it is shared with, or remove an attachment. |
| `thread:delete` | Delete one. |
| `thread:upload` | Attach a file to a conversation. |
| `message:view` | Read a conversation's messages. |
| `message:create` | Send a message, which is what runs the model. |
| `space:view` | Open a space and list them. |
| `space:create` | Create a space. |
| `space:edit` | Edit a space. |
| `space:delete` | Delete a space. |

`message:create` is the permission that spends credits. Attachments need no permission of
their own to read: whoever can open the conversation can open what was sent to it.

## Agents and prompts

| Permission | Lets someone |
|---|---|
| `agent:view` | Open an agent's configuration and its change history. |
| `agent:create` | Create an agent. |
| `agent:edit` | Change an agent's instructions, model, and tools. |
| `agent:delete` | Delete an agent. |
| `agent:knowledge:edit` | Choose which knowledge bases an agent reads. |
| `assist:run` | Use AI assistance inside an editor: rewrite the text in a field, redraft a document, generate captions, pick photos. |
| `prompt:view` | Open a saved prompt or tool, and its history. |
| `prompt:create` | Create one. |
| `prompt:edit` | Edit one, and file it under a category. |
| `prompt:delete` | Delete one. |
| `prompt:category:edit` | Manage the categories saved prompts are filed under. |
| `wildcard:create` | Create the wildcards prompts are assembled from. |
| `wildcard:edit` | Edit them. |
| `wildcard:delete` | Delete them. |

`agent:edit` amounts to "may change what the AI says on the organization's behalf": it
governs the system prompt, the model, and the tools an agent can call. Running an agent in
a conversation is not a separate permission. That is chatting, gated by `thread:*` with
`message:create`.

`assist:run` is a single permission rather than one per surface because the helpers have
no surface of their own; the rewrite button appears on text fields throughout the product.
It is separable from the edit permissions alongside it because it spends credits, so a
workspace can let someone edit designs without letting them spend.

The module splits along the same line as the permissions: **building** agents and prompts
needs `module-agent-editor`, using them does not. `agent:view` and `prompt:view` are on
every plan, and listing the agents, prompts and wildcards a workspace has needs no
permission at all, because that list is what the chat picker reads.

## Knowledge bases

| Permission | Lets someone |
|---|---|
| `knowledge-base:view` | Open a knowledge base, list them, and read the documents inside. |
| `knowledge-base:create` | Create one. |
| `knowledge-base:edit` | Change its schema and settings. |
| `knowledge-base:delete` | Delete one, or a document in it. |
| `knowledge-base:upload` | Add a document to one. |
| `knowledge-base:write` | Change a document's contents, restore an earlier version, or rebuild what was indexed from it. |
| `knowledge-base:import` | Bulk-import records. |
| `knowledge-base:export` | Bulk-export records. |
| `knowledge-base:crawl` | Fill a knowledge base from a website. |
| `knowledge-base:record:view` | Read the records inside a knowledge base. |
| `knowledge-base:record:create` | Add a record. |
| `knowledge-base:record:edit` | Edit a record. |
| `knowledge-base:record:delete` | Delete a record. |

The split is deliberate: `knowledge-base:edit` governs the base's own structure,
`knowledge-base:write` governs what its documents say, and `knowledge-base:record:*`
governs the structured data inside it. A contributor gets the last two without the first.

The module falls on the same line. `module-ds-editor` is the knowledge-base **builder**, so
only `knowledge-base:create` and `knowledge-base:edit` require it. Reading a base, filling
it, and changing what its documents and records say are on every plan.

## Objects

| Permission | Lets someone |
|---|---|
| `object:view` | Open a record and list them, read its relations, and browse the classification schemes. |
| `object:create` | Create a record, or send one by business key so an upstream system can create and update in one call. |
| `object:edit` | Change a record's attributes, link it to other records, files and classification nodes, and move it through its lifecycle. |
| `object:delete` | Delete a record. |
| `object:taxonomy:edit` | Manage the classification schemes and their nodes. |
| `object:schema:edit` | Define the types of record the workspace keeps, their attributes, and the lifecycle flow they move through. |

All six need `module-objects`, and every operation names it, so a workspace without the
module answers `license_required` rather than `forbidden`.

## Media library

| Permission | Lets someone |
|---|---|
| `media:view` | Browse the library, its previews, and its metadata. |
| `media:upload` | Add a file to the library. |
| `media:download` | Get the original file, and start bulk download jobs. |
| `media:edit` | Edit media records (tags, attribution, analysis results) and manage versions. |
| `media:delete` | Delete media from the library. |
| `media:analyze` | Run AI analysis over a file, and try analysis schemas. |
| `media:publish` | Release a file to its permanent public URL, and withdraw it again. |
| `media:tag:create` | Add a tag to a tag group that already exists, while filing a file. |
| `media:face:view` | See the people recognized in photographs. |
| `media:face:edit` | Name a person, merge two people, confirm or reject a suggestion. |
| `media:face:search` | Find every photo a person appears in. |
| `stock-photo:view` | Search the stock photography library. |
| `stock-photo:import` | Copy a stock photo into the workspace. |

`media:download` is the only download permission in the catalog. Everywhere else, reading
a resource includes its content. A library is different: browsing previews and taking
full-resolution originals with their embedded metadata are separate decisions, so
`media:view` covers the first and `media:download` the second.

Configuring the library (the tag structure itself, the status flow, and duplicate
resolution) is workspace administration and sits under `admin:` below. `media:tag:create`
is the exception: adding a value to a group that already exists happens while filing a
file, so it belongs to the person doing the filing rather than to an administrator.

`media:analyze` runs the workspace's analysis over a file on every plan. Trying a schema
against a file before committing to it needs `module-custom-analysis` as well, as does
managing the schemas themselves, which is `admin:media-analysis:edit`, under [field
definitions](#field-definitions).

The two `stock-photo:*` permissions are a pair in practice: searching exists to feed the
import, and importing needs a search result to work from. `stock-photo:import` is not a
substitute for `media:upload`: a photo imported without naming an object it belongs to
lands in the library, and that still needs `media:upload`.

`media:publish` is separate from `media:edit` the way `media:download` is separate from
`media:view`: changing an asset and putting it on the public internet are different decisions.
Withdrawing a published asset is covered by the same permission. It is not the only one that
lets an asset reach people outside the workspace (`share-link:create` and `social:publish` do
too), so a role that withholds it usually means to withhold those as well.

The three `media:face:*` permissions need `module-face-recognition` and `media:publish` needs
`module-publication`. The rest of the table is on every plan.

## Albums and sharing

| Permission | Lets someone |
|---|---|
| `album:view` | Open an album and list them. |
| `album:create` | Create an album, including a smart album. |
| `album:edit` | Rename an album and change its settings or filters. |
| `album:delete` | Delete an album. |
| `album:curate` | Put files into an album and take them out. |
| `share-link:view` | See the share links a workspace has issued. |
| `share-link:create` | Create a share link. |
| `share-link:edit` | Change a link's expiry, password, or contents. |
| `share-link:delete` | Revoke a share link. |

Share links reach an unauthenticated audience, so `share-link:create` decides who may
publish workspace content outward. Treat it as more consequential than the rest of this
table.

The four `share-link:*` permissions need `module-media-sharing`. Albums are on every plan.

## Documents

| Permission | Lets someone |
|---|---|
| `document:view` | Browse the document library and open a document. |
| `document:upload` | Add a document to the library. |
| `document:edit` | Rename a document, tag it, edit its extracted text, and deprecate or restore it. |
| `document:delete` | Delete a document and its versions. |
| `document:download` | Download the original bytes. |
| `document:tag:create` | Add a value to an existing document tag group while filing something. |
| `document:relation-type:edit` | Define the relationship types documents can be linked with, such as a translation and its source. |
| `document-folder:view` | See the folder tree. |
| `document-folder:create` | Create a folder, including one that fills itself from a saved filter. |
| `document-folder:edit` | Rename a folder or move it under a different parent. |
| `document-folder:delete` | Delete a folder. The documents in it stay in the library. |
| `document-folder:curate` | Put documents into a folder and take them out. |

The document library is separate from the media library and so are its grants: a key holding
`media:view` cannot read a data sheet, and one holding `document:view` cannot browse the photo
library. That separation is the point of the module rather than a side effect, since the two
hold different kinds of confidential material.

`document:edit` covers deprecation, which is the verb worth understanding before granting it.
Deprecating a document removes its indexed passages, so an agent stops retrieving it, while the
file, its versions and its download links are all left intact. It is a way to retire a superseded
data sheet without breaking whoever still has the link, and it is reversible.

Linking two documents ("this is the Spanish translation of that") is part of `document:edit`, and
needs it on both documents. Deciding which kinds of link exist is the separate
`document:relation-type:edit`, because a relationship type is workspace vocabulary rather than a
change to any one document.

All twelve need `module-documents`.

## Designs and studio

| Permission | Lets someone |
|---|---|
| `design:view` | Open a design and list them. |
| `design:create` | Create a design, or one from a template. |
| `design:edit` | Change a design's layers and layout, and publish it as a template. |
| `design:delete` | Delete a design. |
| `design:fill` | Fill a template's editable fields without touching the layout. |
| `design:contribute` | Create designs from approved templates only. |
| `design:category:edit` | Manage the categories designs are filed under. |
| `studio:image:generate` | Generate an image. |
| `infographic:view` | Open a generated infographic and list them. |
| `infographic:generate` | Generate one, or refresh one from its data. |
| `infographic:edit` | Rename one, change its refresh schedule, or change who can see it. |
| `infographic:delete` | Delete one. |

`fill` and `contribute` exist so that people producing day-to-day artwork cannot change
the brand-approved layout it is built on. The two `generate` permissions spend credits,
which is why they are separate from the permissions that browse the results.

The design editor is the module here; infographics and Studio image generation are not.
Every design operation requires `module-design`, and turning an infographic into a design
does too. Generating an infographic or an image is on every plan, and what stops it is the
credit balance rather than the plan.

## Presentations

| Permission | Lets someone |
|---|---|
| `presentation:view` | Open a presentation. |
| `presentation:create` | Generate a presentation. |
| `presentation:edit` | Edit a presentation. |
| `presentation:delete` | Delete a presentation. |
| `presentation:template:edit` | Manage the templates presentations are generated from. |

Every permission in this table needs `module-ppt`.

## Website content

| Permission | Lets someone |
|---|---|
| `content:view` | Open a page, and list sites and pages. |
| `content:create` | Add a site or a page. |
| `content:edit` | Edit page content. |
| `content:delete` | Delete a site or page. |
| `content:generate` | Have the AI write a page, a brief, or a whole site. |
| `content:review` | Move a page through the approval workflow, including approving it. |
| `content:workflow:edit` | Set up the approval workflow: its steps, and who may make each move. |
| `content:comment:view` | Read the comments on a page. |
| `content:comment:create` | Comment on a page, or reply to a comment. |
| `content:comment:delete` | Delete a comment. |

Every permission in this table needs `module-content-editor`.

## Social

| Permission | Lets someone |
|---|---|
| `social:view` | See which accounts are connected, and what has been sent or scheduled. |
| `social:publish` | Send a post to a connected account, schedule one, or cancel one. |

Both permissions need `module-social-post`.

`social:view` covers reading the connected accounts, because whoever sends a post has to
choose where it goes. Connecting or disconnecting one writes a credential the whole
workspace posts under, so that is `admin:social:edit`, under [workspace
administration](#workspace-administration).

Despite the name, `social:publish` has nothing to do with `media:publish`. One sends a post
to an outside platform; the other releases a file on a URL this workspace serves.

## Workflows

| Permission | Lets someone |
|---|---|
| `workflow:view` | Open a workflow and its steps, and list them. |
| `workflow:create` | Create one. |
| `workflow:edit` | Change its steps. |
| `workflow:delete` | Delete one. |
| `workflow:deploy` | Compile and deploy it so it can run. |
| `workflow:execute` | Start a run. |
| `workflow:instance:view` | Open a run and its steps, and list them. |

`workflow:deploy` and `workflow:execute` are separate on purpose: building a workflow and
putting it into production are different decisions. Neither is gated on a module at the
API. The role is the whole gate.

## Tasks and routines

| Permission | Lets someone |
|---|---|
| `task:view` | Open a task and list them. |
| `task:create` | Create one. |
| `task:edit` | Edit one, approve it, or hand it to autopilot. |
| `task:delete` | Delete one. |
| `task:email:send` | Email a task's result out of the workspace. |
| `scheduled-job:view` | Open a routine and list them. |
| `scheduled-job:edit` | Change when it runs. |
| `scheduled-job:execute` | Run it now. |

Every operation under `/tasks` requires `module-tasks`, the daily briefing and autopilot
included. `scheduled-job:*` names no module, so the routines that start work on a schedule
stay available to a workspace without it. One operation sits outside both:
`POST /workflows/tasks/{id}/complete`, the callback a workflow step uses to close a task it
created, takes `task:edit` and names no module.

## Field definitions

Four things in the platform are a set of fields someone defined: the form a person fills in
to complete a task, the template a knowledge base records its items against, the schema that
tells the analysis what to detect in an image, and the schema that says what attributes a
kind of object carries. Each is its own collection, and each is granted separately.

| Permission | Lets someone |
|---|---|
| `task:form:edit` | Create, change and delete the forms tasks are completed with. |
| `knowledge-base:schema:edit` | Create, change and delete knowledge templates. |
| `admin:media-analysis:edit` | Create, change and delete media analysis schemas, and make one active. |
| `object:schema:edit` | Create, change and delete object schemas, and the kinds they declare. |

Each covers creating, changing and deleting together. A workspace that lets someone add a
field but not remove one is a distinction nobody has asked for, and the decision being
granted is the same one either way: may this person define the shape.

Reading is not granted separately at all. A set of fields is the shape of the records
rendered against it, so anyone who can open those records can read the definition behind
them. What varies is the module: analysis schemas need `module-custom-analysis` and object
schemas need `module-objects`, both named on the operations themselves, while task forms and
knowledge templates need none.

## Customer channels

| Permission | Lets someone |
|---|---|
| `chat-widget:view` | Open a widget, its conversations, and its leads. |
| `chat-widget:create` | Create a widget. |
| `chat-widget:edit` | Change its behavior, appearance, and agent. |
| `chat-widget:delete` | Delete a widget. |
| `voice-agent:view` | See a voice agent's configuration and analytics. |
| `voice-agent:create` | Create one. |
| `voice-agent:edit` | Change what it says and how it behaves. |
| `voice-agent:delete` | Delete one. |
| `voice-agent:number:edit` | Buy and release its phone numbers. |
| `voice-agent:call:view` | Read call transcripts and listen to recordings. |

The `chat-widget:*` permissions need `module-chat-widget`, and the `voice-agent:*`
permissions need `module-voice-agent`.

The voice permissions are split because they represent different decisions. The people who
build an agent are not always the people allowed to hear what customers said to it, and
buying a phone number both spends money and changes a published number.

## Integrations

| Permission | Lets someone |
|---|---|
| `integration:view` | See which third-party systems are connected and what they offer. |
| `integration:create` | Connect one. |
| `integration:edit` | Change a connection. |
| `integration:delete` | Disconnect one. |

Every permission in this table needs `module-external-data`.

## Extensions

| Permission | Lets someone |
|---|---|
| `extension:view` | See the extensions enabled in the workspace and the events sent to them. |
| `extension:install` | Enable an extension and choose what it may do, disable or remove it, and issue it a new key or signing secret. |
| `extension:develop` | Connect a dev build to an extension in a sandbox workspace and open the Workbench. |
| `extension-state:read` | Read the documents extensions keep in the workspace. |
| `extension-state:write` | Write and delete them. |

All five need **module-extensions**. An extension acting with its own key or with a token
minted for it reaches only its own documents, whatever it holds.

## Usage and notifications

| Permission | Lets someone |
|---|---|
| `usage:view` | See the workspace's own credit balance and usage totals. |
| `notification:view` | Receive and read notifications. |

`usage:view` is the workspace total, which anyone spending credits needs to see. The
breakdown by person, model and module is `admin:usage:view`, below.

## Workspace administration

Everything under `admin:` governs the workspace itself. There is no umbrella permission:
each operation requires exactly the grant it needs, so a role can be given user
administration and nothing else.

| Permission | Lets someone |
|---|---|
| `admin:user:view` | List the people in a workspace and open their records. |
| `admin:user:create` | Invite someone. |
| `admin:user:edit` | Change someone's roles, permissions, or status. |
| `admin:role:view` | List roles and see what they grant. |
| `admin:role:create` | Create a role. |
| `admin:role:edit` | Change what a role grants. |
| `admin:settings:view` | Read workspace defaults, such as the default agent. |
| `admin:settings:edit` | Change them. |
| `admin:audit:view` | Read the audit history: who changed what, and what it looked like before. |
| `admin:log:view` | Read the API access log. |
| `admin:security-event:view` | Read sign-in and security activity for everyone in the workspace. |
| `admin:usage:view` | See usage broken down by person, model, and module. |
| `admin:storage:view` | See what is stored and what could be reclaimed. |
| `admin:share-link:view` | See every share link the workspace has issued, not only your own. |
| `admin:media-tag:view` | Read the media tag structure, the groups and their values. |
| `admin:media-tag:edit` | Define that structure: add, rename and remove groups and values, and manage the hashtag list. |
| `admin:media-status-flow:view` | See the statuses media moves through and the transitions between them. |
| `admin:media-status-flow:edit` | Change them. |
| `admin:media:deduplicate` | Find duplicate media and resolve the groups. |
| `admin:geo-restriction:view` | Read the named country sets that published assets can be blocked from reaching. |
| `admin:geo-restriction:edit` | Create and change them, and set which of them every published asset is held to. |
| `admin:social:edit` | Connect and disconnect social accounts. |
| `admin:billing:edit` | Change the plan, buy credits, manage billing. |
| `admin:migration` | Run bulk imports from another system. |
| `admin:onboarding:run` | Run the first-run setup wizard and seed demo data. |

`admin:user:edit` and `admin:role:edit` are the two permissions that can change anyone
else's access, and `admin:role:edit` is the stronger of them, because it can widen a role
that other people already hold. Both are audited.

Resolving a duplicate group deletes files, so it requires `media:delete` alongside
`admin:media:deduplicate`. Listing the groups needs only the administration permission.

Two entries here need a module as well. `admin:social:edit` follows the rest of social
posting onto `module-social-post`, and the `admin:geo-restriction:*` pair follows publishing
onto `module-publication`.

## Permissions with no published operation

These gate application surfaces rather than operations a caller integrates against, so they
never appear on an operation in the reference. They still matter when you design a role.

| Permission | Lets someone |
|---|---|
| `api-key:view` | See the workspace's keys and when they were last used. |
| `api-key:create` | Issue an API key. |
| `api-key:revoke` | Revoke a key. |
| `saved-view:view` | Open the filter views kept on list screens. |
| `saved-view:create` | Save one. |
| `saved-view:edit` | Edit one. |
| `saved-view:delete` | Delete one. |

The three `api-key:*` permissions need `module-api`; the saved views are on every plan.

A key can only be scoped down from its creator's own access, so `api-key:create` does not
let someone grant themselves more permission than they have. It does let them hand out
what they already hold, so grant it accordingly.

Four more behave the same way. They are listed in the sections above rather than here,
because that is where you look for them when you build a role:

| Permission | Listed under |
|---|---|
| `notification:view` | [Usage and notifications](#usage-and-notifications) |
| `admin:billing:edit` | [Workspace administration](#workspace-administration) |
| `admin:migration` | [Workspace administration](#workspace-administration) |
| `admin:onboarding:run` | [Workspace administration](#workspace-administration) |

Billing, provisioning and bulk imports from another system are things a person does in the
app rather than surfaces anyone integrates against.

## Files

There are no file permissions. A file is governed by whatever it belongs to:

| A file in | Is governed by |
|---|---|
| The media library, and what the platform generated without filing it anywhere | `media:*`. `media:view` for the record and preview, `media:download` for the original |
| A knowledge base | `knowledge-base:*`. `view` reads the document, `write` changes it |
| A conversation | The conversation. Whoever can open the thread can open its attachments; `thread:upload` adds one |
| A design, prompt or presentation | That resource's own permissions |
| A task form | Nothing further to read it. A form's uploads are as readable as the form itself; `task:form:edit` changes or removes one |

A file operation therefore lists every permission that could apply to it, and which one
applies depends on where that file lives. A key scoped to `media:view` and
`media:download` reads the media library and provably nothing else.

## Not included

Permissions that govern cross-workspace tooling are not part of this API and are not
documented here.
