1. Documentation
  2. HTTP API
  3. API overview
ReadmenpmGitHub
  • Introduction
  • Quickstart
  • Configuration file
  • Monitors
  • Checks and scheduling
  • Notifications
  • Incidents and maintenance
  • Subscribers
  • Metrics and badges
  • Identity and appearance
  • Telemetry
  • The check run
  • Uptime and history
  • Automatic incidents
  • Notification delivery
  • Public subscriptions
  • StatusPage component
  • Themes
  • UI primitives
  • Colour mode
  • React Router
  • Next.js
  • Astro
  • SQLite
  • Cloudflare D1
  • PostgreSQL
  • Schema and migrations
  • Cloudflare Workers
  • Vercel
  • Self-hosting
  • API overview
  • Status endpoints
  • Incident and maintenance endpoints
  • Subscriber endpoints
  • Badges, feeds and metrics
  • Admin endpoints
  • CLI commands
  • Package exports
  • Security
  • Troubleshooting

API overview

Routing, authentication, error shapes and the full endpoint map.

Every endpoint is served by one catch-all route. statusPage.handler strips basePath from the incoming URL, so a path below is always reached at basePath + path — by default /api/heyo-status.

text
https://status.acme.com/api/heyo-status/status└──────── origin ──────┘└── basePath ─┘└ path ┘

Endpoint map

MethodPathAuthEnabled by
GET/status—always
GET/status/summary—always
GET/monitors—always
GET/monitors/:name—always
GET/monitors/:name/uptime—always
GET/badge/:name.svg—metrics.badges
GET/metrics—metrics.prometheus
GET/rss.xml—incidents.enabled
GET/atom.xml—incidents.enabled
GET/incidents—incidents.enabled
GET/incidents/:id—incidents.enabled
GET/maintenance—maintenance.enabled
POST/subscribers—subscribers.enabled
GET/subscribers/confirm—subscribers.enabled
DELETE/subscribers/:id—subscribers.enabled
GET/subscribers/:id/unsubscribe—subscribers.enabled
POST/subscribers/:id/unsubscribe—subscribers.enabled
GET/healthz—always
POST/admin/checks/runtokenalways
POST/admin/incidentstokenincidents.enabled
POST/admin/incidents/:id/updatestokenincidents.enabled
PATCH/admin/incidents/:idtokenincidents.enabled
DELETE/admin/incidents/:idtokenincidents.enabled
POST/admin/maintenancetokenmaintenance.enabled
PATCH/admin/maintenance/:idtokenmaintenance.enabled
DELETE/admin/maintenance/:idtokenmaintenance.enabled
GET/admin/notifications/logtokenalways

A disabled feature answers 404 { "error": "This feature is disabled." }, which is deliberate — it does not reveal whether the route exists.

Authentication

Everything under /admin/* requires:

http
Authorization: Bearer <HEYO_STATUS_API_TOKEN>

The token comes from adminToken in the configuration, or the HEYO_STATUS_API_TOKEN environment variable. Comparison is constant-time.

SituationResponse
No token configured503 { "error": "The management API is disabled. Set adminToken or HEYO_STATUS_API_TOKEN." }
Wrong or missing header401 { "error": "Unauthorized." }

Public endpoints are unauthenticated by design — a status page is meant to be readable during an outage, including by people who cannot sign in.

Status codes

CodeMeaning
200Success.
201Created — an incident, a maintenance window, a confirmed subscription.
202Accepted — a subscription awaiting email confirmation.
204Deleted. No body.
400Invalid input. The message names the field.
401Missing or wrong bearer token.
404Not found, or the feature is disabled.
501Manual checks require the status-page runtime.
503Management API disabled, or an email delivery dependency failed.
500Unexpected error, including an unreachable database.

Errors are always JSON:

json
{ "error": "severity must be a valid incident severity." }

Read routes have nothing to recover from, so a database that is unreachable — an unbound D1 binding, a missing DATABASE_URL — is reported with the same shape and the actionable message, rather than a plain-text 500.

Conventions

  • Request bodies must be JSON objects; arrays and scalars are rejected.
  • Timestamps in requests and responses are ISO-8601 (2026-01-01T02:00:00Z).
  • List filters accept comma-separated values: ?status=investigating,identified.
  • limit and offset are non-negative integers.
  • String arrays are trimmed and de-duplicated; empty entries are rejected.
  • Monitor names in a path must be percent-encoded.

Quick examples

bash
BASE=https://status.acme.com/api/heyo-statuscurl "$BASE/status/summary"curl "$BASE/monitors/API/uptime"curl "$BASE/incidents?status=investigating&limit=5"curl -X POST "$BASE/admin/incidents" \  -H "authorization: Bearer $HEYO_STATUS_API_TOKEN" \  -H "content-type: application/json" \  -d '{"title":"Degraded API","severity":"major","affectedMonitors":["API"],"message":"Investigating."}'

Calling the handler directly

The HTTP surface is available without a framework, which is what the tests and the CLI dev server use:

ts
const response = await statusPage.handler(  new Request("https://status.acme.com/api/heyo-status/status"),);

Router-relative paths are passed through unchanged, so new Request("http://localhost/status") works too.

Related

  • Status endpoints
  • Admin endpoints
  • Security checklist
Self-hosting< PreviousStatus endpointsNext >

Powered by heyo

On this page

Endpoint mapAuthenticationStatus codesConventionsQuick examplesCalling the handler directly