This guide is for developers who've never followed a Slack app recipe before. We'll teach you how to cook up a Slack app from scratch.

If you're an experienced chef, already familiar with seasons of Slack apps past, check out this guide that explains exactly what new ingredients have arrived to apps.

By the end of this guide, your app will be poised to post messages, respond to mentions, and use classic recipes like Slash commands and incoming webhooks.

Let's get cooking, starting with the first ingredient: creating an app.

Creating an app

If you haven't already, create a Slack app with our UI:

Create a Slack app

Fill out your App Name and select the Development Workspace where you'll play around and build your app. Don't fuss too much over either field—no matter what workspace you select, you'll still be able to distribute your app to other workspaces if you choose.

If you need to update the name of your app later, you can do so in the following places:

Changing the app name under Settings > Basic Information will update the bot name rather than the app name; this change applies to the name that appears when the app performs actions such as posting in a channel or sending a DM.

Requesting scopes

Preheat the oven and ready your app for action by requesting scopes. Scopes give your app permission to do things (for example, post messages) in your development workspace.

You can select the scopes to add to your app by heading over to the OAuth & Permissions sidebar.

Scroll down to the Scopes section and click to Add an OAuth Scope.

To allow your app to post messages, add the chat:write scope to your Bot Token.

While you're at it, add the channels:read scope too so your app can gain knowledge about public Slack channels.

If you're confused about the difference between adding a Bot Token Scope or a User Token Scope, worry not:

Add scopes to your Bot Token, not your User Token.

One notable exception to that rule is if you need to act as a specific user (for example, posting messages on behalf of a user, or setting a user's status). In that situation, you'll need a User Token.

Modern Slack apps may not access RTM
For most apps, the Events API lets your app listen to Slack goings-on in a more structured, safe way. If you require access to RTM (say, because you're building your app behind a corporate firewall), you'll need to create a classic Slack app and use its bot token to call rtm.connect:

Create a classic Slack app

Otherwise, it's bot tokens all the way down.

Installing the app to a workspace

Sure, you can request any scope you want—but final say always resides with the user installing your app. Like a picky eater, a user can choose to refuse any and all installs that seem to request permissions beyond what an app truly needs.

Try it out! Install your own app by selecting the Install App button on the sidebar.

After clicking through one more green Install App To Workspace button, you'll be sent through the Slack OAuth UI.

New Oauth UI for users

Here's a potentially confusing bit: when you follow this flow with Slack, you're playing the part of the installing user—the picky eater—not the app! If you were adding your app to a different workspace besides your development workspace, this flow would be completed by a user from that workspace, not you.

As a user, you're choosing to trust the app. Is it trustworthy? Well, you just built it—hopefully, it's not too bad.

Getting your authentication token

After installation, you'll find an access token inside your app management page. Look for it under the OAuth & Permissions sidebar.

Access tokens are imbued with power. They represent the permissions delegated to your app by the installing user. Remember to keep your access token secret and safe, to avoid violating the trust of the installing user.

At a minimum, avoid checking your access token into public version control. Access it via an environment variable. We've also got plenty more best practices for app security.

Calling API methods

Your access token allows you to call the methods described by the scopes you requested during installation.

For example, your chat:write scope now allows your app to post messages. Your app probably isn't a member of any channels yet, so pick a channel you don't mind adding some test messages to and /invite your app.

You can find the corresponding id for the channel that your app just joined by looking through the results of the conversations.list method:

curl https://slack.com/api/conversations.list -H "Authorization: Bearer xoxb-1234..."

You'll receive a list of conversation objects.

Now, post a message to the same channel your app just joined with the chat.postMessage method:

curl -X POST -F channel=C1234 -F text="Reminder: we've got a softball game tonight!" https://slack.com/api/chat.postMessage -H "Authorization: Bearer xoxb-1234..."

Voila! We're already well on our way to putting a full-fledged Slack app on the table.

Slack Softball Team app message

Want more tips on cooking up the perfect API call? Check out the Web API guide for some technical tricks.

If you just want to see all the different methods you can call, check out the methods list. If you select any method, you'll see exactly what parameters the method takes, plus additional bits of knowledge. Think of the methods list as the Slack API cookbook.

Posting in public channels

Slack apps do not begin life with the ability to post to any public channel without joining.

Good news: apps can gain that ability by asking for them explicitly with the use of scopes.

Request the chat:write.public scope to gain the ability to post in all public channels, without joining. Otherwise, you'll need to use conversations.join, or have your app invited by a user into a channel, before you can post.

Customizing message authorship

Slack apps also do not start with the ability to adjust username or icon when posting messages—that is, message authorship.

You can adjust your app's message authorship with the help of the chat:write.customize scope. Once you've requested the scope, you can make use of the username, icon_url, and icon_emoji parameters in chat.postMessage.

Listening for events

One fundamental pattern of Slack apps is listening and responding.

We've already touched on one way an app can respond: by calling chat.postMessage to post a message.

But our app isn't a very good listener yet. An app that speaks without being prompted can be distracting at best and outright disruptive at worst.

Apps always respond to something. It might be a mention in channel, a button pushed to trigger an action, even a user entering into a DM with the app. But apps never act for no reason.

Apps listen with the Events API. Events are just what you'd expect: notifications, sent to your app, about happenings in Slack. Each type of event lets your app know about a certain type of happening.

Let's subscribe to the app_mention event. Select the Event Subscriptions sidebar and toggle "Enable Events" on. Within Subscribe to bot events click Add Bot User Event, then search for app_mention.

As with scopes, always subscribe to events with a bot user, unless only a user token will do.

Set the Request URL to a URL where your app's server listens to incoming HTTP requests. Slack will send an HTTP request there when your app is mentioned, allowing your app to figure out how it wants to respond.

If setting a server up makes you nervous, you may want to explore the Bolt SDKs, which implement a server listening for events automatically.

You'll notice that the app_mention event requires the app_mention:read scope. Events are like API methods: they allow your app access to info in Slack, so you need permission for them. Reinstall your app with the new scope.

Now you'll be notified when your app is mentioned, and you can respond however you like:

Slack Softball Team app call and response

Using Slash commands and Incoming Webhooks

Slack apps can still use beloved recipes passed down through the family: Slash commands and Incoming Webhooks.

Request the commands scope to build a Slash command. Request the incoming-webhook scope to use Incoming Webhooks. Both features act exactly the way they did for classic Slack apps, with one big exception:

Slash commands and Incoming Webhooks are now tied to your bot user and bot token, not a user. That means you're safe from unexpected uninstalls if the user who builds a command or webhook leaves the workspace!

Slack apps do not support Slash commands or Incoming Webhooks on a user token. They can only be obtained by the app's bot user.

Handling link unfurling

You can request the links:read and links:write scopes so that your app can handle unfurls.

A link shared in a channel will only be unfurled if the token with links:write has access to the message that contains the link. For example, if an installing user shares a link to a private channel, but the Slack app is not in that private channel, that link will not unfurl.

Where to go next

Cooking is a life-long pursuit, and Slack apps have the same complexity. From here, you can go on to build mouth-watering interactive workflows; spice up your sentences with Block Kit; even pursue building for larger Enterprise Grid organizations, which contain multiple workspaces.

You can even submit Slack apps to the app directory and share your creations with others!