Browse the docs

Status page data

Read a page's current state as JSON, embed a badge, subscribe to feeds, and let people subscribe. No authentication.

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

GET/public/pages/:ref/summary.json

The 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.
Request
curl "https://api.statusbee.co/public/pages/{ref}/summary.json"
Response
{
  "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

GET/public/pages/:ref/snapshot.json

Everything 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.
Request
curl "https://api.statusbee.co/public/pages/acme-cloud/snapshot.json"
Response
{
  "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

GET/public/pages/:ref/incidents/:id.json

An 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).
Request
curl "https://api.statusbee.co/public/pages/acme-cloud/incidents/91.json"
Response
{
  "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

GET/public/pages/:ref/badge.svg

A 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.
Markdown
![Acme Cloud status](https://api.statusbee.co/public/pages/acme-cloud/badge.svg)
Request
curl "https://api.statusbee.co/public/pages/acme-cloud/badge.svg"
Response (image/svg+xml)
<svg xmlns="http://www.w3.org/2000/svg" width="152" height="20" …>
  … Acme Cloud · Partial outage …
</svg>

RSS and Atom feeds

GET/public/pages/:ref/feed.rss

Open 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.
Request
curl "https://api.statusbee.co/public/pages/acme-cloud/feed.rss"
Response (application/rss+xml)
<?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

POST/public/pages/:ref/access

Trades 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.
Request
curl -X POST "https://api.statusbee.co/public/pages/acme-cloud/access" \
  -H "Content-Type: application/json" \
  -d '{
  "password": "••••••••"
}'
Response
{
  "statusCode": 200,
  "error": false,
  "message": null,
  "data": {
    "token": "eyJwIjo0LCJrIjoi…",
    "expires_in": 2592000
  }
}

Subscribe

POST/public/pages/:ref/subscribe

What 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 email
email, slack, discord, teams, webhook, telegram or sms.
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.
Request
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
  ]
}'
Response
{
  "statusCode": 200,
  "error": false,
  "message": null,
  "data": {
    "channel": "email",
    "status": "pending_confirmation",
    "already_subscribed": false
  }
}

Unsubscribe

GET/public/unsubscribe/:token

One-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.
Request
curl "https://api.statusbee.co/public/unsubscribe/unsub_5b7e…"
Response
{
  "statusCode": 200,
  "error": false,
  "message": null,
  "data": {
    "status": "unsubscribed"
  }
}