Notifications
Email notifications projected from platform events, the curated allowlist that prevents notification fatigue, and per-user opt-out preferences.
Email notifications projected from platform events, the curated allowlist that prevents notification fatigue, and per-user opt-out preferences.
A notification is one platform event projected onto email. The platform already records everything that happens as an append-only ledger of events; notifications are a derived view over that ledger — they surface the handful of events a person actually needs to know about, and nothing else.
The event ledger and your domain data stay the source of truth; a notification is a projection, so a missed email loses nothing but the reminder.
Email is the notification channel. Notifications never touch your webhook endpoints: webhooks are a separate, machine-facing delivery you configure per endpoint — the platform never re-delivers a webhook as a notification.
The platform does not email on everything. Exactly one curated list decides which events send an email, to whom. Anything not on the list stays silent — by construction, not by configuration. There is no "notify on all events" switch to accidentally flip.
The list covers the events that matter operationally:
| Event | Who is notified |
|---|---|
| Payment succeeded | The subscriber's members |
| Payment failed | The subscriber's members |
| Subscription canceled | The subscriber's members |
| Access request created | The subscriber's owners/admins |
| Access request resolved | The subscriber's owners/admins |
| Change set approved | Your organization's owners/admins |
| Change set applied | Your organization's owners/admins |
| Build failed | Your organization's members |
| Business published | Your organization's members |
Recipients are resolved from live membership at the moment the event happens, then frozen — a member added during a delivery delay never receives an event that predated them. There is no assumption of teams or roles: a solo (personal) organization resolves to its single owner; an individual subscriber resolves to its one member.
The smallest honest preference model: each person can opt out of email. There is no per-event tuning (the allowlist is already curated) and no digest batching — just a clean on/off, globally or per category.
Builder plane:
GET /businesses/:id/notification-preferences
PATCH /businesses/:id/notification-preferences # { "master": true } → opt out of all email
Portal plane:
GET /portal/businesses/:productId/me/notification-preferences
PATCH /portal/businesses/:productId/me/notification-preferences
The PATCH body is a partial patch — send only what you're changing; omitted
fields keep their current setting. true means "opted out." Opt out of a single
category with { "categories": { "billing": true } }.