The Slack Web API is an interface for querying information from and enacting change in a Slack workspace. Use it on the fly for ad-hoc queries, or as part of a more complex tapestry of platform features in a Slack app. What can you do with the Web API? . Search everything you add to Slack from one box – messages, files, comments. Then filter, sort, slice and dice your search to find exactly what you need faster. Mobile apps from Slack are fully functional and mean all your team communication are available everywhere, directly from the palm of your hand. Description Slack brings team communication and collaboration into one place so you can get more work done, whether you belong to a large enterprise or a small business. Check off your to-do list and move your projects forward by bringing the right people, conversations, tools. The first step to creating our Slack Bot is to simply create an app within Slack.
The @slack/web-api
package contains a simple, convenient, and configurable HTTP client for making requests to Slack’sWeb API. Use it in your app to call any of the over 130methods, and let it handle formatting, queuing, retrying, pagination, and more.
Installation
Initialize the client
The package exports a WebClient
class. All you need to do is instantiate it, and you’re ready to go. You’ll typicallyinitialize it with a token
, so that you don’t have to provide the token each time you call a method. A token usuallybegins with xoxb
or xoxp
. You get them from each workspace an app is installed onto. The app configuration pageshelp you get your first token for your development workspace.
Alternatively, you can create a client without an token, and use it with multiple workspaces as long as you supply atoken
when you call a method.
Call a method
The client instance has a named method for each of the public methods in the Web API. The most popular one iscalled chat.postMessage
, and its used to send a message to a conversation. For every method, you pass arguments asproperties of an options object. This helps with the readablility of your code since every argument has a name. Allnamed methods return a Promise
which resolves with the response data, or rejects with an error.
Hint: If you’re using an editor that supports TypeScript, even if you’re not using TypeScript to write your code,you’ll get hints for all the arguments each method supports. This helps you save time by reducing the number oftimes you need to pop out to a webpage to check the reference. There’s more information about usingTypeScript with this package in the documentation website.
Note: Use the Block Kit Builder for a playgroundwhere you can prototype your message’s look and feel.
If you want to provide the method name as a string, so that you can decide which method to call dynamically, or to calla method that might not be available in your version of the client, use the WebClient.apiCall(methodName, [options])
method. The API method call above can also be written as follows:
Handle errors
Errors can happen for many reasons: maybe the token doesn’t have the proper scopes tocall a method, maybe its been revoked by a user, or maybe you just used a bad argument. In these cases, the returnedPromise
will reject with an Error
. You should catch the error and use the information it contains to decide how yourapp can proceed.
Each error contains a code
property, which you can check against the ErrorCode
export to understand the kind oferror you’re dealing with. For example, when Slack responds to your app with an error, that is anErrorCode.PlatformError
. These types of errors provide Slack’s response body as the data
property.
There are a few more types of errors that you might encounter, each with one of these code
s:
ErrorCode.RequestError
: A request could not be sent. A common reason for this is that your network connection isnot available, orapi.slack.com
could not be reached. This error has anoriginal
property with more details.ErrorCode.RateLimitedError
: The Web API cannot fulfill the API method call because your app has made too manyrequests too quickly. This error has aretryAfter
property with the number of seconds you should wait before tryingagain. See the documentation on rate limit handling tounderstand how the client will automatically deal with these problems for you.ErrorCode.HTTPError
: The HTTP response contained an unfamiliar status code. The Web API only responds with200
(yes, even for errors) or429
(rate limiting). If you receive this error, its likely due to a problem with a proxy,a custom TLS configuration, or a custom API URL. This error has thestatusCode
,statusMessage
,headers
, andbody
properties containing more details.
Pagination
Many of the Web API’s methods returnlists of objects, and are known to be cursor-paginated. The result of calling these methods will contain a part ofthe list, or a page, and also provide you with information on how to continue to the next page on a subsequent API call.Instead of calling many times manually, the WebClient
can manage getting each page, allowing you to determine when tostop, and help you process the results.
The process of retrieving multiple pages from Slack’s API can be described as asynchronous iteration, which meansyou’re processing items in a collection, but getting each item is an asynchronous operation. Fortunately, JavaScripthas this concept built in, and in newer versions of the language there’s syntax to make it even simpler:for await...of
.
The for await...of
syntax is available in Node v10.0.0 and above. If you’re using an older version of Node, seefunctional iteration below.
The .paginate()
method can accept up to two additional parameters. The third parameter, stopFn
, is a function thatis called once for each page of the result, and should return true
when the app no longer needs to get another page.The fourth parameter is reducerFn
, which is a function that gets called once for each page of the result, but canbe used to aggregate a result. The value it returns is used to call it the next time as the accumulator
. The firsttime it gets called, the accumulator
is undefined.
The returned value is a Promise
, but what it resolves to depends on whether or not you include the fourth (optional)parameter. If you don’t include it, the resolved value is always undefined
. In this case, its used for control flowpurposes (resuming the rest of your program), and the function in the third parameter is used to capture a result. Ifyou do include the fourth parameter, then the resolved value is the value of the accumulator
. This is a familiarpattern for people that use functional programming.
Opening modals
Modals can be created by calling the views.open
method. The method requires you to pass a valid view payload in addition to a trigger_id
, which can be obtained when a user invokes your app using a slash command, clicking a button, or using another interactive action.
After the modal is opened, you can update it dynamically by calling views.update
with the view ID returned in the views.open
result.
Logging
The WebClient
will log interesting information to the console by default. You can use the logLevel
to decide howmuch information, or how interesting the information needs to be, in order for it to be output. There are a few possiblelog levels, which you can find in the LogLevel
export. By default, the value is set to LogLevel.INFO
. While you’rein development, its sometimes helpful to set this to the most verbose: LogLevel.DEBUG
.
All the log levels, in order of most to least information are: DEBUG
, INFO
, WARN
, and ERROR
.
You can also choose to have logs sent to a custom logger using the logger
option. A custom logger needs to implementspecific methods (known as the Logger
interface):
Slack Webclient
Method | Parameters | Return type |
---|---|---|
setLevel() | level: LogLevel | void |
setName() | name: string | void |
debug() | ...msgs: any[] | void |
info() | ...msgs: any[] | void |
warn() | ...msgs: any[] | void |
error() | ...msgs: any[] | void |
A very simple custom logger might ignore the name and level, and write all messages to a file.
Automatic retries
In production systems, you want your app to be resilient to short hiccups and temporary outages. Solving for thisproblem usually involves building a queuing system that handles retrying failed tasks. The WebClient
comes with thisqueuing system out of the box, and its on by default! The client will retry a failed API method call up to 10 times,spaced out over about 30 minutes. If the request doesn’t succeed in that time, then the returned Promise
will reject.You can observe each of the retries in your logs by setting the log level to DEBUG. Try running thefollowing code with your network disconnected, and then re-connect after you see a couple of log messages:
Shortly after re-connecting your network, you should see the Done!
message. Did you notice the program doesn’t use avalid token? The client is doing something clever and helpful here. It knows the difference between an error such as notbeing able to reach api.slack.com
and an error in the response from Slack about an invalid token. The former issomething that can be resolved with a retry, so it was retried. The invalid token error means that the call isn’t goingto succeed until your app does something differently, so it stops attempting retries.
You might not think 10 reties in 30 minutes is a good policy for your app. No problem, you can set the retryConfig
toone that works better for you. The retryPolicies
export contains a few well known options, and you can always writeyour own.
Here are some other values that you might want to use for retryConfig
:
retryConfig | Description |
---|---|
retryPolicies.tenRetriesInAboutThirtyMinutes | (default) |
retryPolicies.fiveRetriesInFiveMinutes | Five attempts in five minutes |
retryPolicies.rapidRetryPolicy | Used to keep tests running fast |
{ retries: 0 } | No retries (other options) |
Note: If an API call results in a rate limit being exceeded, you might still notice the client automaticallyretrying the API call. If you’d like to opt out of that behavior, set the rejectRateLimitedCalls
option to true
.
Upload a file
A couple methods, files.upload
and users.setPhoto
, allow you to upload a file over the API. In Node, there are a fewways you might be dealing with files, or more generally, binary data. When you have the whole file in memory (like whenyou’ve just generated or processed an image), then in Node you’d have a Buffer
that contains that binary data. Or,when you are reading the file from disk or a network (like when you have a path to file name), then you’d typically havea ReadableStream
. The client can handle both of these binary data types for you, and it looks like any other API call.
The following example shows how you can use files.upload
to upload afile that is read from disk (as a ReadableStream
).
In the example above, you could also use a Buffer
object as the value for the file
property of the options object.
Proxy requests with a custom agent
The client allows you to customize the HTTPAgent
used to create the connection to Slack.Using this option is the best way to make all requests from your app through a proxy, which is a common requirement inmany corporate settings.
In order to create an Agent
from some proxy information (such as a host, port, username, and password), you can useone of many npm packages. We recommend https-proxy-agent
. Startby installing this package and saving it to your package.json
.
Import the HttpsProxyAgent
class, and create an instance that can be used as the agent
option of the WebClient
.
Rate limits
When your app calls API methods too frequently, Slack will politely ask (by returning an error) the app to slow down,and also let your app know how many seconds later it should try again. This is called rate limiting and theWebClient
handles it for your app with grace. The client will understand these rate limiting errors, wait theappropriate amount of time, and then retry the request without any changes in your code. The Promise
returned onlyresolves when Slack has given your app a real response.
It’s a good idea to know when you’re bumping up against these limits, so thatyou might be able to change the behavior of your app to hit them less often. Your users would surely appreciate gettingthings done without the delay. Each time a rate limit related error occurs, the WebClient
instance emits an event:WebClientEvent.RATE_LIMITED
. We recommend that you use the event to inform users when something might take longer thanexpected, or just log it for later.
You might not want to the WebClient
to handle rate limits in this way. Perhaps the operation was time sensitive, andit won’t be useful by the time Slack is ready for another request. Or, you have a more sophisticated approach. In thesecases, you can set the rejectRateLimitedCalls
option on the client to true
. Once you set this option, method callscan fail with rate limiting related errors. These errors have a code
property set to ErrorCode.RateLimitedError
. Seeerror handling for more details.
Request concurrency
Each of the API method calls the client starts are happening concurrently, or at the same time. If your app triesto perform a lot of method calls, let’s say 100 of them, at the same time, each one of them would be competing for thesame network resources (such as bandwidth). By competing, they might negatively affect the performance of all the rest,and therefore negatively affect the performance of your app. This is one of the reasons why the WebClient
limits theconcurrency of requests by default to ten, which means it keeps track of how many requests are waiting, and onlystarts an eleventh request when one of them completes. The exact number of requests the client allows at the same timecan be set using the maxRequestConcurrency
option.
Slack Web Client
The lower you set the maxRequestConcurrency
, the less parallelism you’ll have in your app. Imagine setting theconcurrency to 1
. Each of the method calls would have to wait for the previous method call to complete before it caneven be started. This could slow down your app significantly. So its best not to set this number too low.
Another reason, besides competing for resources, that you might limit the request concurrency is to minimize theamount of state in your app. Each request that hasn’t completed is in some ways a piece of state that hasn’t yet beenstored anywhere except the memory of your program. In the scenario where you had 100 method calls waiting, and yourprogram unexpectedly crashes, you’ve lost information about 100 different things going on in the app. But by limitingthe concurrency to a smaller number, you can minimize this risk. So its best not to set this number too high.
Custom TLS configuration
Each connection to Slack starts with a handshake that allows your app to trust that it is actually Slack you areconnecting to. The system for establishing this trust is called TLS. In order for TLS to work, the host running your appkeeps a list of trusted certificate authorities, that it can use to verify a signature Slack produces. You don’tusually see this list, its usually a part of the operating system you’re running on. In very special cases, like certaintesting techniques, you might want to send a request to another party that doesn’t have a valid TLS signature that yourcertificate authority would verify. In these cases, you can provide alternative TLS settings, in order to change how theoperating system might determine whether the signature is valid. You can use the tls
option to describe the settingsyou want (these settings are the most common and useful from the standard NodeAPI).
tls property | Description |
---|---|
ca | Optionally override the trusted CA certificates. Any string or Buffer can contain multiple PEM CAs concatenated together. |
key | Private keys in PEM format. PEM allows the option of private keys being encrypted. Encrypted keys will be decrypted with passphrase . |
cert | Cert chains in PEM format. One cert chain should be provided per private key. |
pfx | PFX or PKCS12 encoded private key and certificate chain. pfx is an alternative to providing key and cert individually. PFX is usually encrypted, if it is, passphrase will be used to decrypt it. |
passphrase | Shared passphrase used for a single private key and/or a PFX. |
Custom API URL
The URLs for method calls to Slack’s Web API always begin with https://slack.com/api/
. In very special cases, such ascertain testing techniques, you might want to send these requests to a different URL. The slackApiUrl
option allowsyou to replace this prefix with another.
Exchange an OAuth grant for a token
There’s one method in the Slack Web API that doesn’t requires a token, because its the method that gets a token! Thismethod is called oauth.v2.access
. It’s used as part of the OAuth2.0 process that users initiate when installing your app into a workspace. In thelast step of this process, your app has received an authorization grant called code
which it needs to exchange foran access token (token
). You can use an instance of the WebClient
that has no token to easily complete thisexchange.
Slack Webinar
Note: If you’re looking for a more complete solution that handles more of the OAuth process for your app, take alook at the @aoberoi/passport-slack Passport Strategy.