Permissions Reference
Every dashboard action maps to a named permission. A permission is granted when the caller's workspace role or their application role on the target application satisfies the rule — whichever axis applies first wins. See Team management for how roles are assigned.
sk_ / pk_ key. A Clerk caller carries the wildcard scope and is gated purely by these permissions; an API-key caller is gated purely by its scopes and never by RBAC. The two systems compose; neither replaces the other.How permission checks work
For each request Throttle resolves two values from the auth context: the caller's workspace-level role (owner | workspace_admin | none) and their application-level role on the specific application being acted on (admin | developer | finance | viewer | none). A permission is granted if either role set contains the caller.
owner and workspace_admin satisfy most application-level permissions without needing an explicit per-application role. They act as supersets of any application role on any application in the workspace.403 member_env_forbidden.The permission check is exposed at GET /api/v1/auth/permissions. The response lists every permission key and whether it resolves to true for the authenticated caller, optionally scoped to a specific application via the x-application-id header.
Permission catalog
The table below lists every permission string, which workspace roles satisfy it, and which application roles satisfy it. A dash (—) means that role axis is not checked for that permission.
| Permission | Workspace roles | Application roles |
|---|---|---|
workspace:delete | owner | — |
workspace:transfer | owner | — |
workspace:billing | owner | — |
workspace:invite-admin | owner | — |
workspace:settings | owner, workspace_admin | — |
workspace:invite | owner, workspace_admin | admin |
workspace:edit-member | owner, workspace_admin | — |
workspace:remove-member | owner, workspace_admin | — |
workspace:read-team | owner, workspace_admin, member | — |
application:settings | owner, workspace_admin | admin |
application:api-keys | owner, workspace_admin | admin, developer |
application:webhooks | owner, workspace_admin | admin, developer |
application:customers:write | owner, workspace_admin | admin, developer |
application:customers:read | owner, workspace_admin | admin, developer, finance, viewer |
application:orders:write | owner, workspace_admin | admin, developer |
application:orders:read | owner, workspace_admin | admin, developer, finance, viewer |
application:refunds:issue | owner, workspace_admin | admin, developer, finance |
application:payments:read | owner, workspace_admin | admin, developer, finance, viewer |
application:edit-app-member | owner, workspace_admin | admin |
application:extensions:read | owner, workspace_admin | admin, developer, finance, viewer |
application:extensions:write | owner, workspace_admin | admin, developer |
application:extensions:install | owner, workspace_admin | admin, developer |
application:extensions:admin | owner, workspace_admin | admin |
Permission scope notes
Workspace-only permissions
workspace:delete,workspace:transfer,workspace:billing, andworkspace:invite-adminare exclusively for the owner. No application role satisfies these.workspace:settingscovers workspace branding, sender domains, and workspace-scoped email settings.workspace:edit-memberandworkspace:remove-memberrequire workspace_admin or above; no application role grants them.
Read vs write split
- The
financerole sees customers, orders, and payments but cannot write to customers or orders. It can issue refunds. - The
viewerrole is fully read-only. It cannot issue refunds or perform any write action. - The
developerrole is the same asfinanceplus write access to customers and orders, and access to API keys and webhooks.
Check permissions at runtime
Call GET /api/v1/auth/permissions with a Clerk JWT. Pass x-application-id to resolve application-level role flags for a specific application. The response shape is:
{
"workspaceRole": "workspace_admin",
"appRole": "developer",
"permissions": {
"workspace:delete": false,
"workspace:invite": true,
"application:api-keys": true,
"application:customers:write": true,
...
}
}