You must enable javascript in order to use Slack. You can do this in your browser settings.

Apps in shared channels

The rundown
Read this if:You're still experimenting, prototyping, and exploring.
Read next: Enterprise Grid Sandbox

Shared Channels allows you to collaborate with an external org!

Shared channels empower paid workspaces to seamlessly collaborate with people working at other companies and organizations without leaving Slack — or your Slack apps behind.

While many apps, bots, and other integrations should continue to work with shared channels, you may face unexpected quirks as a result of multiple teams mingling in the same space, made manageable with our Conversation APIs.

What are shared channels?

A shared channel is a bridge between teams needing to work together. Instead of endless email threads or sidecar Slack workspaces, teams can use shared channels to connect, chat, share files, and use apps with the same cozy ease they use communicating with their more immediate colleagues.

Life before shared channels

Maybe you're just learning about shared channels or maybe it's years from when this documentation was written. Hello, time traveler. In either case, let's rewind to life before shared channels to understand how they can make your working life simpler and more productive:

Before shared channels. With cats and dogs.

Before, when messaging was more limited, what our feline friends were saying and doing on the project that impacted these playful pups was a mystery. When the two teams tried to communicate it was disconnected, disparate, even duplicative.

This is now solved with shared channels. Now the project channel #projectM exists in each team's workspace (Catnip Inc. and Woof Inc., respectively).

After shared channels. With cats and dogs.

How shared channels work

In an ideal world, shared channels will work just like any other channel for users. Your app should also act predictably.

Messages and files

Both team's workspaces involved in a shared channel can read and send messages, share files, and access the history of shared channels.

Channel settings

A shared channel may have different settings on each workspace it's party to.

  • Channel names may differ. What's one workspace's #do-stuff is another workspace's #do-nothing. It's best to make no assumptions about channel names and stick only with IDs.
  • One workspace might set the channel as private, while the other workspace may set the same channel as public.
  • Data retention settings may differ between teams.

With all these differences in channel type settings, you must use the new Conversations API instead of existing APIs like channels.*, ims.*`, and groups.*

Supporting shared channels

Be on the look out for minor differences in channel, message, user, team and related objects. When a channel can hold multiple teams within it, naturally you'll encounter messages and users originating from other teams.

🆕 Detecting when a channel is shared and unshared

Your app can be informed when channels become shared and unshared with another team by subscribing to the channel_shared and channel_unshared events in the Event Subscriptions tab under your Apps page.

To receive all shared events for channels or groups in a workspace, your app will need the channels:read or groups:read scope respectively. To receive only shared events for channels and groups your bot user is in, your app just needs the bot scope.

Both shared events contain the ID of the channel itself in addition to the team that the channel was shared or unshared with:

{
    "type": "channel_shared",
    "connected_team_id": "TLL6DGUHX",
    "channel": "CLZT0MJHZ",
    "event_ts": "1565722340.000000"
}

It may be helpful for your app to note the connected_team_id, as it will start receiving messages and events from users on that external team.

Users may seem strange

Your app will begin to receive messages and events from users on external teams. Information about these users will be different than users on the workspace where your app is installed.

A stranger in shared channels
An external member. In their profile, a member from an external team will be marked with a square status indicator next to the user name.
  • External members are members on the other team that your application shares channel membership with.
  • Strangers are external members on the other team that your application does not have a shared channel in common; you can find out about these members when the other team mentions them in the shared channel or shares one of their messages or files into the shared channel.

The user type object (returned by methods like users.info) provides additional information to identify external members, while withholding some information your app may expect.

  • If the user is a stranger who isn't in any shared channels, the is_stranger flag is set true.
  • For external members and strangers, profile data will not contain email even if you have the users:read.email scope.
  • For external members and strangers, profile data will not contain any locale information, even if you pass the include_locale flag.

Here's an example of a response from users.info:

{
    "ok": true,
    "user": {
        "id": "U0BNRNDKJ",
        "team_id": "T07QCRP7S",
        "name": "rex",
        "real_name": "Devon Rex",
        "profile": {
            "image_24": "https:\/\/.../11662770033.jpg",
            "team": "T07QCRP7S",
            "display_name": "eshellstrop"
            // all that other stuff
        },
        "is_stranger": true
    }
}

Please note that when you specify a user, you need to use user id, instead of the username. With the new name-tagging feature, the username attribute cannot be relied on as a unique identifier, and will not work with "foreign" users via the API. For example, you cannot use chat.postMessage with a username set to a foreign user.

A bot user 🤖 is able to DM users on both workspaces, as long as users are in a shared channel together.

Same channel, different setting

When a channel is shared, the channel ID remains the same but the name prefix can be different, depending on its setting- Even if the channel is set to private, the ID prefix changes from G to C (e.g. G1234567890 becomes C1234567890).

Since each team in the channel can independently decide if the channel is public or private on their end, so there are some changes with the APIs too:

  • The conversations.* methods accept any type of channel.

  • The channel type object now includes the channel type info (public, private, etc.).

  • The conversations.info method will provide additional information on the workspaces connected to the shared channel and the ID of the host workspace.

  • Now the channels.* methods accept both public and private channels with appropriate permission scopes.

The channel type object (which is returned by methods like conversations.info) tells you additional channel info. If the channel is shared, is_shared is set true. If it is a private channel or a group DM channel, the properties, is_private or is_mpim is set true, respectively.

Use the is_shared, is_private, and is_mpim flags exclusively to determine the privacy and type of a given channel.

Example response from conversations.list:

{
    "ok": true,
    "channels": [
        {
            "id": "C0A1NBPT3",
            "name": "product-qa",
            "is_channel": true,
            "created": 1491332036,
            "creator": "U0A379ZT2",
            "is_archived": false,
            "is_general": false,
            "is_shared": true,
            "is_org_shared": false,
            "is_member": false,
            "is_private": true,
            "is_mpim": false,
            "members": [
                "U0A379ZT2",
                "U0AU7DMHN"
            ],
             ...
        },
        { ...  },
    ]
}

Unsharing Channels

When a shared channel is unshared by the host workspace, both teams can still access channel history for all previous messages and activity. However, the channel in the disconnected workspace will be assigned a new ID, while the host workspace keeps the original channel ID.

Sharing and unsharing private channels

Shared channels can be made private on a per-workspace basis. For instance, a public channel on one workspace can be shared with a private channel on another workspace. Use the Conversations API methods to work with the channels and accurately determine their privacy. channels.* and groups.* will not work with private shared channels.

When a workspace's private shared channel becomes unshared, its channel ID remains C-prefixed (i.e. C1234567890 does not change back to G1234567890) although the channel is still private, making channel prefix an unreliable narrator in determining privacy.

New behavior to expect

In general, apps work between workspaces transparently. However, due to the nature of sharing, there will be restrictions in some scenarios depending on how the service behind the app is designed. For example, a commercial app like Salesforce that's tied to a specific workspace's users won't automatically give access to the users on another workspace. The Conversations API & users.info method should be used to determine appropriate data access of your app. As a rule of thumb, your app should default to exposing less information in shared channels to protect your users' data.

Bot users are accessible to all users on the workspace where your app is installed, and any external members in a shared channel where your bot is also present. When an external member messages you, the team parameter will inform your app which team their message originated from. You can compare this to the team_id parameter, which indicates the workspace where the app is installed. If your app typically shares sensitive information, make sure to change its behavior for external members.

Slash commands and message actions are not shared — they are limited only to the team that has installed to their team workspace. Another team needs to install them independently to be able to use them.

When your app is initiated by a slash command or message action, only the team that installed your app can invoke it, but external members can still see any information posted into channel as a result. For example, let's say Catnip inc. has installed a polling app that is initiated with a command /poll. Users in the Catnip inc. can initiate a poll, while Woof inc. can only vote on the poll and cannot create a new poll.

Example: a shared bot that initiates with a slash command

Slash Command behavior on shared channels

Support strategies by feature

API Support strategies
Events API
  • Support events originated from external users in the shared channels.
  • No duplicated event triggering between shared channels
  • To see which teams the event is delivered, look for the values of the authed_teams property for the response.
  • Web API
  • Support external users in shared channels. Some user-related actions will not be permissible due to their external nature
  • Use users.info to retrieve additional information on cross-team user ID not found in users.list.
  • Incoming webhooks
  • Messages from incoming webhooks are visible to all members of a shared channel.
  • Incoming webhook can send DM only to the users on installed teams.
  • Slash commands
  • Slash commands can be only invoked by users belonging to the workspace your app is installed.
  • Turn on entity resolution for mentioned users, allowing you to identity them by id, including on foreign teams.
  • Message actions
  • Message actions can be only invoked by users belonging to the workspace your app is installed.
  • Interactive messages
  • Handle action invocation by users from other teams, and letting them know if an action is not permissible due to their external nature.
  • Unfurls
  • When a user on the installing workspace posts a link in the shared channel. The link should be unfurled for the entire channel unless there is a privacy concern.
  • RTM
  • Support users from other workspace in shared channels where appropriate.
  • Message deliveries are duplicated in shared channels when installed on multiple joined workspaces due to the multiple socket connections.
  • Bot users 🤖
  • Bot users can DM all local users in the workspace they are installed in, and external users with a common shared channel.
  • Conversations API

    Developing with shared channels effectively requires using the new Web API methods we call the Conversations API.

    Requesting a sandbox

    Building properly for shared channels or enterprise grid requires experiencing the unique constraints and opportunities yourself.

    If you don't already have access to workspaces with the proper plan level to grant access to shared channels, please complete the form below to request a sandbox. We'll get back to you as soon as possible.

    Request a sandbox

    Known issues

    We're still working on shared channels. Some features are not yet available and it's likely you'll run into a bug or three.

    Here's what we know about:

    🚧 Channel IDs can become unstable in certain situations

    There are a few circumstances channel IDs might change within a workspace. If you can operate without depending on their stability, you'll be well-prepared for unfortunate hijinks.

    In the future, we'll mitigate this unexpected transition with appropriate Events API events or other solutions.

    In the meantime, be aware this might happen and use conversations.list regularly to monitor change for known #channel names if ID stability is important to you.

    🚧 MPIM events tell little lies about channel types

    In a multiparty direct message channel ("MPIM") with a foreign user, events like member_joined_channel and member_left_channel may dispatch an incorrect value for channel_type.

    🚧 IM Object format is not yet consistent

    IM formats may differ from other channel objects for a while. We're working towards making all objects the same format.

    🚧 Unsharing channels

    When a channel becomes unshared, conversations.history access for the channel may become unreliable.

    🚧 Select menus may be inconsistent

    Default select menus (users_select, conversations_select, and channels_select) may display unexpected options in shared channels.

    🚧 app_home_opened event isn't triggered for external members

    When members from the non-host workspace access the app DM, the app_home_opened event will not be fired.

    Stay tuned for future updates!