Skip to content

Scopes ​

A scope says what an API key may do. A key carries one or more scopes; each route of the API requires exactly one; the request passes when one of the key's scopes covers the required one. Scopes restrict: a key never does more than the member who created it (Authentication).

The grammar ​

A scope is written <domain>:<verb>, with the verb one of read, write or *:

  • workflows:read — read the routes of the domain;
  • workflows:write — read and write: write implies read. A key that can create a workflow can read it back; a key that writes blind would help nobody;
  • workflows:* — the wildcard of one domain, equivalent to write today and to whatever the domain gains tomorrow.

There is no global wildcard: a key that can do everything is a key you can no longer revoke without cutting everything. Grant one domain at a time.

A route requires a precise verb, never a wildcard: GET /api/v1/workflows requires workflows:read, POST /api/v1/workflows requires workflows:write. The key is what may carry a broader scope. When you create a key, redundant scopes are reduced: asking for workflows:read and workflows:write stores workflows:write alone.

The verb follows the effect of the route, not its HTTP method. Running a workflow creates an execution, so POST /api/v1/workflows/{id}/test, POST /api/v1/workflows/{id}/run and the retry routes require executions:write, not workflows:write.

Domains ​

The domains are those of the Settings › API keys screen, where each one is a row with three choices: nothing, read, read and write.

DomainWhat it covers
workflowsWorkflows (drafts, versions, publishing, node catalog), prompt evaluation runs, installing a template
executionsExecutions (read, retry, cancel, test runs), waiting executions and their manual wake-up
mailboxesMailboxes (list, sync, journal, folders)
messagesMessages (read, search, send, drafts), threads and their actions
tablesTables (schema and rows)
contactsAddress book
templatesWorkflow templates (reading the catalog; installing one is workflows:write)
connectionsConnections (integrations, AI models)
approvalsApprovals
notificationsNotifications and incidents, including the execution summary
reviewMorning review and sending journal
analyzerMailbox analyzer
assistantWorkflow assistant
dashboardDashboard
profileMy account (profile, scope, signatures)
adminAdministration (members, policies, audit log), reserved to administrators

The exact scope of every route is in the reference, under its Access line.

Administrator-only scopes ​

admin:read, admin:write and admin:* can be put on a key only by an administrator. The restriction is not a security measure (a key of an ordinary member would fail the administrator check anyway) but a matter of honesty: a scope you can tick and that will never do anything is a lie on screen. POST /api/v1/api-keys refuses them to an ordinary member with api_key.scope_forbidden.

Conversely, an administrator's key with no admin scope cannot reach /api/v1/admin/…: the key restricts, as always.

signals:write ​

signals:write is the only scope without a read counterpart: a signal is emitted, never read. It covers one route, POST /api/v1/signals, which wakes or cancels the executions waiting on a key (see the flow.wait node). It is the scope to give a CRM or a signing service that only needs to tell Mankomail "this file is signed".

How a route declares its scope ​

In the OpenAPI document, every route open to keys carries the extension x-required-scope, and lists the same scope under its security requirement:

json
{
  "summary": "Create a workflow",
  "x-required-scope": "workflows:write",
  "security": [
    { "sessionCookie": [] },
    { "apiKey": ["workflows:write"] }
  ]
}

The two entries of security are alternatives: a session cookie, or an API key whose scopes cover workflows:write. Routes reserved to a session carry only sessionCookie; public routes carry an empty security.

When a scope is missing ​

A key whose scopes do not cover the route gets 403 with the code api_key.scope_missing and the scope to add in details.required:

json
{
  "code": "api_key.scope_missing",
  "message": "missing scope workflows:write",
  "details": { "required": "workflows:write" }
}

The key itself is fine. Create a key with the missing scope (or a broader verb on the same domain) and replace it in the calling system. Scopes cannot be edited after creation.