Modifying messages
We're still building and not all features are available quite yet. Enjoy this peek into the future!
Not ready for the future? Return to the past at api.slack.com.
A message captures a specific moment in time. But if you're an app, you might want to publish messages that communicate something that changes over time. Perhaps its the progress of a long running database request, or maybe just a message asking a user to wait for the response of an external API request.
In these cases and others, it's useful to have a way to modify messages from their original form. Slack apps are able to update and delete messages via APIs.
Updating messages
Any non-ephemeral message may possibly be updated by an app, by using the chat.update
method.
The process for using this API is largely the same as that for sending messages, but there are a few small differences:
- You can't move a message, so the
channel
parameter is used as an identifier for the target message to update, not as a way to update the conversation a message is in. - Ephemeral messages can't be updated in this way.
- An app can't just update every message in a conversation - only ones posted by the authenticated user of the token being used, including those posted as the app. The same applies to bot users, where you use a bot user token. Read the API reference for more information.
Updating messages using response_url
When a user interacts with an interactive element in a message, a payload containing a response_url
will be sent to the app that published the interactive message.
This response_url
can be used to publish new messages. It can also be used to update the original interactive message, regardless of whether it was an ephemeral message or not.
Read our interactive messages guide for more details on how to update messages using response_url
.
Deleting messages
The chat.delete
API method offers apps the powerful ability to delete messages, using the same permissions as those used to send messages:
- HTTP
- Java
- JavaScript
- Python
POST https://slack.com/api/chat.delete
Content-type: application/json
Authorization: Bearer xoxb-your-token
{
"channel": "PARENT_CHANNEL_ID",
"ts": "MESSAGE_TO_DELETE"
}
import com.slack.api.bolt.App;
import com.slack.api.bolt.AppConfig;
import com.slack.api.bolt.jetty.SlackAppServer;
import com.slack.api.methods.SlackApiException;
import com.slack.api.model.event.ReactionAddedEvent;
import java.io.IOException;
public class ChatDelete {
public static void main(String[] args) throws Exception {
var config = new AppConfig();
config.setSingleTeamBotToken(System.getenv("SLACK_BOT_TOKEN"));
config.setSigningSecret(System.getenv("SLACK_SIGNING_SECRET"));
var app = new App(config); // `new App()` does the same
// When a user reacts to a message with an X emoji, delete the message
app.event(ReactionAddedEvent.class, (req, ctx) -> {
var logger = ctx.logger;
try {
var event = req.getEvent();
// Only delete message if emoji is "x"
if (event.getReaction().equals("x")) {
// Call the chat.delete method using the built-in WebClient
var item = event.getItem();
var result = ctx.client().chatDelete(r -> r
// The token you used to initialize the app, stored in context
.token(ctx.getBotToken())
.channel(item.getChannel())
.ts(item.getTs())
);
logger.info("result: {}", result);
}
} catch (IOException | SlackApiException e) {
logger.error("error: {}", e.getMessage(), e);
}
return ctx.ack();
});
var server = new SlackAppServer(app);
server.start();
}
}
// 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
});
// The ts of the message you want to delete
const messageId = "12345.9876";
// The ID of the channel that contains the message
const channelId = "C12345";
try {
// Call the chat.delete method using the WebClient
const result = await client.chat.delete({
channel: channelId,
ts: messageId
});
console.log(result);
}
catch (error) {
console.error(error);
}
import logging
import os
# Import WebClient from Python 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__)
# The ts of the message you want to delete
message_id = "12345.9876"
# The ID of the channel that contains the message
channel_id = "C12345"
try:
# Call the chat.chatDelete method using the built-in WebClient
result = client.chat_delete(
channel=channel_id,
ts=message_id
)
logger.info(result)
except SlackApiError as e:
logger.error(f"Error deleting message: {e}")
The right for an app to delete a message depends on a few caveats:
- If using a standard user's user token, only messages posted by that user, or those posted as the app, may be deleted.
- If using a Workspace Admin user's user token, most messages in that workspace can be deleted.
- If using a bot user token, only messages posted by that bot user, or those posted as the app, may be deleted.
- Ephemeral messages can't be deleted in this way.
If the message has some threaded replies, then those replies will be left in the conversation, with a placeholder informing viewers about the deleted message:
Deleting messages using response_url
When a user interacts with an interactive element in a message, a payload containing a response_url
will be sent to the app that published the interactive message.
This response_url
can be used to publish new messages in response. It can also be used to delete the original interactive message, regardless of whether it was an ephemeral message or not.
Read our interactive messages guide for more details on how to delete messages using response_url
.