Notification channels
A notification channel is a shared destination that team rules deliver to. Channels belong to the organization, and only organization owners can see or change them. Manage them under Organization settings → Notification channels.
There are three kinds:
| Kind | In the dashboard | What it is |
|---|---|---|
| Slack, connected | Slack: OAuth | Add to Slack: you pick the workspace and channel on Slack's own screen. Needs a Slack app — see Add to Slack. |
| Slack, pasted | Slack: webhook | A Slack incoming webhook URL you paste in. Works with no Slack app configured on the instance. |
| Webhook | Webhook | A signed JSON POST to your own https:// endpoint. See Webhooks. |
Email is not a channel. Email goes to people, through their personal rules.
Add to Slack
Slack: OAuth needs a Slack app that belongs to your instance. Without one, the option is hidden and pasted Slack webhooks still work.
-
At api.slack.com/apps, choose Create New App → From an app manifest, and paste this manifest. Replace
YOUR-OKAPI-DOMAINwith the public HTTPS host browsers use for Okapi:{ "display_information": { "name": "Okapi Alerts" }, "features": { "bot_user": { "display_name": "Okapi" } }, "oauth_config": { "redirect_urls": [ "https://YOUR-OKAPI-DOMAIN/api/v1/slack/oauth/callback" ], "scopes": { "bot": [ "incoming-webhook" ] } }, "settings": { "org_deploy_enabled": false, "socket_mode_enabled": false, "token_rotation_enabled": false } }Slack keeps every app in a development workspace. If you have none, create a free workspace at slack.com/create; your users never see it.
-
Copy the app's Client ID and Client Secret into
OKAPI_SLACK_CLIENT_IDandOKAPI_SLACK_CLIENT_SECRETin your.env. -
Decide which workspaces can install the app. By default a Slack app installs only into its own development workspace. To allow any workspace, open the app's Manage Distribution page, complete the "Remove Hard Coded Information" checklist, and press Activate Public Distribution. This needs no Slack review.
-
Recreate the app container:
docker compose up -d --force-recreate app.
Then, in New channel, choose Slack: OAuth and press Save and connect to Slack. Okapi keeps only the incoming webhook that Slack returns and discards the broader access token.
Set both variables or neither. If only one is set, Okapi starts with Add to Slack off and shows instance administrators a notice. A compose file downloaded before these variables were added does not pass them — see Setting variables the compose file does not list.
The URL is the credential
A Slack webhook URL is enough to post into that Slack channel, and a webhook URL often carries a token. So Okapi never shows a channel's URL in a list or a read. It shows a hint instead: the host and the last four characters, for example hooks.slack.com/…x9Qz.
- Reveal shows the full URL and, for a webhook, its signing secret. You confirm your password first, and every reveal is recorded in the audit log.
- Rotate creates a new signing secret for a webhook, behind the same password check, and is audited. Update your receiver's verifier at the same time, or it rejects every delivery after the rotation.
Destination URLs must use https:// and cannot carry a username or password. Okapi refuses to deliver to loopback, private, and link-local addresses, and checks the resolved address again on every send.
Projects and default rules
A channel can serve All projects or only the projects you choose. A team rule can only use a channel that covers its project.
Use for default alerts attaches the channel to the team default rules. It does this when a project is created, when you create the channel with the option on, and when you turn the option on for an existing channel. It respects the channel's projects. Turning the option off does not detach the channel from any rule.
Send test
Send test makes one real delivery with the title "Okapi test notification" (webhook kind: test). If it fails, the error is shown and nothing is counted against the channel. If it succeeds, it clears the channel's failure count and turns an auto-disabled channel back on. In safe mode the test is refused.
Health
Each channel shows a status: Healthy, Failing · N of 20, Auto-disabled, or Disabled (turned off by an owner).
After 20 failed delivery attempts in a row, Okapi auto-disables the channel, so one broken endpoint cannot slow down everything else. A failed attempt is a request the destination answered with an error, or a timeout or connection failure. Upstream rate limiting (429), Okapi's own caps, and failures on Okapi's side that never reached the destination do not count. While a channel is auto-disabled, new alerts are not sent to it.
Not in a released self-host version yet. Failures in the slow retry phase (see Delivery and retries) do not count toward the 20. Okapi keeps retrying the deliveries that were already pending for up to 7 days, and turns the channel back on if one succeeds. In the current self-host release, deliveries that were already pending when the channel auto-disabled are dropped, not retried, and only a successful Send test turns the channel back on. In both versions, alerts matched while a channel is auto-disabled are never sent to it.
Delivery and retries
A delivery succeeds on any 2xx response. Okapi waits up to 10 seconds for a response and does not follow redirects.
| Response | What happens |
|---|---|
2xx |
Delivered. |
429 |
Retried. A Retry-After header can lengthen the wait (up to one hour), never shorten it. Does not count toward auto-disable. |
5xx, timeout, connection error |
Retried. |
Any other 4xx, an invalid destination |
Failed permanently, with no retry. |
Retries wait 10 seconds, 30 seconds, 60 seconds, 150 seconds, and 300 seconds. Email and in-app deliveries stop after those five retries.
Not in a released self-host version yet. Channel deliveries do not stop after the fifth retry. Once a delivery is about nine minutes old, the waits grow to 30 minutes, 1, 2, 4 and 8 hours, then every 12 hours, until seven days after the delivery was created. In the current self-host release, channel deliveries stop after the fifth retry, like email.
Destination caps
Two fixed caps protect a destination during an incident. They are not configurable.
| Cap | Limit |
|---|---|
| Per channel | 300 alerts per hour, across every rule that uses the channel |
| Per person, email | 60 alert emails per hour |
An alert that a cap refuses is dropped for that destination and does not count against the rule's throttle. Other destinations of the same alert still receive it. See Volume limits for the per-rule cap.
Overflow summaries
Not in a released self-host version yet.
When a cap refuses alerts, or a Slack channel answers with 429 at least twice in one UTC hour, Okapi sends that destination one summary after the hour ends. The headline names the closed hour:
- For the hour that just ended: "N more alerts were withheld or delayed in the last hour · <start>–<end> UTC"
- For an older hour, after downtime: "N more alerts were withheld or delayed between <start> and <end> UTC"
With a count of one it reads "1 more alert was withheld or delayed". Times use the form 2026-10-04 14:00. The summary adds "Includes rate-limit delays and repeated refusals; this is not a count of distinct issues.", and, when 429s were involved, "Individual retries continue." It has one section per affected project, with an Open project link. Email summaries carry an ALERT SUMMARY badge, and webhooks receive them as kind overflow_summary.
Each destination gets at most one summary per closed UTC-hour bucket, and a summary is sent once and never retried. After downtime, Okapi can send several summaries in a row, one for each missed hour. The caps do not apply to it, and it does not replace the individual retries, which continue. Catch-up covers hours up to seven days back. A channel that is disabled or auto-disabled gets no summary.
Next: Digests.