1. Documentation
  2. Manage Status Page
  3. Subscribers
ReadmeGitHub
  • Introduction
  • Quickstart
  • CLI
  • Configuration
  • Identity
  • Branding
  • Themes
  • Monitors
  • Checks and scheduling
  • Metrics and badges
  • Incidents
  • Maintenance
  • Notifications
  • Subscribers
  • React Router
  • Next.js
  • Astro
  • SQLite
  • Cloudflare D1
  • PostgreSQL
  • Schema and migrations
  • Cloudflare
  • Vercel
  • Self-hosting
  • API overview
  • Status endpoints
  • Incident endpoints
  • Maintenance endpoints
  • Subscriber endpoints
  • Badges, feeds and metrics
  • Admin endpoints
  • The check run
  • Uptime and history
  • Automatic incidents
  • Notification delivery
  • Public subscriptions

Subscribers

Enable public subscriptions over email, feeds and webhooks, safely.

Let visitors subscribe to incident and maintenance updates by email, RSS or webhook. Subscriptions are off by default: email and webhook sign-ups store visitor-supplied destinations, and webhooks make outbound requests from your deployment.

ts
subscribers: {  enabled: true,  methods: ["email", "rss"],  requireConfirmation: true,},
enabledbooleanoptional

Defaults to false. While false, every /subscribers* route answers 404 and the page shows no subscribe control.

methods("email" | "rss" | "webhook")[]optional

Defaults to ["email", "rss"]. Duplicates are rejected.

requireConfirmationbooleanoptional

Defaults to true. Email subscriptions use double opt-in.

Choose a subscription method

MethodStorageNotes
emaila subscribers rowNeeds a configured email notification channel. Double opt-in by default.
rssnothingA link to /rss.xml and /atom.xml in the subscribe dialog.
webhooka subscribers rowVisitor-supplied HTTP(S) URL. Opt-in only; see the warning below.

RSS is not a stored subscription — it is a URL — so it adds nothing to the database and nothing to send.

Visitor-supplied webhooks need a network policy

Enabling "webhook" lets anonymous visitors make your deployment issue HTTP requests to a host they choose. Heyo Status rejects loopback, private, link-local, carrier-grade NAT and multicast literals, credentials in the URL, and reserved suffixes such as .local and .internal — but URL validation cannot see through DNS. Pair it with an egress policy if you enable it.

Set up email delivery

Before enabling email sign-ups, configure an email notification channel. Confirmation and incident mail use the first configured email channel, including its transport and from address. Without one, an email subscription request returns 503.

ts
import { email } from "@heyo-sh/heyo-status/notifications";notifications: {  channels: [    email({      transport: "resend",      apiKey: process.env.RESEND_API_KEY!,      from: "status@acme.com",      to: ["oncall@acme.com"],    }),  ],},subscribers: { enabled: true, methods: ["email", "rss"] },

The channel's own to list keeps receiving operational alerts; subscriber mail is addressed only to the subscription.

What subscribers receive

Only public, already-published lifecycle events:

  • incident.created, incident.updated, incident.resolved
  • maintenance.scheduled, maintenance.starting, maintenance.completed

Monitor-level events (monitor.down, monitor.recovered, ssl.expiring) are never sent to public subscribers — those are operational signals for your own channels.

A subscription may optionally name monitors through the API. A subscription with monitors: null (the default) receives everything; one with a list only receives events affecting those monitors, and global events — an incident with an empty affectedMonitors — always go to everyone.

Show the Subscribe button

With subscribers.enabled: true, <StatusPage /> shows a Subscribe button unless you pass subscribeHref or onSubscribe. It loads the bundled dialog when a visitor first opens it:

tsx
<StatusPage  snapshot={snapshot}  basePath={statusPage.basePath}  subscribersEnabled={statusPage.subscribers.enabled}  subscriberMethods={statusPage.subscribers.methods}/>

The dialog shows one tab per configured method and posts to ${basePath}/subscribers. To send visitors to your own page instead:

tsx
<StatusPage snapshot={snapshot} subscribersEnabled subscribeHref="/subscribe" />

Endpoints

MethodPathPurpose
POST/subscribersCreate a subscription. 202 pending or 201 subscribed.
GET/subscribers/confirm?token=Consume a single-use confirmation token.
GET/subscribers/:id/unsubscribeA self-contained HTML confirm page.
POST/subscribers/:id/unsubscribePerforms the removal from that page.
DELETE/subscribers/:idProgrammatic removal.
bash
curl -X POST https://status.acme.com/api/heyo-status/subscribers \  -H "content-type: application/json" \  -d '{"type":"email","target":"person@example.com"}'

Full request and response details are in the subscriber API reference, and the privacy reasoning behind the responses is in How public subscriptions work.

Operational notes

  • Subscriptions are identified by destination, so repeating a request is idempotent and cannot mail an address twice.
  • A pending confirmation is reused for 15 minutes before a new token is issued.
  • Deliveries are isolated per destination and written to the notification log.
  • A failure to list subscribers never fails an incident update.

Related

  • Double opt-in and SSRF protections
  • Admin API
  • Email channels
Notifications< PreviousReact RouterNext >

Powered by heyo

On this page

Choose a subscription methodSet up email deliveryWhat subscribers receiveShow the Subscribe buttonEndpointsOperational notes