Fun with APIs: Building a Slack pinboard app!
Tags: slack, api, vue
Published: 2019-10-22 15:30:59

---
title: Fun with APIs: Building a Slack pinboard app!
published: true
cover_image: https://thepracticaldev.s3.amazonaws.com/i/u2cvobxhxkhekxs0noyz.png
description: 
tags: #slack #api #vuejs
---

_**Notice**: Parts of this article from 2019 mention using Bearer to connect to the Slack API. Instead, we now recommend checking out our open source project [Pizzly](https://github.com/Bearer/Pizzly). You can use it to handle the oAuth portions mentioned in this article._

Like everyone, we use Slack a lot at [Bearer](https://www.bearer.sh). We have tons of channels, some for the whole team, some only for the guilds. We even have some for #coffee that we take remotely.

Like any other team, information gets lost a lot on Slack. So one thing that we try to do well its to pin important messages in each channel.

It can be a command to get up and running quickly on a project or just a link to our favorite restaurant menu. Pinning a message turned to be a big part of our Slack routine now - and we even pin messages in DM.

![6 pinned messages in the #engineering channel](https://pix.watch/WpZzAE/5m2KMQ.png)<figcaption>6 pinned messages in the #engineering channel</figcation>

On Slack, you can see pinned messages with the little 📌 on top of a channel. Clicking on it opens a sidebar with a truncated version of the messages. You then need to click on each message to see its context.

The thing is that the FREE version of Slack doesn't let you access old messages. Turns out that the API does! So, [we built an app for that](https://community.bearer.sh/slack-pinboard/). 

Let's see how we did?

## Understanding the Slack API

Let's start by having a look [on Slack's API documentation](https://api.slack.com/methods), which reference a [`pins.list` endpoint](https://api.slack.com/methods/pins.list) having the following abstract:

![Abstract of the pins.list endpoint](https://thepracticaldev.s3.amazonaws.com/i/i1e6y2ik11sxp7bkq3rr.png)

And that request takes the following arguments:
![Arguments of the pins.list endpoint](https://thepracticaldev.s3.amazonaws.com/i/6b2gvrifnbkaeh9aay4j.png)

The token in Slack documentation is a user token, more commonly known as an [access token](https://www.oauth.com/oauth2-servers/access-tokens/). And the channel argument is a channel identifier, which means that we need to first query another endpoint, [`channels.list`](https://api.slack.com/methods/channels.list).

From there we can deduct what our API call flow will be:
* First, we will query the list of channels;
* Then, we will use a channel identifier and list its pinned messages.

**Now, time to play 🤓!**

## Configuring the Slack API and generating a token

To help us use the Slack API, we will use Bearer below. First, we [add the Slack API](https://www.bearer.sh/integrations/11/slack-api) to Bearer's dashboard and follow the instructions provided:

![The Slack API added to my Bearer account](https://thepracticaldev.s3.amazonaws.com/i/w9yr335msanimq31pcxy.png)

We have to create a new Slack App: 
![Create a new Slack App](https://thepracticaldev.s3.amazonaws.com/i/jgwh1kw18yk4sec2bcdm.png)


Then, we configure the OAuth callback URL:
![Bearer OAuth callback URL](https://thepracticaldev.s3.amazonaws.com/i/g7ie1qnmzf56vlghnt5x.png)

And the required scopes:
![Required scopes](https://thepracticaldev.s3.amazonaws.com/i/2toxc3y7h1iomzipbykn.png)

Finally, we grab our Slack credentials and add them to Bearer:
![My Slack App credentials](https://thepracticaldev.s3.amazonaws.com/i/i25ud9qyk6lch6x18k1a.png)

Well, the Slack seems well configured! Let's start to make API requests. But first, we have to generate an access token, this is required for every OAuth APIs. This token represents a user identity.

Usually handling OAuth is tricky, but here we will generate this token with Bearer. [Go back to your Slack API](https://www.bearer.sh/integrations/11/slack-api) on the Bearer's dashboard and click on Bearer's **Connect to Slack** button:

![Slack OAuth dance with Bearer's connect button](https://thepracticaldev.s3.amazonaws.com/i/mqiptoj8x9fju1ddsm4i.gif)<figcaption>Slack OAuth dance with Bearer's connect button</figcation>

Bearer retrieves and stores this token and in return provides an authentication identifier (`authId`). When calling the API with Bearer, we will use this `authId` instead of the token.

This way Bearer will always make sure to pass the token and manage the refresh token automatically when needed ✨!

## Calling the Slack API

We are ready to call the API. Here's how a request to the `channels.list` endpoint looks like:

```bash
$ curl "https://proxy.bearer.sh/slack/channels.list" \
-H "Authorization: _REPLACE-WITH-YOUR-BEARER-SECRET-KEY_" \
-H "Bearer-Auth-Id: _REPLACE-WITH-YOUR-AUTH-ID_"
``` 

If you replace the above params with yours, Slack will successfully respond to your API call 🎉!! It shall return a list of all your channels.

Now, we can send a request to the `pins.list` endpoint, using one of the channel ID previously retrieved (e.g. _C4FE4TW9K_).

```bash
$ curl "https://proxy.bearer.sh/slack/pins.list?channel=C4FE4TW9K" \
-H "Authorization: _REPLACE-WITH-YOUR-BEARER-SECRET-KEY_" \
-H "Bearer-Auth-Id: _REPLACE-WITH-YOUR-AUTH-ID_"
```

I can hear some of you saying: _don't we need to pass the `token` as well?_ Well, as we said previously, using the connect button, Bearer handles the token arguments. It knows where to pass it and what value it is!

The whole logic and API flow is working. It's time to implement this Slack API integration into a proper-application.

## An application to retrieve pinned messages

We are going to use Vue.js, which is an awesome framework to build a simple app like this one. No backend, only plain HTML, CSS and a bit of JS. 

If you add the Bearer's Javascript API client on top to perform the API calls, it's starting to look magical.

For instance, here's how the app fetches Slack channels:

```js
slack
  .auth("AN-AUTH-ID-GENERATED")
  .get('/channels.list')
  .then(({ data }) => {
    if (data.ok && data.channels) {
      this.channels = channels
    }
  })
```

And the function fetching pinned messages from a previously selected channel:

```js
slack
  .auth("AN-AUTH-ID-GENERATED")
  .get(`/pins.list?channel=${this.selectedChannelId}`)
  .then(({ data }) => {
    if (data.ok && data.items) {
      this.messages = data.items
    }
  })
```

> __**A note on front-side API call:**__ When calling an API from a client-side context, you need to be extra careful about security. Bearer gives you an option to enable client-side calls, using a publishable key.

We are almost done, but something is still missing on our application. So far, we've been using our own Slack identity, but we want to let anyone connect using their Slack identity and retrieve their own pinned messages. So it can work for any Slack's workspaces.

## Adding Slack authentication

To let the user retrieves its own Slack channels and pinned messages, we need to let him/her connect using its Slack identity.

Bearer provides a [JavaScript client](https://docs.bearer.sh/integration-clients/javascript#adding-a-connect-button-oauth-apis) (and a React component) that deals with such logic.

![The Bearer's connect button for Slack](https://thepracticaldev.s3.amazonaws.com/i/0rxjwfwfzqjfh8va7714.png)

Once this component is added, our users are able to login using their Slack account. By using their identity, our application will perform API calls to Slack on behalf of their identity. That's exactly what we wanted.


<hr/>

Let's sum up! We just built a static app using Slack API. The entire OAuth flow and API calls are handled by Bearer. And it's deployed in production using Netlify 🚀

Try it out right [here](https://community.bearer.sh/slack-pinboard/) and open the source code to have a full overview.