SlackKit is a Slack client for Elixir. It covers both halves of the Slack platform from a single library:
- Real-Time Messaging (RTM). A long-lived WebSocket connection that
streams workspace events (messages, presence changes, channel updates…) into
a bot module of your choosing. See
SlackandSlack.Bot. - Web API. The full Slack Web API surface — every
chat.postMessage,conversations.list,users.info, and so on — generated at compile time from the official JSON schemas. See theSlack.Web.*modules.
You'll need a Slack API token, which can be obtained by following the Token Generation Instructions or by creating a new bot integration.
SlackKit is a fork of Elixir-Slack,
which is no longer maintained. It has been updated to use the latest versions
of dependencies and migrated off the unmaintained websocket_client Erlang
library onto Mint.WebSocket.
Add :slack_kit to your mix.exs dependencies:
def deps do
[
{:slack_kit, "~> 0.24"}
]
endThen fetch dependencies:
mix deps.getDefine a module that uses the Slack behaviour and defines the appropriate callback methods.
defmodule SlackRtm do
use Slack
def handle_connect(slack, state) do
IO.puts "Connected as #{slack.me.name}"
{:ok, state}
end
def handle_event(message = %{type: "message"}, slack, state) do
send_message("I got a message!", message.channel, slack)
{:ok, state}
end
def handle_event(_, _, state), do: {:ok, state}
def handle_info({:message, text, channel}, slack, state) do
IO.puts "Sending your message, captain!"
send_message(text, channel, slack)
{:ok, state}
end
def handle_info(_, _, state), do: {:ok, state}
endTo run this example, you'll want to call Slack.Bot.start_link(SlackRtm, [], "TOKEN_HERE") and run the project with mix run --no-halt.
You can send messages to channels using send_message/3 which takes the message
as the first argument, channel/user as the second, and the passed in slack
state as the third.
The passed-in slack argument is a Slack.State struct that's folded forward
as RTM events arrive. It exposes the current bot identity (me), team
(team), and live maps of channels, groups, users, bots, and ims
keyed by ID — see Slack.State for the full surface.
To trigger sends from outside the RTM loop — for example, from a Phoenix
controller or a periodic job — leverage handle_info/3:
{:ok, rtm} = Slack.Bot.start_link(SlackRtm, [], "token")
send rtm, {:message, "External message", "#general"}
#=> {:message, "External message", "#general"}
#==> Sending your message, captain!Slack has a lot of message types, so define a catch-all handle_event/3
clause to keep unrecognised events from crashing your bot. A full list of types
is on the RTM API page.
The complete Slack Web API surface is generated at compile time from the JSON
schemas under priv/docs/methods/. Each endpoint becomes a function on a
module derived from its name — for example chat.postMessage becomes
Slack.Web.Chat.post_message, and conversations.list becomes
Slack.Web.Conversations.list. Required parameters are positional; everything
else goes through an optional_params map.
There are two ways to authenticate. The common case is to set a default token in application config:
config :slack, api_token: "xoxb-…"Alternatively, pass %{token: "VALUE"} in optional_params on any call. This
overrides the configured :api_token and is useful for multi-workspace apps.
Quick example — get every member's real name:
"xoxb-…"
|> then(&Slack.Web.Users.list(%{token: &1}))
|> Map.fetch!("members")
|> Enum.map(& &1["real_name"])import Config
config :slack,
api_token: System.get_env("SLACK_TOKEN"),
url: "https://slack.com",
web_http_client: Slack.Web.DefaultClient,
web_http_client_opts: [receive_timeout: 10_000]See Configuration for the full list of supported config
keys, including custom HTTP clients and Req options.
Full documentation, including all generated Slack.Web.* modules, lives at
hexdocs.pm/slack_kit.
Copyright (c) 2026 Samuel Gordalina Copyright (c) 2014-2022 Blake Williams
Source code is released under the MIT license.