Go to Slack

Permissions API

Developer preview

Workspace apps are currently in developer preview. You are welcome to install as internal integrations or distribute to other workspaces, but we aren't yet accepting workspace app submissions for the Slack app directory.

Whether your app asks for permissions progressively or requires them all at installation, workspace apps may use the Permissions API to programmatically manage workspace access.

Lunch Train asking for upgraded posting permissions

Permissions API Overview

The Permissions API grants you the serenity to deftly manage your app's capabilities, privileges, and resources:

  • Capabilities - the things your app can do for a workspace, like offering slash commands or posting interactive notifications. Sometimes, but not always, represented by a scope.
  • Privileges - the things your app is allowed to do for a workspace, like being granted the ability to learn more about users or examine channel history. Typically represented by a scope. Scopes apply workspace-wide and travel to whichever resources your app is granted.
  • Resources - the where and what your app can act and act on, like a list of channels, specific direct message conversations, and a workspace.

The Permissions API is not a single API but a collection of Web API methods and Events API event types that inform your app about permission and access change over time while also providing your app with the hooks needed to progressively ask for additional permissions. OAuth 2.0 is still required to manage initial application installation for distributed apps.

Workspace token-based Slack apps are required for the Permissions API. It cannot be used with traditional user and bot token-based Slack apps or legacy custom integrations.

Flow and states

Where does OAuth end and these permission APIs begin? In the infinitesimal space between the reticulated splines of each. They work together.

Here is a description of your hopefully never-ending, non-linear Permissions API lifecycle :

A user installs your app for the first (or nth) time

This is part of the Slack app installation flow, either using OAuth or the streamlined single workspace installation flow.

Lunch Train installation

All workspace apps request default permissions from the installing user — the opportunity to have a direct message conversation with the app. Additional permissions can be requested at this time, or they can be saved for later.

A user adds your app to a resource

During the installation process or during the normal course of user business, a user might add your app directly to a resource.

Lunch Train being added to a single channel

One way they might do this is by inviting your app to a public or private channel, or by adding your slash command to a channel, or by discovering your app in the sidebar.

If subscribed, you'll receive resources_added events as this happens.

A user removes your app from a resource

This happens to all apps. Your app is asked to leave a channel or is removed from it in some other way.

When this happens, your scopes and access will no longer apply to the resource and you'll get a resources_removed event, if subscribed.

Your app requests additional permissions

If progressive permissions is an attractive concept to you, then bask in the opportunity to conversationally suggest expanding your app's permission purview.

Lunch Train asks for more permission

While your app can't make this request out of the blue, there are many opportunities to initiate this flow and it's an ideal way to gate paid features, trial new functionality, and change your app's capabilities over time.

Implementation details can be found in the progressive permissions section below.

Your app is awarded or rejected those permissions

It's not enough to ask for progressive permissions, you need to be granted or rejected them to.

Lunch Train gets more permission

This step is actually just like the other resources_added step above — the net result is your app gains resources and is notified about it.

Your app waits for stuff to happen

Your app is probably doing other things, just things with the permissions, resources, and capabilities afforded to it. But as far as the Permissions API goes, your app just waits for a new change to occur.

Maybe your app makes occasional requests to apps.permissions.resources.list and apps.permissions.scopes.list while waiting — just in case.

Resources

Each OAuth scope governs your app's capabilities against a set of resources.

A single resource might be a specific direct message conversation, a private channel, or maybe even a wildcard.

Today, workspace apps support only these resources:

  • channel - public channels
  • im - private direct messages
  • mpim - private multi-party direct messages
  • group - private channels
  • team - information about the workspace itself and its inhabitants

Expect this list to include users and files and more in the future.

Wildcard resources

These little tricksters let a user add your application to all of something. Today, only the channels resource can be communicated as a wildcard, meaning a user can indicate your app should be installed in all public channels. All channels that is, except those explicitly excluded.

Here's what it looks like when a user selects a channel wildcard:

Lunch Train asking for upgraded posting permissions

Find the status of any wildcard permissions granted to your app using apps.permissions.info:

{
    "ok": true,
    "info": {
        "channel": {
            "scopes": [
                "channels:history",
                "chat:write"
            ],
            "resources": {
                "ids": [],
                "wildcard": true,
                "excluded_ids": [ "C01234BCD"]
            }
        }
    }
}

The above structure says your app may read the history of and post messages to all public channels, except the channel identified by C01234BCD.

Wildcard exclusions

You won't be able to read or write data about excluded resources.

Users may block workspace apps from a list the channels at installation time, even when installing to a wildcard like all public channels.

You'll find a list of excluded channel IDs in excluded_ids arrays returned in apps.permissions.info.

The resources listed in excluded_ids supersede any wildcard-awarded grants. If your app is "kicked" or forced to leave a channel, that channel ID will be included in excluded_ids.

OAuth permission scopes

As with all Slack apps, workspace apps are governed by the OAuth 2.0 scopes system.

OAuth permission scopes apply globally to workspaces your app is installed on. However, each specific resource those scopes work against are governed by granted resources. So if your app has the chat:write and channels:history scopes, those scopes travel with your app to any channel resource it's allowed to use, like a #general channel.

To determine which OAuth scopes are supported with workspace apps, look for the workspace token labels. Only the scopes with this label work with workspace-based apps and the Permissions API.

Discover the currently supported scopes for workspace apps here.

During the developer preview period, we will continue refining the scope system for workspace apps.

Monitoring change with the Events API

If you're working with workspace apps or with the Permissions API, then chances are you'll want to use the Events API too. And if you do that, you'll want to subscribe to these app event types, which require no specific OAuth scope.

resources_added

The thing about this event is that you need to be ready for it at any time. In a world of workspace apps, a user might discover your app and open a conversation with it. Or discover your slash command and add it to a dozen channels willy-nilly.

For direct messages, you won't get a chance to say "yeah, but" — the conversation will open and you'll get the base-level grant to converse as if they're an installer.

{
        "token": "verification_token",
        "team_id": "T061EG9R6",
        "api_app_id": "A0BLA3EP2",
        "event": {
                "type": "resources_added",
                "resources": [
                        {
                                "resource": {
                                        "type": "channel",
                                        "grant": {
                                                "type": "specific",
                                                "resource_id": "C061EG9SL"
                                        }
                                },
                                "scopes": [
                                        "channels:read"
                                ]
                        }
                ]
        },
        "type": "event_callback",
        "authed_teams": [],
        "event_id": "Ev0CV7H3KJ",
        "event_time": 1501110008
}

Here's another example of a resources_added event, this time our app is being awarded the users:read scope against the team resource. We can read the list of users and information about those users.

{
    "token": "verification_token",
    "team_id": "T061EG9R6",
    "api_app_id": "A0BLA3EP2",
    "event": {
        "type": "resources_added",
        "resources": [
            {
                "resource": {
                    "type": "workspace",
                    "grant": {
                        "type": "specific",
                        "resource_id": "T061EG9R6"
                    }
                },
                "scopes": [
                    "users:read"
                ]
            }
        ]
    },
    "type": "event_callback",
    "authed_teams": [],
    "event_id": "Ev0CQ92RH7",
    "event_time": 1501174698
}

See resources_added for more information.

resources_removed

Users and admins can remove your app from channels and other conversations. Maybe someday they can seek and destroy a piecemeal permission. If you're keeping track, this event subscription will tell you which grants have gone the way of the dodo.

{
    "token": "verification_token",
    "team_id": "T061EG9R6",
    "api_app_id": "A0BLA3EP2",
    "event": {
        "type": "resources_removed",
        "resources": [
            {
                "resource": {
                    "type": "channel",
                    "grant": {
                        "type": "specific",
                        "resource_id": "C061EG9SL"
                    }
                },
                "scopes": [
                    "channels:read"
                ]
            }
        ]
    },
    "type": "event_callback",
    "authed_teams": [],
    "event_id": "Ev0CV7JG72",
    "event_time": 1501110117
}

See resources_removed for more information.

scope_granted

When subscribed to this event, you'll receive it when a user approves specific scopes to your app. Often paired with resources_added events, though it depends on what the scopes are being added to.

See scope_granted for more information.

scope_denied

When subscribed to this event, you'll receive it when a user rejects the overtures of your apps.permission.request.

See scope_denied for more information.


Progressive permissions

Request for permissions all up front during installation, or ask for them incrementally using the Permissions API.

Learn more about building progressive permission upgrade flows.

Methods for the Web API

Look up your app's current state of permissions with a workspace or leverage a trigger_id to make a progressive permissions request with these two workspace token API methods.

Examine current permissions

Look up your token's current permission state at will with apps.permissions.resources.list and apps.permissions.scopes.list. You'll find a complete inventory of afforded OAuth scopes and resources.

Your app's home

What's an app_home? It's like a virtual house for your Slack app. Today, it's a handy way of knowing which users you can have open direct message conversations with — the ones users can find under Apps in the sidebar.

The App Home's natural habitat

The resources correspond to those direct message conversations and scopes are your app's powers granted to those same conversations.

The best way to receive and differentiate messages in App Home is by subscribing to message.app_home events with the Events API. No additional scopes are required.

Request permissions with apps.permissions.request

This is your powerful write request initiating everything awesome about progressive permissions.

When successful, Slack presents a delightful dialog to the intended user, requesting the scopes in context to the appropriate resources.

The real trick with the method, if you haven't read deeper yet, is that you need a trigger_id and you can only get one of those from a slash command invocation or an interactive message action. Learn more about triggers.

Which means that your app needs to incite a user to do something — click a button, select from a menu, or type a slash command to inspire your app to ask the user for more permission.

Events for the Events API

Triggers and how to find them

Learn more about finding and using triggers.