1. Documentation
  2. HTTP API
  3. API overview
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

API overview

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

Use the public routes to read status; use /admin/* with a bearer token to run checks or manage incidents. They all live under one catch-all route, /api/heyo-status by default. The paths in the table below are relative to that base path.

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

For example, read the summary without a token or create an incident with an admin token:

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 $ADMIN_TOKEN" \  -H "content-type: application/json" \  -d '{"title":"Degraded API","severity":"major","affectedMonitors":["API"],"message":"Investigating."}'

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

If a feature is disabled, its routes return 404 { "error": "This feature is disabled." } rather than exposing a disabled endpoint.

Authentication

Everything under /admin/* requires:

http
Authorization: Bearer <admin-token>

The token comes only from adminToken in the configuration. Comparison is constant-time.

SituationResponse
No token configured503 { "error": "The management API is disabled. Set adminToken in heyo-status.config.ts." }
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." }

If the database is unavailable, read routes return a JSON error too. Check the message for an unbound D1 binding or a failed connection instead of expecting 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.

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
Self-hosting< PreviousStatus endpointsNext >

Powered by heyo

On this page

Endpoint mapAuthenticationStatus codesConventionsCalling the handler directly