Schedules a message to be sent to a channel.
POSThttps://slack.com/api/chat.scheduleMessage
application/x-www-form-urlencoded
application/json
token
Authentication token bearing required scopes. Tokens should be passed as an HTTP Authorization header or alternatively, as a POST parameter.
xxxx-xxxxxxxxx-xxxx
Channel, private group, or DM channel to send message to. Can be an encoded ID, or a name. See below for more details.
C1234567890
blocks
text
If attachments
or blocks
are also included, text
will be used as fallback text for notifications only.
A JSON-based array of structured attachments, presented as a URL-encoded string.
[{"pretext": "pre-hello", "text": "text-world"}]
blocks
A JSON-based array of structured blocks, presented as a URL-encoded string.
[{"type": "section", "text": {"type": "plain_text", "text": "Hello world"}}]
How this field works and whether it is required depends on other fields you use in your API call. See below for more detail.
Hello world
Set to true
to post the message as the authed user, instead of as a bot. Defaults to false. Cannot be used by new Slack apps. See chat.postMessage.
true
Find and link user groups. No longer supports linking individual users; use syntax shown in Mentioning Users instead.
true
JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you post to Slack is accessible to any app or user who is a member of that workspace.
{"event_type": "task_created", "event_payload": { "id": "11223", "title": "Redesign Homepage"}}
Used in conjunction with thread_ts
and indicates whether reply should be made visible to everyone in the channel or conversation. Defaults to false
.
true
Provide another message's ts
value to make this message a reply. Avoid using a reply's ts
value; use its parent instead.
Pass true to enable unfurling of primarily text-based content.
true
Bug alert
Messages scheduled with chat.scheduleMessage
will not post if the metadata
parameter is used.
This method schedules a message for delivery to a public channel, private channel, or direct message (DM, or IM) conversation at a specified time in the future.
Think of chat.scheduleMessage
and chat.postMessage
as two siblings in the Slack family. They aren't twins, but they still share many similarities, such as their ability to send messages and include various features like attachments and emojis.
text
, blocks
and attachments
fields The usage of the text
field changes depending on whether you're using blocks
. If you're using blocks
, this is used as a fallback string to display in notifications. If you aren't, this is the main body text of the message. It can be formatted as plain text, or with mrkdwn
.
You will only be able to schedule a message up to 120 days into the future. If you specify a post_at
timestamp beyond this limit, you’ll receive a time_too_far
error response. Additionally, you cannot schedule more than 30 messages to post within a 5-minute window to the same channel. Exceeding this will result in a restricted_too_many
error.
The response includes the scheduled_message_id
assigned to your message. Use it with the chat.deleteScheduledMessage
method to delete the message before it is sent.
For details on formatting, usage in threads, and rate limiting, check out chat.postMessage
documentation.
You must specify a public channel, private channel, or DM conversation with the channel
argument. Each one behaves slightly differently based on the authenticated user's permissions and additional arguments:
You can either pass the channel's name (#general
) or encoded ID (C123ABC456
), and the message will be posted to that channel. The channel's ID can be retrieved through the channels.list
API method.
Pass the DM conversation's channel ID (D123ABC456
) or a user's user ID (U123ABC456
) as the value of channel
to post to that DM conversation.
The DM conversation's channel ID can be retrieved through the conversations.list
API method. Use the types
parameters to return only im
conversations.
You might receive a channel_not_found
error if your app doesn't have permission to enter into an IM with the intended user.
Typical success response
{
"ok": true,
"channel": "C123ABC456",
"scheduled_message_id": "Q1298393284",
"post_at": "1562180400",
"message": {
"text": "Here's a message for you in the future",
"username": "ecto1",
"bot_id": "B123ABC456",
"attachments": [
{
"text": "This is an attachment",
"id": 1,
"fallback": "This is an attachment's fallback"
}
],
"type": "delayed_message",
"subtype": "bot_message"
}
}
Typical error response if the post_at
is invalid (ex. in the past or too far into the future)
{
"ok": false,
"error": "time_in_past"
}
This table lists the expected errors that this method could return. However, other errors can be returned in the case where the service is down or other unexpected factors affect processing. Callers should always check the value of the ok
params in the response.
Error | Description |
---|---|
channel_not_found | Value passed for |
is_archived | Channel has been archived. |
invalid_blocks | Blocks submitted with this message are not valid |
invalid_blocks_format | The |
invalid_metadata_format | Invalid metadata format provided |
invalid_metadata_schema | Invalid metadata schema provided |
invalid_time | value passed for |
message_limit_exceeded | Members on this team are sending too many messages. For more details, see https://slack.com/help/articles/115002422943-Usage-limits-for-free-workspaces |
metadata_must_be_sent_from_app | Message metadata can only be posted or updated using an app-level token |
metadata_too_large | Metadata exceeds size limit |
msg_too_long | Message text is too long |
no_text | No message text provided |
not_in_channel | Cannot post user messages to a channel they are not in. |
rate_limited | Application has posted too many messages, read the Rate Limit documentation for more information |
restricted_action | A workspace preference prevents the authenticated user from posting. |
restricted_action_non_threadable_channel | Cannot post thread replies into a non_threadable channel. |
restricted_action_read_only_channel | Cannot post any message into a read-only channel. |
restricted_action_thread_only_channel | Cannot post top-level messages into a thread-only channel. |
restricted_too_many | Too many messages were scheduled in the channel for a given period. See usage info for additional details |
slack_connect_file_link_sharing_blocked | Admin has disabled Slack File sharing in all Slack Connect communications |
time_in_past | value passed for |
time_too_far | value passed for |
too_many_attachments | Too many attachments were provided with this message. A maximum of 100 attachments are allowed on a message. |
invalid_token | The passed token is invalid or not supported by this method. |
access_denied | Access to a resource specified in the request is denied. |
account_inactive | Authentication token is for a deleted user or workspace when using a |
deprecated_endpoint | The endpoint has been deprecated. |
ekm_access_denied | Administrators have suspended the ability to post a message. |
enterprise_is_restricted | The method cannot be called from an Enterprise. |
invalid_auth | Some aspect of authentication cannot be validated. Either the provided token is invalid or the request originates from an IP address disallowed from making the request. |
method_deprecated | The method has been deprecated. |
missing_scope | The token used is not granted the specific scope permissions required to complete this request. |
not_allowed_token_type | The token type used in this request is not allowed. |
not_authed | No authentication token provided. |
no_permission | The workspace token used in this request does not have the permissions necessary to complete the request. Make sure your app is a member of the conversation it's attempting to post a message to. |
org_login_required | The workspace is undergoing an enterprise migration and will not be available until migration is complete. |
token_expired | Authentication token has expired |
token_revoked | Authentication token is for a deleted user or workspace or the app has been removed when using a |
two_factor_setup_required | Two factor setup is required. |
team_access_not_granted | The token used is not granted the specific workspace access required to complete this request. |
accesslimited | Access to this method is limited on the current network |
fatal_error | The server could not complete your operation(s) without encountering a catastrophic error. It's possible some aspect of the operation succeeded before the error was raised. |
internal_error | The server could not complete your operation(s) without encountering an error, likely due to a transient issue on our end. It's possible some aspect of the operation succeeded before the error was raised. |
invalid_arg_name | The method was passed an argument whose name falls outside the bounds of accepted or expected values. This includes very long names and names with non-alphanumeric characters other than |
invalid_arguments | The method was either called with invalid arguments or some detail about the arguments passed is invalid, which is more likely when using complex arguments like blocks or attachments. |
invalid_array_arg | The method was passed an array as an argument. Please only input valid strings. |
invalid_charset | The method was called via a |
invalid_form_data | The method was called via a |
invalid_post_type | The method was called via a |
missing_post_type | The method was called via a |
ratelimited | The request has been ratelimited. Refer to the |
request_timeout | The method was called via a |
service_unavailable | The service is temporarily unavailable |
team_added_to_org | The workspace associated with your request is currently undergoing migration to an Enterprise Organization. Web API and other platform operations will be intermittently unavailable until the transition is complete. |
This table lists the expected warnings that this method will return. However, other warnings can be returned in the case where the service is experiencing unexpected trouble.
Warning | Description |
---|---|
message_truncated | The |
missing_charset | The method was called via a |
superfluous_charset | The method was called via a |
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 java.io.IOException; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; public class ChatScheduleMessage { 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 app.command("/schedule", (req, ctx) -> { var logger = ctx.logger; var tomorrow = ZonedDateTime.now().truncatedTo(ChronoUnit.DAYS).plusDays(1).withHour(9); try { var payload = req.getPayload(); // Call the chat.scheduleMessage method using the built-in WebClient var result = ctx.client().chatScheduleMessage(r -> r // The token you used to initialize your app .token(ctx.getBotToken()) .channel(payload.getChannelId()) .text(payload.getText()) // Time to post message, in Unix Epoch timestamp format .postAt((int) tomorrow.toInstant().getEpochSecond()) ); // Print result logger.info("result: {}", result); } catch (IOException | SlackApiException e) { logger.error("error: {}", e.getMessage(), e); } // Acknowledge incoming command event return ctx.ack(); }); var server = new SlackAppServer(app); server.start(); } }
Code to initialize Bolt app// 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 });
// Unix timestamp for tomorrow morning at 9AM const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setHours(9, 0, 0); // Channel you want to post the message to const channelId = "C12345"; try { // Call the chat.scheduleMessage method using the WebClient const result = await client.chat.scheduleMessage({ channel: channelId, text: "Looking towards the future", // Time to post message, in Unix Epoch timestamp format post_at: tomorrow.getTime() / 1000 }); console.log(result); } catch (error) { console.error(error); }
Code to initialize Bolt appimport datetime 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__)
# Create a timestamp for tomorrow at 9AM tomorrow = datetime.date.today() + datetime.timedelta(days=1) scheduled_time = datetime.time(hour=9, minute=30) schedule_timestamp = datetime.datetime.combine(tomorrow, scheduled_time).strftime('%s') # Channel you want to post message to channel_id = "C12345" try: # Call the chat.scheduleMessage method using the WebClient result = client.chat_scheduleMessage( channel=channel_id, text="Looking towards the future", post_at=schedule_timestamp ) # Log the result logger.info(result) except SlackApiError as e: logger.error("Error scheduling message: {}".format(e))
POST https://slack.com/api/chat.scheduleMessage Content-type: application/json Authorization: Bearer xoxb-your-token { "channel": "YOUR_CHANNEL_ID", "text": "Hey, team. Don't forget about breakfast catered by John Hughes Bistro today.", "post_at": 1551891428, }