SOLFIND
Web Lens
Portal home

Retrieving messages | Slack Developer Docs

https://docs.slack.dev/messaging/retrieving-messages/ • 213 KB fetched
Open original page


Retrieving messages | Slack Developer Docs guide Skip to main content Guides Reference Samples Tools Changelog Dev Program MANAGE APPS * Welcome! * Quickstart * Resources * * Slack platform concepts * AI in Slack * APIs * App management * App manifests * Admin resources * Authentication * Block Kit * Enterprise * Enterprise Search for apps * GovSlack * Interactivity * Messaging * Overview * Creating interactive messages * Formatting message text * Modifying messages * Sending and scheduling messages * Sending messages using incoming webhooks * Retrieving messages * Working with files * Migrating outmoded message compositions to blocks * Message metadata * Work Objects * Unfurling links in messages * Slack Marketplace * Surfaces * Workflows * * Legacy * * 日本語版ページ * * Messaging * Retrieving messages Copy as markdown On this page Retrieving messages Slack apps tend to encounter messages most often when receiving them in Events API payloads or in request payloads when users invoke slash commands or custom actions . However, there are some occasions where it might be necessary for an app to actively seek out a message and find it in the wild. This guide will show you how to access the history of a Slack conversation and then pull out the details of a specific message. It will also show you how to identify threaded messages and retrieve the replies in a thread. Before you begin ​ You'll need a Slack app if you don't already. Here's a quick guide to help you create one . Make sure you create the app in a test workspace, because you're going to be requesting some major data access permissions. Once you've done that, come back here. Requesting the necessary permissions ​ In a raw state, your app will only be able to view messages that are sent to it. In order to read anything else, it will need to request scopes to get permission . There are lots of scopes available , and you can read our OAuth guide for more information on why they're needed, and what they do. For this guide, we need to add two scopes: * channels:read . This scope lets your app retrieve a list of all the public channels in a workspace so that we can pick one to retrieve a message from . * channels:history . This scope lets your app view all the messages within any public channel in a workspace. You can add these scopes to your app like so: * Open the settings for your app from the App Management page. * In the navigation menu, select OAuth & Permissions . * Scroll down to the Scopes section, and pick channels:read and channels:history from the drop down menu. * Click Save changes . * Scroll back to the top of this page and look for the button that says Install App to Workspace (or Reinstall App if you've done this before). Click it. You'll now see a permission request screen to install your app to its original workspace. If you had already installed your app to its original workspace before, you might still see the permissions screen if the scopes you just added weren't previously granted to your app. Authorize your app and you should see a success message. On the OAuth & Permissions settings page you're brought back to, you should now see an OAuth access token available. Grab this token and store it for later, as we'll use that token to make some Web API calls. Finding a conversation ​ In order to find a valid Slack conversation ID, we'll use the conversations.list method. This API will return a list of all public channels in the workspace your app is installed to. You'll need the channels:read scope granted to your app. Within that list, we'll be able to find a specific id of the conversation that we want to access. Here's an example API call: * HTTP * Java * JavaScript * Python GET https://slack.com/api/conversations.list Authorization: Bearer xoxb-your-token import com . slack . api . Slack ; import com . slack . api . methods . SlackApiException ; import com . slack . api . model . Conversation ; import org . slf4j . LoggerFactory ; import java . io . IOException ; public class FindingConversation { /** * Find conversation ID using the conversations.list method */ static void findConversation ( String name ) { // you can get this instance via ctx.client() in a Bolt app var client = Slack . getInstance ( ) . methods ( ) ; var logger = LoggerFactory . getLogger ( "my-awesome-slack-app" ) ; try { // Call the conversations.list method using the built-in WebClient var result = client . conversationsList ( r -> r // The token you used to initialize your app . token ( System . getenv ( "SLACK_BOT_TOKEN" ) ) ) ; for ( Conversation channel : result . getChannels ( ) ) { if ( channel . getName ( ) . equals ( name ) ) { var conversationId = channel . getId ( ) ; // Print result logger . info ( "Found conversation ID: {}" , conversationId ) ; // Break from for loop break ; } } } catch ( IOException | SlackApiException e ) { logger . error ( "error: {}" , e . getMessage ( ) , e ) ; } } public static void main ( String [ ] args ) throws Exception { // Find conversation with a specified channel `name` findConversation ( "tester-channel" ) ; } } // Require the Node Slack SDK package (github.com/slackapi/node-slack-sdk) const { WebClient , LogLevel } = require ( "@slack/web-api" ) ; // WebClient instantiates a client that can call API methods // When using Bolt, you can use either `app.client` or the `client` passed to listeners. const client = new WebClient ( "xoxb-your-token" , { // LogLevel can be imported and used to make debugging simpler logLevel : LogLevel . DEBUG } ) ; // Find conversation ID using the conversations.list method async function findConversation ( name ) { try { // Call the conversations.list method using the built-in WebClient const result = await app . client . conversations . list ( { // The token you used to initialize your app token : "xoxb-your-token" } ) ; for ( const channel of result . channels ) { if ( channel . name === name ) { conversationId = channel . id ; // Print result console . log ( "Found conversation ID: " + conversationId ) ; // Break from for loop break ; } } } catch ( error ) { console . error ( error ) ; } } // Find conversation with a specified channel `name` findConversation ( "tester-channel" ) ; import logging import os # Import WebClient from Python Slack SDK (github.com/slackapi/python-slack-sdk) from slack_sdk import WebClient from slack_sdk . errors import SlackApiError # WebClient instantiates a client that can call API methods # When using Bolt, you can use either `app.client` or the `client` passed to listeners. client = WebClient ( token = os . environ . get ( "SLACK_BOT_TOKEN" ) ) logger = logging . getLogger ( __name__ ) channel_name = "needle" conversation_id = None try : # Call the conversations.list method using the WebClient for result in client . conversations_list ( ) : if conversation_id is not None : break for channel in result [ "channels" ] : if channel [ "name" ] == channel_name : conversation_id = channel [ "id" ] #Print result print ( f"Found conversation ID: { conversation_id } " ) break except SlackApiError as e : print ( f"Error: { e } " ) You'll get back a JSON object, with a channels array containing all the public channels that your app can see. You can find your channel by looking for the name in each object. When you've found the matching channel, make note of the id value, as you'll need it for certain API calls. If your app implements shortcuts , slash commands , or uses the Events API , your app will see conversation id s in request payloads sent by those features. In those cases, your app can dynamically respond using the payload data to identify the relevant conversation, rather than needing to use the conversations.list method described above. Retrieving conversation history ​ With the information you just collected and your previously generated token, we can make another Web API call to conversations.history : * HTTP * Java * JavaScript * Python GET https://slack.com/api/conversations.history Authorization: Bearer xoxb-your-token { "channel": "YOUR_CONVERSATION_ID", "latest": "YOUR_TS_VALUE", "limit": 1, "inclusive": true } // Require the Node Slack SDK package (github.com/slackapi/node-slack-sdk) const { WebClient , LogLevel } = require ( "@slack/web-api" ) ; // WebClient instantiates a client that can call API methods // When using Bolt, you can use either `app.client` or the `client` passed to listeners. const client = new WebClient ( "xoxb-your-token" , { // LogLevel can be imported and used to make debugging simpler logLevel : LogLevel . DEBUG } ) ; // Store message let message ; // Fetch conversation history using the ID and a TS from the last example async function fetchMessage ( id , ts ) { try { // Call the conversations.history method using the built-in WebClient const result = await app . client . conversations . history ( { // The token you used to initialize your app token : "xoxb-your-token" , channel : id , // In a more realistic app, you may store ts data in a db latest : ts , // Limit results inclusive : true , limit : 1 } ) ; // There should only be one result (stored in the zeroth index) message = result . messages [ 0 ] ; // Print message text console . log ( message . text ) ; } catch ( error ) { console . error ( error ) ; } } // Fetch message using a channel ID and message TS fetchMessage ( "C12345" , "15712345.001500" ) ; import logging import os # Import WebClient from Python Slack SDK (github.com/slackapi/python-slack-sdk) from slack_sdk import WebClient from slack_sdk . errors import SlackApiError # WebClient instantiates a client that can call API methods # When using Bolt, you can use either `app.client` or the `client` passed to listeners. client = WebClient ( token = os . environ . get ( "SLACK_BOT_TOKEN" ) ) logger = logging . getLogger ( __name__ ) # ID of channel that the message exists in conversation_id = "C01JASD6802" try : # Call the conversations.history method using the WebClient # The client passes the token you included in initialization result = client . conversations_history ( channel = conversation_id , inclusive = True , oldest = "1610144875.000600" , limit = 1 ) message = result [ "messages" ] [ 0 ] # Print message text print ( message [ "text" ] ) except SlackApiError as e : print ( f"Error: { e } " ) Dropping in your token and id values, this method will return a list of a list of messages and events within the chosen conversation. The method's reference contains example responses and some explanations of the data included within. The important part for this guide is the messages array, which contains every message in the conversation. For the next part of the guide, you need to grab the ts value of one of these message objects; we'll explain why in a second. Retrieving individual messages ​ The structure of message objects retrieved via Slack APIs is very similar to the general structure of a message payload you want to publish . There are a few additional fields that describe the author (such as user or bot_id ), but there's also an additional ts field. The ts value is essentially the ID of the message, guaranteed unique within the context of a channel or conversation. They look like UNIX/epoch timestamps, hence ts , with specified milliseconds. But they're actually message IDs, even if they're partially composed in seconds-since-the-epoch. The ts of a message can be used in many operations such as replying to it in a thread , or modifying the message . But it can also be used to retrieve the message by itself. Using the ts from the previous step with the information previously collected, and your token, we can make a slightly different call to conversations.history : * HTTP * Java * JavaScript * Python GET https://slack.com/api/conversations.history Authorization: Bearer xoxb-your-token { channel: "CONVERSATION_ID_HERE" } import com . slack . api . Slack ; import com . slack . api . methods . SlackApiException ; import com . slack . api . model . Message ; import org . slf4j . LoggerFactory ; import java . io . IOException ; import java . util . List ; import java . util . Optional ; import static java . util . Collections . emptyList ; public class ConversationsHistory { static Optional < List < Message > > conversationHistory = Optional . empty ( ) ; /** * Fetch conversation history using ID from last example */ static void fetchHistory ( String id ) { // you can get this instance via ctx.client() in a Bolt app var client = Slack . getInstance ( ) . methods ( ) ; var logger = LoggerFactory . getLogger ( "my-awesome-slack-app" ) ; try { // Call the conversations.history method using the built-in WebClient var result = client . conversationsHistory ( r -> r // The token you used to initialize your app . token ( System . getenv ( "SLACK_BOT_TOKEN" ) ) . channel ( id ) ) ; conversationHistory = Optional . ofNullable ( result . getMessages ( ) ) ; // Print results logger . info ( "{} messages found in {}" , conversationHistory . orElse ( emptyList ( ) ) . size ( ) , id ) ; } catch ( IOException | SlackApiException e ) { logger . error ( "error: {}" , e . getMessage ( ) , e ) ; } } public static void main ( String [ ] args ) throws Exception { fetchHistory ( "C24601" ) ; } } // Require the Node Slack SDK package (github.com/slackapi/node-slack-sdk) const { WebClient , LogLevel } = require ( "@slack/web-api" ) ; // WebClient instantiates a client that can call API methods // When using Bolt, you can use either `app.client` or the `client` passed to listeners. const client = new WebClient ( "xoxb-your-token" , { // LogLevel can be imported and used to make debugging simpler logLevel : LogLevel . DEBUG } ) ; // Store conversation history let conversationHistory ; // ID of channel you watch to fetch the history for let channelId = "C24601" ; try { // Call the conversations.history method using WebClient const result = await client . conversations . history ( { channel : channelId } ) ; conversationHistory = result . messages ; // Print results console . log ( conversationHistory . length + " messages found in " + channelId ) ; } catch ( error ) { console . error ( error ) ; } import logging import os # Import WebClient from Python Slack SDK (github.com/slackapi/python-slack-sdk) from slack_sdk import WebClient from slack_sdk . errors import SlackApiError # WebClient instantiates a client that can call API methods # When using Bolt, you can use either `app.client` or the `client` passed to listeners. client = WebClient ( token = os . environ . get ( "SLACK_BOT_TOKEN" ) ) logger = logging . getLogger ( __name__ ) # Store conversation history conversation_history = [ ] # ID of the channel you want to send the message to channel_id = "C123ABC456" try : # Call the conversations.history method using the WebClient # conversations.history returns the first 100 messages by default # These results are paginated, see: /methods/conversations.history$pagination result = client . conversations_history ( channel = channel_id ) conversation_history = result [ "messages" ] # Print results logger . info ( "{} messages found in {}" . format ( len ( conversation_history ) , channel_id ) ) except SlackApiError as e : logger . error ( "Error creating conversation: {}" . format ( e ) ) You can read the conversations.history reference for a more in-depth explanation of what these additional parameters do, but essentially we're telling the API to return one result from the conversation's history, using the message ts as a starting point. Other encounters with individual messages ​ As we mentioned before, your app is likely to encounter individual messages in ways other than a direct retrieval. If you subscribe to certain Events API types, you will receive a notification payload from each event that may contain a message object. For example, the app_mention event will be sent whenever someone mentions your app in a message, and that source message will be included in the notification payload. After you publish a message , you'll receive an API response that will include a message object containing the newly-created message. Slash commands and custom actions both send similar request payloads when a user invokes them in Slack. Those payloads contain a message object that describes the source message of the invocation. Interactive components in messages will also send request payloads when the components are used. Again, these payloads will contain a message object that describes the source of the interaction. In all of the above cases, the structure of the message object is similar to that outlined above . Read the relevant individual guides to see examples of the kinds of payloads or responses your app will receive. Threaded messages ​ We've explained the basics behind threaded messages elsewhere (familiarize yourself with our terminology if you haven't already, because it can get tangled), but how do you know when the message you've received or retrieved is part of a thread? And if you have a parent message, how do you retrieve all the replies to it? Read on to find out. Spotting threads ​ There's a few steps involved with spotting a thread and then understanding the context of a message within it. Let's unspool them: * Detect a threaded message by looking for a thread_ts value in the message object. The existence of such a value indicates that the message is part of a thread. * Identify parent messages by comparing the thread_ts and ts values. If they are equal , the message is a parent message. * Threaded replies are also identified by comparing the thread_ts and ts values. If they are different , the message is a reply. One quirk of threaded messages is that a parent mess

Links found on this page

  1. Skip to main content [direct]
  2. Guides [direct]
  3. Reference [direct]
  4. Samples [direct]
  5. Tools [direct]
  6. Changelog [direct]
  7. Dev Program [direct]
  8. MANAGE APPS [direct]
  9. Quickstart [direct]
  10. Resources [direct]
  11. Slack platform concepts [direct]
  12. AI in Slack [direct]
  13. APIs [direct]
  14. App management [direct]
  15. App manifests [direct]
  16. Admin resources [direct]
  17. Authentication [direct]
  18. Block Kit [direct]
  19. Enterprise [direct]
  20. Enterprise Search for apps [direct]
  21. GovSlack [direct]
  22. Interactivity [direct]
  23. Messaging [direct]
  24. Creating interactive messages [direct]
  25. Formatting message text [direct]
  26. Modifying messages [direct]
  27. Sending and scheduling messages [direct]
  28. Sending messages using incoming webhooks [direct]
  29. Retrieving messages [direct]
  30. Working with files [direct]
  31. Migrating outmoded message compositions to blocks [direct]
  32. Message metadata [direct]
  33. Work Objects [direct]
  34. Unfurling links in messages [direct]
  35. Slack Marketplace [direct]
  36. Surfaces [direct]
  37. Workflows [direct]
  38. Legacy [direct]
  39. 日本語版ページ [direct]
  40. Events API [direct]
  41. slash commands [direct]
  42. custom actions [direct]
  43. Here's a quick guide to help you create one [direct]
  44. request scopes to get permission [direct]
  45. lots of scopes available [direct]
  46. channels:read [direct]
  47. channels:history [direct]
  48. Web API [direct]
  49. conversations.list [direct]
  50. conversations.history [direct]
  51. general structure of a message payload you want to publish [direct]
  52. app_mention [direct]
  53. send request payloads [direct]
  54. conversations.replies [direct]
  55. Slack CLI [direct]
  56. Bolt frameworks [direct]
  57. Block Kit Builder [direct]
  58. Code samples & tutorials [direct]
  59. LLM? Read llms.txt [direct]
  60. Learning paths [direct]
  61. Workshops [direct]
  62. Slack certifications [direct]
  63. Trailhead [direct]
  64. Resource library [direct]
  65. All learning resources [direct]
  66. Slack community [direct]
  67. Slack events [direct]
  68. Blog [direct]
  69. Slack marketplace [direct]
  70. Developer newsletter [direct]
  71. Status [direct]
  72. Privacy [direct]
  73. Terms [direct]
  74. Your Privacy Choices [direct]