Public pages are served from a prebuilt snapshot, so these endpoints are fast and stay up independently of the rest of the platform. They answer with Cache-Control: public, s-maxage=30, stale-while-revalidate=86400; poll no more often than every 30 seconds. Only published pages of active accounts are served; anything else is 404. :ref is the page slug (acme-cloud) or one of its verified custom domains (status.acme.com).
A password-protected page answers 401 with data.code: "PAGE_LOCKED" until the request carries an access token in the X-Page-Access header. Get one from the access endpoint below; it stays valid for 30 days or until the page's password changes.
The hosted page itself serves the same documents under its own address: https://acme-cloud.statusbee.co/summary.json, /feed.rss, /feed.atom and /badge.svg, plus permalinks at /incidents/:id and /maintenance/:id.
Responses here are the documents themselves, not wrapped in the data envelope.
Summary
/public/pages/:ref/summary.jsonThe stable subset for integrations: overall status, each component's status, open incidents and upcoming maintenance. Fields are added over time, never removed.
Path parameters
refstringrequired- The page's address prefix, the part before
.statusbee.co, or a verified custom domain.
curl "https://api.statusbee.co/public/pages/{ref}/summary.json"{
"status": "partial_outage",
"page": {
"name": "Acme Cloud",
"slug": "acme-cloud",
"url": "https://acme-cloud.statusbee.co"
},
"components": [
{
"id": 21,
"name": "REST API",
"status": "operational"
},
{
"id": 22,
"name": "Webhooks",
"status": "partial_outage"
}
],
"active_incidents": [
{
"id": 91,
"title": "Elevated webhook delivery latency",
"status": "identified",
"impact": "major",
"started_at": "2026-09-14T09:02:11.000Z"
}
],
"maintenance": [
{
"id": 17,
"title": "Database upgrade",
"status": "scheduled",
"scheduled_start": "2026-09-20T02:00:00.000Z",
"scheduled_end": "2026-09-20T03:00:00.000Z"
}
],
"generated_at": "2026-09-14T09:02:11.000Z"
}Full snapshot
/public/pages/:ref/snapshot.jsonEverything the status page renders: page settings and resolved branding, groups, components with daily uptime, open incidents with their updates, upcoming maintenance, and history (what resolved or completed inside the uptime window). The document the hosted page itself is built from.
Path parameters
refstringrequired- Page slug or custom domain.
curl "https://api.statusbee.co/public/pages/acme-cloud/snapshot.json"{
"version": 12,
"generated_at": "2026-09-14T09:02:11.000Z",
"page": {
"id": 4,
"slug": "acme-cloud",
"name": "Acme Cloud",
"visibility": "public",
"published": true,
"serving": {
"ok": true,
"reason": null
},
"timezone": "UTC",
"uptime_display_days": 90,
"powered_by_hidden": false,
"url": "https://acme-cloud.statusbee.co",
"hostnames": [
"status.acme.com"
]
},
"status": "partial_outage",
"groups": [
{
"id": 8,
"name": "API",
"position": 1,
"collapsed_default": false
}
],
"components": [
{
"id": 21,
"group_id": 8,
"name": "REST API",
"status": "operational",
"position": 0,
"display_uptime": true,
"start_date": "2026-06-01",
"uptime_daily": [
{
"date": "2026-09-13",
"up_s": 86100,
"degraded_s": 0,
"down_s": 300,
"maint_s": 0,
"unknown_s": 0
}
]
}
],
"active_incidents": [
{
"id": 91,
"title": "Elevated webhook delivery latency",
"status": "identified",
"impact": "major",
"started_at": "2026-09-14T09:02:11.000Z",
"resolved_at": null,
"component_ids": [
22
],
"updates": [
{
"id": 241,
"status": "identified",
"body_md": "The cause is a stuck consumer on the delivery queue.",
"display_at": "2026-09-14T09:02:11.000Z"
}
]
}
],
"maintenance": [
{
"id": 17,
"title": "Database upgrade",
"status": "scheduled",
"scheduled_start": "2026-09-20T02:00:00.000Z",
"scheduled_end": "2026-09-20T03:00:00.000Z"
}
],
"history": {
"since": "2026-06-18",
"incidents": [],
"maintenance": []
}
}One incident
/public/pages/:ref/incidents/:id.jsonAn incident with its full timeline, for permalinks. Open incidents and everything inside the page's history window come from the snapshot; older ids are still answered.
Path parameters
refstringrequired- Page slug or custom domain.
idintegerrequired- Incident id.
/public/pages/:ref/maintenance/:id.json answers the same way for a maintenance window (maintenance instead of incident).curl "https://api.statusbee.co/public/pages/acme-cloud/incidents/91.json"{
"incident": {
"id": 91,
"title": "Elevated webhook delivery latency",
"status": "identified",
"impact": "major",
"started_at": "2026-09-14T09:02:11.000Z",
"resolved_at": null,
"postmortem_md": null,
"component_ids": [
22
],
"updates": [
{
"id": 241,
"status": "identified",
"body_md": "The cause is a stuck consumer on the delivery queue.",
"display_at": "2026-09-14T09:02:11.000Z"
}
]
},
"page": {
"id": 4,
"slug": "acme-cloud",
"name": "Acme Cloud",
"url": "https://acme-cloud.statusbee.co"
},
"components": [
{
"id": 22,
"name": "Webhooks",
"status": "partial_outage"
}
],
"generated_at": "2026-09-14T09:02:11.000Z"
}Status badge
/public/pages/:ref/badge.svgA small SVG showing the overall status, for a README or an internal dashboard. Cached for 60 seconds.
Path parameters
refstringrequired- Page slug or custom domain.
curl "https://api.statusbee.co/public/pages/acme-cloud/badge.svg"<svg xmlns="http://www.w3.org/2000/svg" width="152" height="20" …>
… Acme Cloud · Partial outage …
</svg>RSS and Atom feeds
/public/pages/:ref/feed.rssOpen incidents, upcoming maintenance and the recent history as a feed, newest first, 50 items. feed.atom serves the same items in Atom.
Path parameters
refstringrequired- Page slug or custom domain.
curl "https://api.statusbee.co/public/pages/acme-cloud/feed.rss"<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Acme Cloud status</title>
<item>
<title>Elevated webhook delivery latency</title>
…
</item>
</channel>
</rss>Unlock a password-protected page
/public/pages/:ref/accessTrades the page password for an access token. Send the token as X-Page-Access on every other read of that page. Rate limited to 10 attempts per 15 minutes per address; a wrong password answers 401 with data.code: "PASSWORD_INVALID".
Path parameters
refstringrequired- Page slug or custom domain.
Body
passwordstring- The password the page owner shared.
challenge_tokenstring- Turnstile token, when the page has bot protection on.
curl -X POST "https://api.statusbee.co/public/pages/acme-cloud/access" \
-H "Content-Type: application/json" \
-d '{
"password": "••••••••"
}'{
"statusCode": 200,
"error": false,
"message": null,
"data": {
"token": "eyJwIjo0LCJrIjoi…",
"expires_in": 2592000
}
}Subscribe
/public/pages/:ref/subscribeWhat the page's Subscribe button calls. Email addresses get a confirmation email; Slack, Discord, Teams and webhook URLs get a test post (a type: "ping" envelope for plain webhooks) and are active immediately if it succeeds; Telegram returns a bot deep link. Rate limited to 20 attempts per 15 minutes per address. Callable from any origin.
Path parameters
refstringrequired- Page slug or custom domain.
Body
channelstringdefault emailemail,slack,discord,teams,webhook,telegramorsms.destinationstring- Address, URL or number. Not used for Telegram.
component_idsarray- Follow only these components. Omit for the whole page.
localestring- Preferred language tag.
challenge_tokenstring- Turnstile token, when the page has bot protection on.
websitestring- Honeypot. Leave it out; anything in it is treated as a bot.
curl -X POST "https://api.statusbee.co/public/pages/acme-cloud/subscribe" \
-H "Content-Type: application/json" \
-d '{
"channel": "email",
"destination": "ops@customer.example",
"component_ids": [
21
]
}'{
"statusCode": 200,
"error": false,
"message": null,
"data": {
"channel": "email",
"status": "pending_confirmation",
"already_subscribed": false
}
}Unsubscribe
/public/unsubscribe/:tokenOne-click unsubscribe. The link in every email opens the page's own /unsubscribe/:token, which asks first and then calls this; mailbox providers that implement RFC 8058 POST here directly. GET /public/unsubscribe/:token/preview describes the subscription (masked address, page) without changing anything.
Path parameters
tokenstringrequired- The subscriber's unsubscribe token from the email.
curl "https://api.statusbee.co/public/unsubscribe/unsub_5b7e…"{
"statusCode": 200,
"error": false,
"message": null,
"data": {
"status": "unsubscribed"
}
}