Integrating with the Slack API is becoming an increasingly common task. Slack is the de facto communication platform for many companies, so there's a lot of demand for getting data from Node.js apps to Slack in realtime. In this article, I'll explain the basics of how to send a Slack message from Node.js.

Getting Started

There are two npm modules that I recommend for working with the Slack API: the official @slack/web-api module and the slack module written primarily by Brian LeRoux of WTFJS fame. I've also used node-slack in the past, but that module is fairly out of date. However, both @slack/web-api and slack are fairly thin wrappers around the Slack API, so, for the purposes of this article, we'll just use axios.

In order to make an API request to Slack, you need a Slack token. There are several types of Slack token, each with its own permissions. For example, an OAuth token lets you post messages on behalf of a user. But, for the purposes of this article, I'll be using bot user tokens. Bot user tokens let you post messages as a bot user, with a custom name and avatar, as opposed to as an existing user.

In order to get a bot user token, you first need to create a new Slack app. Make sure you set "Development Slack Workspace" to the Slack Workspace you want to use.

Next, go through the steps to create a bot user. You'll have to add scopes (permissions) to your bot user, and then install your app. First, make sure you add the following scopes to your bot user:

  • chat-write
  • chat-write.customize
  • chat-write.public

Once you've added the above scopes, click "Install App" to install this new Slack app to your workspace. Once you've installed the app, Slack will give you a bot user token:

Making Your First Request

To send a message to a Slack channel, you need to make an HTTP POST request to the https://slack.com/api/chat.postMessage endpoint with your Slack token in the authorization header. The POST request body must contain the channel you want to post to, and the text of your message.

Below is how you can send a 'Hello, World' message with Axios. Note that you must have a #test channel in your Slack workspace for the below request to work.

const axios = require('axios');

const slackToken = 'xoxb-YOUR-TOKEN_HERE';

run().catch(err => console.log(err));

async function run() {
  const url = 'https://slack.com/api/chat.postMessage';
  const res = await axios.post(url, {
    channel: '#test',
    text: 'Hello, World!'
  }, { headers: { authorization: `Bearer ${slackToken}` } });

  console.log('Done', res.data);
}

If the request is successful, the response will look something like what you see below:

{
  ok: true,
  channel: 'C0179PL5K8E',
  ts: '1595354927.001300',
  message: {
    bot_id: 'B017GED1UEN',
    type: 'message',
    text: 'Hello, World!',
    user: 'U0171MZ51E3',
    ts: '1595354927.001300',
    team: 'T2CA1AURM',
    bot_profile: {
      id: 'B017GED1UEN',
      deleted: false,
      name: 'My Test App',
      updated: 1595353545,
      app_id: 'A017NKGAKHA',
      icons: [Object],
      team_id: 'T2CA1AURM'
    }
  }
}

And you should see the below message show up in your #test channel.

Because of the chat-write.customize scope, this bot can customize the name and avatar associated with this message. For example, you can set the username and icon_emoji properties to customize the user your messages come from as shown below.

const res = await axios.post(url, {
  channel: '#test2',
  text: 'Hello, World!',
  username: 'Test App',
  icon_emoji: ':+1:'
}, { headers: { authorization: `Bearer ${slackToken}` } });

Below is how the above message looks in Slack.

More Sophisticated Features

You can send plain text messages, but Slack allows you to add formatting to messages using a custom formatting language called mrkdwn. Slack's mrkdwn language is conceptually similar to markdown. Most notably, mrkdwn supports code samples in much the same way markdown supports code snippets:

- `foo` with backticks makes "foo" an inline code block.
- Multi-line code blocks are fenced with three backticks ```

But there are also several important differences:

  • *foo* makes foo bold in mrkdwn, as opposed to italic in markdown. To make text italic in mrkdwn, you should do _foo_.
  • To make the substring "Google" link to https://www.google.com/ in mrkdwn, you need to write <https://www.google.com/|Google>
  • Mrkdwn does not support custom HTML. Any HTML is valid Markdown, but not mrkdwn.

For example, here's how you can send a message with some basic formatting, including a code block.

const url = 'https://slack.com/api/chat.postMessage';

const text = `
Check out this *cool* function!

\`\`\`
${hello.toString()}
\`\`\`
`;

const res = await axios.post(url, {
  channel: '#test',
  text,
  username: 'Test App',
  icon_emoji: ':+1:'
}, { headers: { authorization: `Bearer ${slackToken}` } });

Here's what the above message looks like:

Slack also supports more sophisticated layouts via blocks. Instead of specifying a message's text, you can specify a blocks array. There are several different types of blocks, including a generic section block and an image block for pictures.

For example, below is a simplified example of sending a notification that a new order came in to an eCommerce platform, including a qr code image.

const res = await axios.post(url, {
  channel: '#test',
  blocks: [
    {
      type: 'section',
      text: { type: 'mrkdwn', text: 'New order!' },
      fields: [
        { type: 'mrkdwn', text: '*Name*\nJohn Smith' },
        { type: 'mrkdwn', text: '*Amount*\n$8.50' },
      ]
    },
    {
      type: 'image',
      image_url: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/QR_code_for_mobile_English_Wikipedia.svg/1200px-QR_code_for_mobile_English_Wikipedia.svg.png',
      alt_text: 'qrcode'
    }
  ],
  username: 'Test App',
  icon_emoji: ':+1:'
}, { headers: { authorization: `Bearer ${slackToken}` } });

Below is what the above message looks like in Slack.

Moving On

Once you get a bot token, working with the Slack API from Node.js is fairly straightforward. You can send neatly formatted messages to Slack to notify them of events they might be interested in, whether they be coworkers at your company or clients using one of your products.

Found a typo or error? Open up a pull request! This post is available as markdown on Github
comments powered by Disqus