Public channels, private channels, DMs... They're all conversations!
The Slack Conversations API provides your app with a unified interface to work with all the channel-like things encountered in Slack: public channels, private channels, direct messages, group direct messages, and our newest channel type, Shared Channels.
Use this API family to review history, create or archive channels, invite team members, set conversation topic and purpose, and more — no matter what type of conversation your app is working with.
The types of channels you may interface with in the Conversations API is governed by corresponding OAuth scopes. To retrieve info about a public channel, you'll need channels:read
and for info about a private channel, you'll need groups:read
), and so on.
Journey with us, and stay tuned for future updates!
If it walks like a duck, quacks like a duck, and swims like a duck — it's probably a duck!
If it works like a channel, has messages like a channel, and is experienced like a channel... it's a channel conversation!!!
Before the Conversations API, you needed to use different methods from multiple "family trees" to achieve the same thing depending on the type of channel you were working with.
For example, to list direct messages you had to call im.list
, but for public channels you had to call channels.list
. Many different objects and shapes at their core all represented the same type of timeline message container. All these older methods are now deprecated
In the new model, just use conversations
to access anything channel-like. For example, the conversation.list
method returns information on public, private, and direct message channels, when accessed with the appropriate permission scopes.
Channel Type | Previously used method | New method you should use |
---|---|---|
Public | channels.list |
conversations.list |
Private | groups.list |
conversations.list |
DM | im.list |
conversations.list |
Group DM | mpim.list |
conversations.list |
Method & Description | Description |
---|---|
conversations.acceptSharedInvite Accepts an invitation to a Slack Connect channel. | Accepts an invitation to a Slack Connect channel. |
conversations.approveSharedInvite Approves an invitation to a Slack Connect channel | Approves an invitation to a Slack Connect channel |
conversations.archive Archives a conversation. | Archives a conversation. |
conversations.close Closes a direct message or multi-person direct message. | Closes a direct message or multi-person direct message. |
conversations.create Initiates a public or private channel-based conversation | Initiates a public or private channel-based conversation |
conversations.declineSharedInvite Declines a Slack Connect channel invite. | Declines a Slack Connect channel invite. |
conversations.history Fetches a conversation's history of messages and events. | Fetches a conversation's history of messages and events. |
conversations.info Retrieve information about a conversation. | Retrieve information about a conversation. |
conversations.invite Invites users to a channel. | Invites users to a channel. |
conversations.inviteShared Sends an invitation to a Slack Connect channel | Sends an invitation to a Slack Connect channel |
conversations.join Joins an existing conversation. | Joins an existing conversation. |
conversations.kick Removes a user from a conversation. | Removes a user from a conversation. |
conversations.leave Leaves a conversation. | Leaves a conversation. |
conversations.list Lists all channels in a Slack team. | Lists all channels in a Slack team. |
conversations.listConnectInvites Lists shared channel invites that have been generated or received but have not been approved by all parties | Lists shared channel invites that have been generated or received but have not been approved by all parties |
conversations.mark Sets the read cursor in a channel. | Sets the read cursor in a channel. |
conversations.members Retrieve members of a conversation. | Retrieve members of a conversation. |
conversations.open Opens or resumes a direct message or multi-person direct message. | Opens or resumes a direct message or multi-person direct message. |
conversations.rename Renames a conversation. | Renames a conversation. |
conversations.replies Retrieve a thread of messages posted to a conversation | Retrieve a thread of messages posted to a conversation |
conversations.setPurpose Sets the purpose for a conversation. | Sets the purpose for a conversation. |
conversations.setTopic Sets the topic for a conversation. | Sets the topic for a conversation. |
conversations.unarchive Reverses conversation archival. | Reverses conversation archival. |
users.conversations List conversations the calling user may access. | List conversations the calling user may access. |
Each channel has a unique-to-the-team ID that begins with a single letter prefix: either C
, G
, or D
.
When a channel is shared across teams (see Developing for Shared Channels), the prefix of the channel ID may be changed, e.g. a private channel with ID G0987654321
may become ID C0987654321
.
This is one reason you should use the conversations
methods instead of the previous API methods! You cannot rely on a private shared channel's unique ID remaining constant during its entire lifetime.
The channel type object 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
are set true
, respectively.
The response to conversations.list
might look like the following, with the first channel in this example being a shared channel:
{
"ok": true,
"channels": [
{
"id": "C0AMV1W3T",
"name": "shared-project-01",
"is_channel": true,
"created": 1494292130,
"creator": "U07QCR6A4",
"is_archived": false,
"is_general": false,
"name_normalized": "shared-project-01",
"is_shared": true,
"is_org_shared": false,
"is_member": false,
"is_private": false,
"is_mpim": false,
"topic": {
"value": "",
"creator": "",
"last_set": 0
},
"purpose": {
"value": "",
"creator": "",
"last_set": 0
},
"previous_names": [],
"num_members": 27
},
...
]
}
Some of the most important fields in conversation objects are the booleans indicating what kind of conversation/channel it is and how private it is.
Here's a legend:
is_archived
indicates a conversation is archived.is_channel
indicates whether a conversation is a public channel. Everything said in a public channel can be read by anyone else belonging to a workspace. is_private
will usually be false
whenever this boolean is true
, but you should check both to take care of edge cases.is_ext_shared
shows whether this conversation is part of a Shared Channel with a remote organization. Your app should make sure the data it shares in such a channel is appropriate for both workspaces. is_shared
will also be true
.is_general
means the channel is the workspace's "general" discussion channel (even if it may not be named #general
). That might be important to your app because almost every user is a member.is_group
means the channel is a private channel. is_private
will also be true
. Check yourself before you wreck yourself.is_im
means the conversation is a direct message between two distinguished individuals or a user and a bot. Yes, it's an is_private
conversation.is_member
indicates the user or bot user or Slack app associated with the token making the API call is itself a member of the conversation.is_mpim
represents an unnamed private conversation between multiple users. It's an is_private
kind of thing.is_org_shared
explains whether this shared channel is shared between Enterprise Grid workspaces within the same organization. It's a little different from (externally) Shared Channels. Yet, is_shared
will be true
.is_pending_ext_shared
is intriguing. It means the conversation is ready to become an is_ext_shared
channel but needs some kind of approval or sign off. Best to treat it as if it were a shared channel, even if it traverses only one workspace.is_private
means the conversation is privileged between two or more members. Meet their privacy expectations.is_read_only
means the conversation can't be written to by the user performing the API call.is_shared
means the conversation is in some way shared between multiple workspaces. Look for is_ext_shared
and is_org_shared
to learn which kind it is, and if that matters, act accordingly. Have we mentioned how great is_private
is yet?num_members
is, you guessed it, the number of members in the conversation. Note: num_members
might not make an appearance in the response for conversation types like DMs, where the number of members is constant.Discover who is party to a conversation with conversations.members
, a paginated method allowing you to safely navigate through very large (or tiny) collections of users.
Your app's scopes act as a filter. They sieve out the conversations you don't have access to, guaranteeing that Conversations API methods only return the conversations your app should see.
All Conversations API endpoints still accept multiple scopes and filter access to channels based on the provided token's scope. If you have a scope that allowed you to use a classic decomposed conversation method, that scope will work with the Conversations API equivalent.
For instance, conversations.list
accepts channels:read
, groups:read
, mpim:read
, and im:read
.
If you only have channels:read
, then conversations.list
will only return public channels and all the related methods will only deal with public channels. If you have both channels:read
and im:read
, then methods will only return public channels and DMs, and so on.
One exception: if you're developing a workspace app, you'll want to use the umbrella scopes below.
Workspace apps are deprecated
Legacy workspace apps are deprecated and will retire in August 2021. Learn more.
Workspace apps no longer need to request scopes for each individual type of conversation, like channels:read
and groups:read
. Now, each conversations
method has a matching conversations
scope that allows full use of the method. For instance, the conversations.list
method accepts the conversations:read
scope.
The only three scopes that workspace apps need to worry about in order to use the Conversations API are conversations:read
, conversations:history
, and conversations:write
.
For the time being, deprecated scopes like channels:read
will still work for workspace apps.
The Conversations API uses our cursor-based pagination model, improving the performance of requests over large sets of data. You could even walk through a list of channels 1-by-1 if you fancy.
Just set a limit
on your first request, include the next_cursor
found in response_metadata
in the response as the cursor
parameter in your next request and you're paginating with ease on the conversational trapeze.
Unlike older methods, the Conversations API is paginated by default.
Please keep in mind that it's possible to receive fewer results than your specified limit
, even when there are additional results to retrieve. Maybe you'll even receive 0 results but still have a next_cursor
with 4 more waiting in the wings.
When looking up MPIMs using the conversations.list
, you are likely to get far fewer results than requested number with a next_cursor
value, although next_cursor
will continue to indicate when more results await. e.g. When requesting 100 MPIMs, it may return only 5.
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.
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 formats may differ from other channel objects for a while. We're working towards making all objects the same format. You may notice members
lists that aren't meant to be there.
These are almost all cleared up!
When a channel becomes unshared, conversations.history
access for the channel may become unreliable.