Slack incident alerts you can acknowledge
Most alert-to-Slack setups only go one way. A message lands in #alerts, someone adds an emoji to say "on it", and then opens another tool to actually acknowledge the page. An hour later nobody can tell from the channel whether the incident is still open.
ZipLogger's Slack app posts each incident as one message and keeps that message up to date. It has buttons, and a click changes the real incident in ZipLogger, as the person who clicked. This post covers the setup, what the message looks like, how Slack users are matched to ZipLogger users, and when a plain incoming webhook is enough.
Two ways to get incidents into Slack
| Slack app (a destination) | Incoming webhook (on an alert rule) | |
|---|---|---|
| Set up in | Settings → Integrations, then Alerts → Delivery → Destinations | the alert rule's Webhook URL field |
| Which incidents | any incident that matches a severity, service and environment | only incidents from that one alert rule |
| Messages | one per incident, edited as it changes | a new message when it fires, another when it recovers |
| Buttons | Acknowledge, Assign to me, Resolve | none |
| Private channels | no | yes, if the webhook belongs to one |
The rest of this post is about the app. The webhook is covered at the end.
Connect the Slack workspace
A ZipLogger Admin opens Settings → Integrations and clicks Connect Slack → on the Slack card. ZipLogger sends you to Slack's own consent screen, where you pick the workspace. The app asks for two bot scopes and nothing else:
chat:write, to post its messages and edit themchannels:read, to list public channels for the channel picker
So it cannot read message history, cannot look up members' email addresses, and cannot post to a channel it was not invited to. After you approve, Slack sends you back to Settings → Integrations, which now shows the workspace, who connected it, and when.
A few rules the install enforces:
- Start from ZipLogger. The install link works once, expires after 10 minutes, and is tied to the browser that started it. An install that did not start from the Connect Slack button is refused.
- One to one. A ZipLogger workspace connects to one Slack workspace, and a Slack workspace can belong to only one ZipLogger workspace at a time. If it is already taken, the banner says
Could not connect Slack (team_taken). - Connecting posts nothing. No message reaches Slack until you add a destination.
Pick a channel
First, invite the bot to the channel in Slack:
/invite @ZipLogger
Then an Admin goes to Alerts → Delivery → Destinations, clicks + Connect a destination and sets Tool to Slack. Editors can change a destination later. There is no API key to paste. The form shows a Channel list loaded from your Slack workspace instead. Only public channels are listed, because the app does not ask for the scope that lists private ones.
Under Which incidents go there, choose a Minimum severity and, if you want, one Service and one Environment. Empty means any. Environment matches the incident's environment label, which comes from job monitors and inbound integrations. Incidents from alert rules have no label, so they only match an empty Environment. Keep Send matching incidents automatically ticked for a normal channel feed. Untick it if the channel should only be used by an escalation policy step. Then click Verify the channel and connect.
The check at save time is light. It confirms that Slack is connected and that a channel was chosen. It does not ask Slack whether the bot is in that channel. If you skipped the /invite, the first incident fails with Slack's not_in_channel error, which shows on the destination instead of being retried forever.
You can add several Slack destinations, for example one channel for everything high and above, and another for one service at any severity.
The message, and how it changes
This is the Block Kit the destination adapter builds for a new incident. It was rendered from ZipLogger's own code for a sample incident. The header block (a coloured dot for the severity, then the title) is left out, and the encrypted button values are shortened:
[
{ "type": "section", "text": { "type": "mrkdwn",
"text": "*Triggered* · severity *high*\nAlert rule \"Checkout errors\" fired: 37 errors in 5 minutes." } },
{ "type": "section", "fields": [
{ "type": "mrkdwn", "text": "*Service*\ncheckout-api" },
{ "type": "mrkdwn", "text": "*Environment*\nproduction" } ] },
{ "type": "actions", "elements": [
{ "type": "button", "text": { "type": "plain_text", "text": "Acknowledge" },
"action_id": "acknowledge", "value": "<encrypted>" },
{ "type": "button", "text": { "type": "plain_text", "text": "Assign to me" },
"action_id": "assign_to_me", "value": "<encrypted>" },
{ "type": "button", "text": { "type": "plain_text", "text": "View in ZipLogger" },
"url": "https://app.ziplogger.ai/alerts/incidents/…" } ] }
]
The buttons follow the incident's current state:
| Incident state | Buttons on the message |
|---|---|
| Triggered | Acknowledge, Assign to me, View in ZipLogger |
| Acknowledged | Resolve, Assign to me, View in ZipLogger |
| Resolved | View in ZipLogger only |
When the incident is acknowledged, resolved or reassigned, ZipLogger edits the same message with chat.update instead of posting a new one. An assignment adds an Assigned to: line with the person's name, or the on-call team's name followed by "(team)". It does not matter where the change happened. A click in Slack, the ZipLogger UI, a Microsoft Teams card or a PagerDuty acknowledgement all refresh the Slack message. The destination's Acknowledging here acknowledges there and Resolving here resolves there boxes control whether those updates are sent, so leave them ticked for Slack.
Who is acting when someone clicks
A Slack click carries a Slack user id, not a ZipLogger login. ZipLogger maps one to the other with an explicit link, never by email address. A Slack workspace admin can set any member's email to anything, so matching on email would let them take over someone else's ZipLogger identity.
A link is made in one of two ways:
- The Admin who connected the workspace is linked automatically during the install.
- Everyone else links on their first click. That click is not applied. Instead, only they see "Link your ZipLogger account to use this button." with a Link your account button. It opens the Link your Slack account page in ZipLogger. They sign in if needed, click Confirm, and see a Linked badge. The link request works once and expires after 10 minutes.
After that, they click the button again. From then on it acts as their ZipLogger user, and the incident timeline records the actor as Slack: followed by their name.
Permissions come from ZipLogger roles, not Slack roles. Admins and Editors can act. A Viewer who clicks gets "You don't have permission to do this in ZipLogger." The role is checked when the click arrives and again when it is applied, so someone downgraded in between is refused.
Two timing details:
- Slack wants an answer within 3 seconds, so ZipLogger queues the click and applies it in the background. The queue is checked every 10 seconds, so the message can take several seconds to change after a click.
- Double clicks and Slack's own retries are safe. The same click is stored once, and acknowledging an incident that someone else already acknowledged does nothing.
Disconnecting
Disconnect on the Slack card revokes the app's token. Slack destinations then fail with "Slack is not connected for this workspace." until you connect again. User links are kept, so nobody has to link again after a reconnect. Removing the app from inside Slack has the same effect: Slack sends app_uninstalled or tokens_revoked, and ZipLogger marks the connection as revoked.
When the incoming webhook is enough
The alert rule's Webhook URL field still exists. It sends an HTTP POST with a Slack-compatible body to whatever URL you paste, so a Slack incoming webhook works, and so does anything else that accepts the same shape. The body is:
{"text": ":rotating_light: *Checkout errors* FIRING\n<summary>\n<link to the incident>"}
On recovery it starts with :large_green_circle: and says RESOLVED instead.
Use it when the alerts must go to a private channel, when you can't install an app in the workspace, or when only one rule should post. Its limits are the reverse of the app's: it only covers that rule's incidents (not job monitors or other sources), every change is a new message, and there is nothing to click. The log alert rules post covers the rule side.
What the Slack app does not do
- No private channels. The picker lists public channels only.
- No slash commands. You can't open or search incidents from Slack. The three buttons are the only actions.
- No Sign in with Slack. Linking attaches a Slack user to an existing ZipLogger account. It is not a login method.
- No posts during planned silence. An incident that opens inside a maintenance window, or while flood control is holding back a burst of incidents, is recorded in ZipLogger but not posted.
- It doesn't replace paging. A Slack message is not a phone call. For someone who must wake up, pair the channel with an escalation policy. See on-call schedules and escalation.
The same steps are in the Slack docs. To try it, create a free workspace, connect Slack under Settings → Integrations, and add a channel under Alerts → Delivery → Destinations.