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.