Skip to content
Docs/Internal status pages

Status pages

Internal status pages

Customers get the public page. The team gets a page that also shows the incidents you have not announced, who is on call and who is working on it, behind a sign-in that takes one email.

Three kinds of page

VisibilityWho can read itWithout access
publicAnyonen/a
internalWhoever signs in as the page allows: a verified address on an allowed domain, an invited address, a member of the workspace; or a request with a shared link, an access token or (if you say so) from one of your networks404, on every surface
privateMembers of the workspace, as a preview in the dashboard session404

An internal page lives where a public one would: https://upbutler.com/s/<slug>, https://<slug>.upbutler.com or your custom domain. A workspace can have both: a public page for customers and an internal page for the team, with components on the same monitors.

# 1. Make the page internal (Starter and up)
curl -X PATCH https://upbutler.com/api/v1/pages/acme-internal \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" -H "Content-Type: application/json" \
  -d '{"visibility": "internal"}'

# 2. Say who may sign in, and what the page shows them
curl -X PUT https://upbutler.com/api/v1/pages/acme-internal/access \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" -H "Content-Type: application/json" \
  -d '{"domains": ["acme.com"], "emails": ["[email protected]"],
       "sections": {"monitors": true, "suspects": true}}'

In the dashboard: Status pages → the page → Settings → Visibility → Internal, then the Access tab.

Signing in

Somebody who opens the page without a session gets a sign-in screen. They type their work email; if the address may view the page, a six-digit code and a link arrive. That is the whole flow: no account, no password, no invitation to accept.

  • Email domains (domains): every verified address at acme.com. Matching is exact: sub.acme.com and acme.com.evil.net are other domains. Public mailbox providers (gmail.com and the like) are refused as a domain; invite those addresses one by one.
  • Invited addresses (emails): contractors, an auditor, a partner.
  • Workspace members (members, on by default): on upbutler.com their dashboard session opens the page; on the page's own host they sign in with the same email.
  • Continue with Google (google), when Google sign-in is configured: Google verifies the address, the allow-list decides.

The form answers the same whether or not an address is allowed, and mail is only sent to allowed addresses, so it cannot be used to probe the list or to mail strangers. Codes work once, for 15 minutes, five tries per code and ten per address and hour.

What a viewer session is

A session for that page: its own cookie, 30 days by default (sessionDays, 1 to 365). It is not a user of the workspace and not a seat. It cannot open the dashboard, the REST API or the workspace MCP server; it can read the page and, if you allow it, write notes in the incident room. The Access tab lists who is signed in; revoke one session, everything of an address, or everyone (POST /pages/:id/access/viewers/revoke). Taking a domain or an address off the list ends its sessions on the next request.

# A shared link for the office wallboard, and a token for internal agents (shown once)
curl -X POST https://upbutler.com/api/v1/pages/acme-internal/access/links \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Office wallboard", "expiresInDays": 365}'
# → { "id": "pal_…", "token": "ubp_…", "url": "https://acme-internal.upbutler.com?access=ubp_…" }
  • Wallboards and TVs: open the url once. The token moves into a cookie and leaves the address bar. Read-only: no notes, no subscriptions.
  • Internal agents: send the token as Authorization: Bearer ubp_… to the page's machine endpoints. Without it they answer 404 like the rest of the page.
  • Tokens are shown once and stored as a hash. Rotate one (POST …/links/:id/rotate) and the old token stops working on the next request; give it an expiry; delete it. Twenty wrong tokens from one address lock that address out for ten minutes.
  • Networks (ip.cidrs): with grant, a request from one of them reads the page without signing in (an office or VPN egress address, for wallboards with no keyboard). With restrictLinks, links and tokens only work from them. The address is the one UpButler trusts for rate limits: a forwarded header a client made up is not believed.
# Internal agents: the same endpoints as a public page, with the page access token
curl https://acme-internal.upbutler.com/status.agent.json -H "Authorization: Bearer ubp_…"
curl https://acme-internal.upbutler.com/status.json       -H "Authorization: Bearer ubp_…"

# MCP (read-only): get_verdict, get_status, list_incidents
{ "mcpServers": { "acme-internal-status": {
    "url": "https://acme-internal.upbutler.com/mcp",
    "headers": { "Authorization": "Bearer ubp_…" } } } }

What the page shows the team

Each line is a switch on the Access tab (sections in the API). The defaults show people and incidents and nothing that can carry a hostname.

SectionShowsDefault
Internal incidents
internalIncidents
Incidents not marked public that are on this page or touch one of its componentson
Team notes
notes
Internal timeline notes written by people and agentson
Who is on call
onCall
The person or agent on call now, per scheduleon
Who is working on it
claims
Who claimed or acknowledged an open incident, and the incident room roleson
Monitor names
monitors
The monitors behind each component and their stateoff
Raw diagnostics
diagnostics
Monitor targets (URL without query string or credentials, host:port), automatic check errors, AI analysis. May show hostnamesoff
Suspect deploys and pull requests
suspects
What changed before the incident, and deploys on its timelineoff
Runbooks and tasks
runbooks
The runbooks attached to an incident and the room's task listoff
Dependency status
upstream
Status of the third-party services the workspace depends onoff
Upcoming drills
drills
The next scheduled incident drillsoff

Internal-only components: mark a component "Internal only" (internalOnly: true) and it is on the internal page and on no public surface. It stays hidden if the page is ever made public.

Every surface, same rule

The page, /history, incident pages, /status.json, /status.agent.json, /.well-known/status, /mcp, the feeds, badges, the embed, /llms.txt and the public API under /api/v1/public/pages/<slug> all answer 404 without a viewer session or a token, with the same body a slug that does not exist gets. With access they answer with Cache-Control: private, no-store, X-Robots-Tag: noindex and no wildcard CORS header; /robots.txt on the page's host disallows everything. The sign-in screen itself is served with status 404: a person sees the form, a crawler sees "not found". Turn off signInBranding and the screen does not name the page either.

Analytics count an internal page's views apart from everything public: page views by signed-in viewers and reads by agents, per day, with no visitor estimate and no referrers, countries or devices.

Subscriptions

Signed-in viewers and members can subscribe by email, to the page, to components (internal-only ones included) or to one incident. The address has to be one the page allows. There are no webhook, Slack, Discord or feed subscriptions on an internal page: they would carry internal incidents out of the company. For chat, use the workspace's alert channels and the incident room's thread.

Plans

PlanInternal pagesViewersShared links and tokens
Free–––
Starter1Unlimited20 per page
Pro3Unlimited20 per page
Business20Unlimited20 per page

Viewers are not seats: you pay for pages, not for the people who read them. An internal page counts as one of the plan's status pages too. After a downgrade, internal pages beyond the plan become private (nothing is deleted, the access settings stay) and come back as internal after an upgrade, never as public.

Single sign-on

SAML / OIDC sign-in for viewers is not built. Email codes on an allowed domain cover the same ground for most teams (whoever can read mail at acme.com gets in, and loses access with their mailbox). The access layer treats "how the address was verified" as a detail of the session, so an identity provider is one more way to verify, not a redesign; ask us if you need it.