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

Slash Commands

Slash Commands enable Slack users to interact with your app directly from Slack.

A slash commmand at work!

What are commands?

Messages that begin with a slash (/) are commands and will behave differently from regular messages. For example, you can use the "topic" command to change your current channel's topic to "Hello!" by typing /topic Hello!. When you type /remind me in 10 minutes to drink a glass of water the command will set a reminder for you to drink a glass of water in 10 minutes.

Under the hood, there are at least 3 different kinds of commands. They work similarly, but are useful for different reasons.

Built-in Commands

Commands like /topic and /remind are built into Slack, and available to every team. They often work as shortcuts for doing something related to your channel or Slack team quickly from the message input field. Here's a list of all of the built-in commands and descriptions about what they do. Give them a try!

Slack App Commands

These are slash commands written by developers like you! They typically trigger an action (like posting a gif, or starting a video conference, or adding something new to your todo list).

As part of a Slack app, they can be easily installed for your team as an internal integration or shared with the world, distributed to other teams.

When a slash command is invoked, Slack sends your server a HTTP POST of data describing the user's invocation.

In order to protect team data, commands installed as part of a distributed Slack app must use HTTPS for their command invocation URL. When building an internal integration for your own team, SSL verification is waived. We also provide a means to verify the request is coming from Slack.

Once your server receives the invocation, it may post a message in response. Any posted messages will originate from your application's identity.

Custom commands

Another way to use slash commands is as part of a legacy custom integration. We recommend building your commands as part of a Slack app instead.

How do commands work?

Triggering a command

When someone types a slash command, the message (and its data) will be sent to the configured external URL via HTTP POST. It's up to you, the developer, to do something with the message data and respond back, if desired.

For example, imagine that there's an app command installed called /weather. If someone on the team types /weather 94070 in the #test channel and hits enter, this data would be posted to the external URL:


Typically, this data will be sent to your URL as a HTTP POST with a Content-type header set as application/x-www-form-urlencoded. If you've chosen to have your slash command's URL receive invocations as a GET request, no explicit Content-type header will be set.

NOTE: If your Slack app is set to be distributable or is part of the Slack app directory, the URL you provide must be use HTTPS with a valid, verifiable SSL certificate. Self-signed certificates cannot be used. See below for more information.

Resolving mentioned user IDs, channel IDs, and URLs

Let's say your slash command was about assigning tasks to a user within a channel. @bert might decide to assign @ernie a task like so:

/task @ernie don't wake me up at night anymore in #here

In the above example, your received text parameter would look like this (though properly URL encoded)

text=@ernie don't wake me up at night anymore in #here

The important part of that URL-encoded value, and somewhat useless to you on its own is: @ernie. That's a username mention.

But to actually address that as any kind of unique entity on the team you're working with, you really want to work with a user ID, not the username. Of course, you'd also like to know that the channel named #here is actually the one with the ID C012ABCDE.

Until just recently, you'd have had to make do with that username and look it up against users.list or other means. Same with the channel name and channels.list.

But now there is another way.

Configure your slash command to receive expanded entity references

When configuring your slash command, you'll find a toggle that enables this translation of channel names and user names into their correlated IDs. It's labeled: Escape channels, users, and links sent to your app.

After toggling this feature to "on", you'll find that the Bert's equivalent text parameter becomes:

text=<@U012ABCDEF|ernie> don't wake me up at night anymore in <#C012ABCDE|here>

Note the angle brackets (< and cousin >) surrounding each tokenized entity. This is strikingly similar to how we format mentions in messages.

What about links?

There's nothing too special about links. Instead of the naked URL just appearing in the string of text, it'll be surrounded with angle brackets. So your URL becomes <>.

Validating the command

When your server receives the above data, you should validate whether to service the request by confirming that the token value matches the validation token you received from Slack when creating the command. The token is available in the "Basic information" section of your app's configuration. It's not the same token as the one used to submit Web API requests, but instead a kind of shared secret.

A slash command validation code

Additionally, you can verify whether the team_id matches a team that has approved your command for usage.

If the token or team are unknown to your application, you should refuse to service the request and return an error instead.

Responding to a command

When the external URL receives this data, you have a few different options for how to respond.

If you'd like to just return information in the simplest possible way, it can respond immediately (within 3000 milliseconds) with a plain text string:

It's 80 degrees right now.

Default command response - plain text, visible only to user who issued the command

If you'd like to customize the appearance of the response message with extra message formatting or attachment fields, you can respond immediately (within 3000 milliseconds) with a valid JSON payload:

    "text": "It's 80 degrees right now.",
    "attachments": [
            "text":"Partly cloudy today and tomorrow"

Your URL should respond with a HTTP 200 "OK" status code. Any other flavor of response will result in a user-facing error.

If you don't want to respond with any message or would rather send your responses later using delayed responses, you should still respond to the invocation of your URL with a simple HTTP 200.

That said, we strongly recommend that you send some kind of positive affirmation to the user as an ephemeral response, even if it's just a simple confirmation that the command was understood.

If you are responding with JSON instead of plain text, the Content-type header of the response must match the disposition of your content, application/json.

"In Channel" vs "Ephemeral" responses

By default, the response messages sent to commands will only be visible to the user that issued the command (we call these "ephemeral" messages). However, if you would like the response to be visible to all members of the channel in which the user typed the command, you can add a response_type of in_channel to the JSON response, like this:

    "response_type": "in_channel",
    "text": "It's 80 degrees right now.",
    "attachments": [
            "text":"Partly cloudy today and tomorrow"

When the response_type is in_channel, both the response message and the initial message typed by the user will be shared in the channel. It will look like this:

Example of a command in channel response

Setting response_type to ephemeral is the same as not including the response type at all, and the response message will be visible only to the user that issued the command. For the best clarity of intent, we recommend always declaring your intended response_type.

Example of a command ephemeral response

Delayed responses and multiple responses

If you want to provide additional command response messages, or if you're unable to immediately respond to a command within 3000 milliseconds, use the specific response_url we send with our initial execution of your URL to respond to a command at your leisure. With this approach, you can respond to a user's command up to 5 times within 30 minutes of the command's invocation.

Sending HTTP requests to this response_url is easy. Just build a JSON POST body in the same format as used when responding to our command invocation request to your registered URL. It supports all of the same fields (response_type, text, and attachments). Then, send that data as an HTTP POST with a content-type of application/json to the destination specified as the response_url.

The only user-facing difference between immediate responses and delayed responses is that "in channel" delayed responses will not include the initial command sent by the user. To echo the command back to the channel, you'll still need to provide a response to Slack's original visit to your invocation URL.

Making slash commands more interactive with message buttons

Slash commands that are installed as part of a Slack app are also able to use message buttons to drive interactive workflows with precision and clarity.

When responding to a command invocation or executing a response_url, include your message button actions as attachments to your message.

Responding to the user with an error message

If you would like to let the user know that something went wrong, you can return an ephemeral response containing a helpful error message. To do this, you can either respond directly to the slash command request, or use the provided response_url.

You'll want to send a JSON payload that looks like this:

  "response_type": "ephemeral",
  "text": "Sorry, that didn't work. Please try again."

Best practices

  • If you're not ready to respond to an incoming command but still want to acknowledge the user's action by having their slash command displayed within the channel, respond to your URL's invocation with a simplified JSON response containing only the response_type field set to in_channel: {"response_type": "in_channel"}.
  • If your command doesn't need to post anything back (either privately or publicly), respond with an empty HTTP 200 response. Best to use this only if the nature of your command makes it obvious that no response is necessary or desired. Even a simple "Got it!" ephemeral response is better than nothing.
  • Help your users understand how to use your command. Provide a help action that explains your command's usage. If your slash command was /please, you should provide a response to /please help that lists the other actions available.
  • Keep track of the validation token Slack gives you when the command is created. Always validate the token field in an incoming slash command request has been issued to you by Slack.
  • Limit yourself to 20 attachments per message. We'll be unable to process messages with more than 100.
  • Turn on entity resolution for usernames, channels, and links by flipping the toggle in your slash command's configuration dialog. Always work with user IDs and channel IDs.
  • If you're using message buttons or attachments, be sure and follow our guidelines.

Consult our Slash Commands Style Guide for further tips!


Slash commands that are part of a Slack app set in "distributed mode" must support HTTPS and serve a valid SSL certificate. Self-signed certificates are not allowed. Check out CloudFlare or Let's Encrypt for easy ways to obtain valid certificates.

Before submitting a command to your server, Slack will occasionally send your command URLs a simple POST request to verify the certificate. These requests will include a parameter ssl_check set to 1. Mostly, you may ignore these requests, but please do respond with a HTTP 200 OK.

Setting up your slash command

Create a Slack app by visiting app management while logged in. After naming your app, make sure to add the Slash commands feature to your app before installing. The shared secret verification token is available in the "Basic information" section of your app's configuration.