In the previous post, we introduced plumber as a way to expose R processes and programs to external systems via REST API endpoints. In this post, weâ€™ll go further by building out an API that powers a Slack slash command, all from within R using plumber. A subsequent post will outline deploying and securing the API.
We will create an API built on top of simulated customer call data that powers a slash command. This command will allows users to view a customer status report within Slack. As shown, this status report contains customer name, total calls, date of birth, and a plot of call history for the past 20 weeks. The simulated data, along with the script used to create it, can be found in the GitHub repository for this example.
Setup
Slack is a commonly used communication tool thatâ€™s highly customizable through various integrations. Itâ€™s even possible to build your own integrations, which is what weâ€™ll be doing here. In order to build a Slack app, you need to have a Slack account and follow the instructions for creating an app. In this example, we will build an app that includes a slash command that users can access by typing / into a Slack message.
The Slack request
In this scenario, weâ€™re building an API that will interact with a known request. This means that we need to understand the nature of the incoming request so that we can appropriately handle it within the API. Slack provides some documentation about the request that is sent when a slash command is invoked. In short, an HTTP POST request is made that contains a URL-encoded data payload. An example data payload looks like:
token=gIkuvaNzQIHg97ATvDxqgjtO
&amp;team_id=T0001
&amp;team_domain=example
&amp;enterprise_id=E0001
&amp;enterprise_name=Globular%20Construct%20Inc
&amp;channel_id=C2147483705
&amp;channel_name=test
&amp;user_id=U2147483697
&amp;user_name=Steve
&amp;command=/weather
&amp;text=94070
&amp;response_url=https://hooks.slack.com/commands/1234/5678
&amp;trigger_id=13345224609.738474920.8088930838d88f008e0
Thereâ€™s a lot of detail included in the Slack request, and the Slack documentation provides details about each field. Weâ€™re mainly interested in the text field, which contains the text entered into Slack after the slash command. In the above example, the user entered /weather 94070 into Slack, so the request indicates that the command was /weather and the text was 94070.
Note that this approach is different from APIs that are not being built around a known request or specification. In such instances, we are free to expose endpoints and return data in whatever method seems most beneficial to downstream consumers. In such a scenario, we would provide downstream API consumers with an understanding of how the API handles requests and what types of responses are generated so that they can appropriately interact with the API. But in this example, the design of our API is, in part, dictated by the specifications Slack provides.
Building the API
Now that we have an understanding of what is included in the incoming request, we can begin to build out the API using plumber. First, we need to set up the global environment for the API by loading necessary packages and global objects, including the simulated data this API is built on. In reality, this data would likely come from an external database accessed via an ODBC connection.
# Packages ----
library(plumber)
library(magrittr)
library(ggplot2)
# Data ----
# Load sample customer data
sim_data %
unlist()
if (length(split_text) __= 1) {
endpoint