Skip to content
v0.3.8GitHub

Status pages

Verified against cerbix f5240f5Report a problem ↗

A status page tells people outside the on-call rotation what is working, which incidents explain the current state, and what maintenance is planned. This page covers visibility, components, how the overall status is composed, and how visitors subscribe.

An organization admin creates a page with POST /api/v1/organizations/{orgID}/status-pages. Example data:

{
"slug": "checkout",
"title": "Checkout status",
"visibility": "public",
"project_id": "<project-id>"
}

slug and title are required. project_id is optional: without it the page belongs to the organization and may hold components from several projects. The slug cannot be changed later; PATCH /api/v1/status-pages/{pageID} edits title and visibility. The public page is served at /status/<slug>.

Visibility Who can view it
internal Members of the organization, through the authenticated preview. This is the default.
public Anyone, without a session.
unlisted Anyone holding the page token: /status/<slug>?token=<token>.

An unlisted page gets a random 128-bit token when it is created or switched to unlisted. Switching away from unlisted deletes the token; switching back mints a new one, so old links stop working. The public endpoints answer 404 for an internal page and for a missing or wrong token.

Public renders are cached for 5 s. An incident update can take that long to appear.

Each component renders from exactly one source. Add one with POST /api/v1/status-pages/{pageID}/components and the fields name, description, group, position, plus service_id, monitor_id or manual_status.

Source Status shown
service Declared maintenance window in force → maintenance; down → major_outage; degraded → degraded; healthy → operational; anything else → no_data
monitor down → major_outage; up → operational; pending or deleted monitor → no_data
manual The manual_status you set: operational, degraded, partial_outage, major_outage or maintenance; none set → no_data

no_data cannot be set by hand: it means nothing was measured. A component whose state could not be read carries unavailable: true on the public payload, so a failed read never looks like a calm value. A bound monitor or Service must belong to the page’s organization and, for a project page, to its project; otherwise the API answers 400 binding not found.

Components also carry 90-day uptime and a daily strip. When uptime cannot be quoted, withheld_reason says why. For a monitor-backed component whose monitor has no data older than the 90 days, uptime_since gives the UTC day the data starts. See Truthful rendering.

A public render with more than 500 components is refused as a whole with 503. The authenticated preview still lists everything.

The page summary keeps measured and unmeasured components apart:

summary_state Meaning
operational Every measured component is operational.
impaired At least one measured component is worse. summary names the worst.
no_data Nothing on the page was measured.
empty The page has no components.

Measured statuses roll up from best to worst: operational, maintenance, degraded, partial_outage, major_outage. unmeasured_count reports how many components had no data; they never count as healthy.

Active incidents never change a component’s status, but they do change the headline:

  • A measured impairment keeps its own headline; the active incident count and worst impact are added below it.
  • Otherwise, with active incidents, the headline is 1 active incident or <N> active incidents, followed by the worst impact and the component truth, such as “All measured services are currently operational.”
  • “All systems operational” appears only with zero active incidents.

Worst impact orders critical, major, minor, none. An old unresolved incident still counts until it is resolved.

A page reports incidents from its own project and from every project its components draw from. That includes project-level incidents with no anchor.

  • Current status by service comes first. A component tied to an active incident shows Active incident or <N> active incidents and links to it.
  • Active incidents are compact rows with one status badge, one impact badge, opened and updated times, the update count and a two-line preview of the latest update. Up to eight are ordered by impact, then by latest activity. Above eight they are grouped by impact.
  • Scheduled maintenance lists active and upcoming windows.
  • Past incidents shows the ten most recent incidents resolved in the last 90 days, with their postmortems. When there are more, View incident history opens a history page that walks the 90 days by UTC calendar month.

The page render carries at most those ten in recent_incidents and sets recent_incidents_more when the 90 days hold more. The history is served month by month, newest first, at most 50 incidents per response:

Terminal window
curl "https://cerbix.example.com/api/v1/public/status-pages/checkout/history?month=2026-10"

month is YYYY-MM (default: the current UTC month) and must be one of the months in the response’s months; pass next_cursor as cursor for the next 50. Unlisted pages need &token=<token>; members read any page at /api/v1/status-pages/{pageID}/history. Uncached public history requests are limited: beyond the limit the answer is 429 history_busy with Retry-After.

The public payload strips project, monitor and Service IDs, Alertmanager keys, acknowledging users and update authors. The incident source (auto, manual, api) is not displayed. Each incident carries affected_component_ids, which lists only component IDs from the same page. Service impact links from Incidents are never public.

Visitors subscribe by email with double opt-in. POST /api/v1/public/status-pages/{slug}/subscribers with {"email": …}, plus ?token= for an unlisted page, answers 202 and sends a confirmation link. Confirmed subscribers receive an email when an incident on any project the page reports opens, is updated or resolves. Organization admins list and remove subscribers at /api/v1/status-pages/{pageID}/subscribers.

Each page also has an incident feed with the 20 most recent incidents, newest first:

Terminal window
curl "https://cerbix.example.com/api/v1/public/status-pages/checkout/feed?format=atom"

format is rss (default), atom or json. Unlisted pages need &token=<token>. Internal pages serve the feed only to members at /api/v1/status-pages/{pageID}/feed.

Branding is instance-wide, not per page. A global admin sets it with PUT /api/v1/settings/branding: product_name (up to 60 characters), accent_color (#rrggbb), logo_url, footer_text, support_url and an announcement with level info, warning or critical. The public page shows the brand mark and page title in its header, and the footer text and support link at the bottom. The brand mark is logo_url when it is set and the default cerbix mark otherwise; a custom accent gets a readable text colour automatically.