Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

slack - Slack Incoming Webhook client

Import with import "slack.j" as slack;. Post messages to a Slack channel through an Incoming Webhook, on top of the http module - a sibling of gotify and discord. Needs the default jennifer binary. The webhook URL is a secret: read it from the environment or a config file, never commit it.

import "slack.j" as slack;

slack.send("https://hooks.slack.com/services/T/B/xxx", "deploy finished");

def m as slack.Message init slack.section(
    slack.header(slack.message(), "Deploy"), "*build 1234* is live");
slack.sendMessage("https://hooks.slack.com/services/T/B/xxx", $m);

Runnable: examples/modules/slack_demo.j.

Plain messages

slack.send(webhookUrl, text) posts {"text": text} (the text is Slack mrkdwn) and returns the http.Response - Slack answers 200 with body ok on success. The webhook’s configured channel receives the message.

Rich messages (Block Kit)

Build a message from Block Kit blocks with value-semantic builders - each returns a fresh Message, so they chain - then post it with sendMessage (or inspect the JSON with render).

def struct slack.Message {
    text as string,           # top-level fallback / notification text ("" to omit)
    blocks as list of string  # pre-rendered block JSON fragments
};
CallReturns
slack.message()Messagestart an empty message
slack.text(m, text)Messageset the fallback / notification text
slack.section(m, markdown)Messageappend a section block (mrkdwn)
slack.header(m, heading)Messageappend a header block (plain text)
slack.divider(m)Messageappend a divider block
slack.render(m)stringrender the JSON payload
slack.sendMessage(webhookUrl, m)http.Responsepost the built message

Text passed to any builder is JSON-escaped for you (via the json library), so quotes, newlines, and other meta-characters are safe. The fallback text is shown in notifications and by clients that do not render blocks - set it even when you use blocks.

Scope

  • Incoming Webhooks, not the Web API - no bot tokens, chat.postMessage, threads, reactions, or file uploads. The channel is fixed by the webhook.
  • A subset of Block Kit - section / header / divider. Fields, accessories, images, and interactive elements are not built here (compose the JSON yourself and post via http if you need them).
  • No retry / rate-limit handling - a non-2xx is returned as the response value for the caller to inspect, not thrown.

See also