Permissions
Each role in a tenant holds a fixed set of permissions (see Roles). FlowState checks the permission on every request, in the web app, the API and MCP.
Tenant permissions
A permission applies only in the tenant where you hold the role. Holding
tenant:notifications:audit:read in tenant A does not let you read tenant B’s audit log.
Settings and administration
| Permission | Self-scoped? | Allows |
|---|---|---|
tenant:settings:read | No | Read tenant name, slug, tier, status, features map, region |
tenant:settings:write | No | Update the tenant name and slug |
tenant:members:read | No | List all members with their roles and last-seen timestamps |
tenant:members:invite | No | Create, list, and revoke pending invites |
tenant:members:remove | No | Remove any member except the owner |
tenant:members:role:write | No | Change a member’s role (never to or from owner) |
tenant:grants:read | No | Read each member’s MCP usage limits |
tenant:grants:write | No | Set or remove a member’s MCP usage limits |
tenant:keys:read | No | List all API keys in the tenant (metadata only, no plaintext) |
tenant:keys:read:self | Yes | List own API keys only |
tenant:keys:write | No | Create API keys, and revoke or rotate your own. With tenant:keys:read as well, revoke or rotate any key in the tenant |
tenant:billing:read | No | Read subscription status, usage summary, invoice list |
tenant:billing:write | No | Open the Stripe billing portal and start a subscription checkout for the tenant |
tenant:transfer:owner | No | Transfer ownership to another member. Only the owner holds it |
tenant:delete | No | Delete the tenant (restorable for 30 days). Only the owner holds it |
tenant:features:read | No | Read the tenant feature-flag map |
tenant:features:write | No | Turn a feature on or off under Settings → Features. Turning a feature off keeps its data |
Integrations
| Permission | Allows |
|---|---|
tenant:integrations:hubspot:connect | Connect a new HubSpot integration or reconnect after token expiry |
tenant:integrations:hubspot:disconnect | Disconnect the HubSpot integration and delete the stored credentials |
tenant:integrations:hubspot:read | Read the integration status, HubSpot account id, granted scopes and connection time |
tenant:integrations:slack:read | Read the Slack integration status, connected workspace, and configured channels |
tenant:integrations:slack:write | Connect, configure channels, set routing rules, and disconnect the Slack integration |
tenant:integrations:apn:configure | Connect, configure catalog (Sandbox/Production), and disconnect APN |
tenant:integrations:apn:read | Read APN integration status, partner account ID, catalog, and sync statistics |
Deals, analysis and sync
| Permission | Allows |
|---|---|
tenant:hubspot:read | Call HubSpot CRM and reporting APIs using the tenant’s stored credentials |
tenant:deals:analyze | Trigger a pipeline refresh run; invoke AI deal analysis |
tenant:deals:read | Read precomputed deal snapshots, pipeline summaries, and deal details |
tenant:deals:reanalyze | Force a fresh analysis of one deal |
tenant:goals:read | Read annual revenue and deal-count goals and rep quotas |
tenant:goals:write | Set annual goals and per-rep quota targets |
tenant:win-loss:read | Read win/loss aggregations and trend analyses |
tenant:win-loss:trigger | Start a win/loss analysis over up to 48 months. At most one run per tenant every 15 minutes |
tenant:slack:test | Send a test message to the tenant’s configured Slack channel |
tenant:apn:read | Read APN sync state for all deals; list opportunities; read conflicts and errors |
tenant:apn:sync:trigger | Trigger manual syncs; retry failed syncs; resolve conflicts; accept/reject engagement invitations |
tenant:marketplace:offers:read | Read Marketplace private offers, their draft changesets and release status |
tenant:marketplace:offers:write | Create and amend DRAFT private offers. A released offer’s commercial terms can never be changed |
tenant:marketplace:offers:release | Release a draft private offer to the buyer. Irreversible — kept separate from write for that reason |
tenant:mcp:invoke | Use the MCP server in this tenant. Without it, every MCP request, including listing the tools, is refused. Each tool also needs its own permission |
Notifications
| Permission | Self-scoped? | Allows |
|---|---|---|
tenant:notifications:read | No | See which members of the tenant receive which notification categories |
tenant:notifications:read:self | Yes | Read own global and per-tenant notification preferences |
tenant:notifications:write:self | Yes | Update own notification preferences (enable/disable categories, per-tenant overrides) |
tenant:notifications:audit:read | No | Read the tenant’s audit log (Settings → Notifications → Audit) and its notification send log |
Self-scoped permissions
A permission ending in :self works only on your own resources:
tenant:keys:read:self: your own API keys, not other members’ keys.tenant:notifications:read:self: your own notification preferences.tenant:notifications:write:self: changes to your own notification preferences.
A :self permission never gives access to another member’s resources. Owners and admins also
hold the broader permissions, which cover their own resources too.