A notification integration is only useful when it is attached to an event the owner cares about. A Slack webhook sitting in settings is not an alert system. A payment-failed event with nowhere to go is not one either.
The base connects the two. It defines product events, lets the owner map an event to one or more channels, resolves each channel from organization settings, sends the message, and records the result.
Nine channel implementations sit behind the same interface: in-app, email, Slack, Discord, Microsoft Teams, Telegram, Twilio, Pushover, and ntfy. Seven are external notification cards. In-app needs no outside account. Email reuses whichever transactional email provider the organization has already configured.
That reuse is the first connection. The email integration is not configured again inside alerts. The owner chooses a transactional provider once; the notification channel asks the email layer for that active provider and sends the existing notification template.
Events become routing rules
The admin event catalog currently contains 21 measured definitions across users, billing, organizations, content, marketing, and system changes. They include signups, invitations, payments, subscription lifecycle, plan and organization changes, published announcements, feature toggles, audience changes, and webhook failure.
An alert rule belongs to one organization and one event type. Its channel list can contain several destinations. The database enforces one rule per organization and event, so the row is the readable answer to a simple question: when this happens, where should the owner hear about it?
One migration backfills six common rules in a disabled state for organizations that exist when it runs. They cover signup, completed and failed payments, cancelled and past-due subscriptions, and failed webhooks. Nothing starts sending merely because the rows exist. The owner enables a rule and chooses configured channels.
The admin can test a channel before relying on it. The test route resolves the organization-specific channel, sends a synthetic signup event, and returns the channel's real success or failure result.
Configuration decides whether a channel exists
In-app is always available because it writes to the product's admin notification table. Email is available only when the organization has a working email provider. Every external channel has its own minimum configuration.
Slack, Discord, and Teams use webhook URLs. Telegram needs a bot token and chat ID. Twilio needs account credentials, a sending number, and a destination number. Pushover needs an API token and user key. ntfy needs a topic URL. If a required value is missing, the channel resolver returns no channel and delivery is skipped rather than attempting a malformed request.
Each external card passes the same integration gate as the rest of the catalog. It appears because a channel implementation consumes its settings. This is why the seven cards count as integrations and the 31 credential-only definitions stay hidden.
One event can do more than notify
When the product dispatches an event, the event layer loads enabled alert rules and active automations for that organization. Matching alert rules fan out across their channel lists. Each attempt becomes a notification-log row with event, channel, sent or failed state, error, and timestamp.
The same event continues through the rest of the product. It can run an automation, trigger an outgoing webhook, enter the owner analytics ledger, and create an admin-bell record. Notification routing is one branch of the event, not a special call embedded separately in every signup or billing handler.
Automations reuse the same channel implementations too. A workflow that sends a Slack message or Twilio SMS resolves the same organization credentials and calls the same adapter as an alert rule. Configuring the channel once supports both reactions.
This is where the nine channels become more than a provider list. A failed payment can create an in-app record, email the owner, post to Teams, and call an outside workflow without four unrelated integrations listening to the payment handler.
Messages and recipients
The channel layer converts a product event into a shared title and message, then wraps it in the destination's native request shape. Slack gets blocks, Teams gets its card format, Telegram gets escaped text, and Twilio sends form-encoded SMS data.
The email channel sends the branded notification template to the first super_admin found in the organization. In-app writes to the admin bell. External destinations use the channel, chat, phone, user, or topic configured for that organization.
This is an owner-alert system. It is distinct from customer-facing transactional email and from mobile push devices registered by end users.
The honest limit
The 21 event definitions are a curated admin menu, not automatic instrumentation for every action a future product may add. A new business event still has to call the shared dispatcher before any alert rule can see it.
The six disabled starter rules are a migration-time backfill, not a provisioning trigger. An organization created later does not automatically receive those six rows in the reviewed code; its owner can create rules from the alerts surface.
Three entries in the 21-event menu do not have tailored text in the shared channel formatter: checkout initiated, audience entered, and audience left. They fall back to a generic event message. The direct admin-bell formatter also has no message branch for those three. Routing works, but their human-facing copy needs a product extension.
Delivery is best-effort and asynchronous from the original product request. The channel function sends once and records sent or failed. The reviewed notification layer does not enqueue a retry. A failed provider response is visible in the log, but the owner or product must decide what retry policy it needs.
The built-in admin bell also has a direct event path outside alert rules. Adding in-app to a rule can therefore overlap with the direct bell record for a curated event. Products that require exactly one bell item per event should keep one insertion path.
Email has one owner recipient in the current adapter: the first super_admin for the organization. It is not a per-rule recipient list. Twilio likewise resolves one stored destination number. Products that need escalation rosters, rotations, or per-recipient delivery need a recipient model above these channels.
Why notifications belong between systems
The strongest part of this layer is not that it can post to nine places. It is that provider configuration, event meaning, and routing policy remain separate and then meet at execution time.
Payments can emit a failure without knowing whether the owner uses Slack. Slack can be replaced without changing the payment path. An inbound webhook can become the same kind of event as a native action. An automation can reuse the same configured channel as an alert rule.
That is a fabric-shaped capability: one event contract supporting several human and machine reactions, with the route and the delivery result visible to the owner.
