Skip to content
ScaledPapers

Account

Status Pages API

The Status Pages API is at https://api.scaledpapers.com. Authenticate with the same key you use for the Checks API: Authorization: Bearer sp_…. An agent can call the same pages from MCP. Creating and revoking keys still happens in API Keys. The key acts as the workspace where it was created (see API keys in a team). If an admin is later changed to member, existing keys keep working until revoked.

Every request acts as the account that owns the key — you can only see and change your own status pages.

Create a status page

curl https://api.scaledpapers.com/v1/sites \
  -H "Authorization: Bearer sp_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme",
    "slug": "acme",
    "url": "https://acme.com"
  }'
  • name and slug are required. Slug is lowercase letters, numbers, and hyphens (2-40 chars) and cannot change later.
  • url is optional — it creates a website component for the page.
  • visibility is optional (public default, or internal for a private page). Private requires Pro and a password of at least 8 characters.
  • custom_domain is optional on create (Pro). Subdomain only, such as status.acme.com. The page stays on {slug}.status.scaledpapers.com until DNS is verified.
  • The page is live at https://acme.status.scaledpapers.com.
  • A taken slug returns 409 with {"detail":"That slug is taken"}.
  • A Free workspace that sends visibility: "internal" or a custom domain gets 403.

Create a private page (visibility stays internal on the wire):

curl https://api.scaledpapers.com/v1/sites \
  -H "Authorization: Bearer sp_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Internal",
    "slug": "acme-internal",
    "visibility": "internal",
    "password": "at-least-8-chars"
  }'

List and read pages

curl https://api.scaledpapers.com/v1/sites \
  -H "Authorization: Bearer sp_…"

Each row includes slug, name, and the worst open incident status. GET /v1/sites/{slug} returns the full bundle: components, groups, incidents, uptime payload, and Slack connection state. Site objects include visibility (public or internal), has_password (never the password itself), publicUrl, and custom-domain fields (custom_domain, custom_domain_status).

Update page info

PATCH /v1/sites/{slug} updates page identity. Send visibility as public or internal. Private pages require Pro and a password of at least 8 characters (omit password to keep the current one). Switching to public clears the password. A Free workspace that tries to set Private gets 403.

Send custom_domain as a hostname such as status.acme.com, or null to remove it. Apex hosts and *.scaledpapers.com are rejected. Custom domains require Pro (403 on Free). After DNS is in place, POST /v1/sites/{slug}/custom-domain/verify checks the CNAME to cname.scaledpapers.com and the TXT challenge. publicUrl becomes https://{custom_domain} only when the domain is active.

Visitors unlock a private page with POST /sites/{slug}/unlock on the monitor (or /unlock on the status page host). That is not part of the authenticated Status Pages API.

Delete a page

DELETE /v1/sites/{slug} removes the public page, its components, incidents, and the owner Slack connection. This cannot be undone.

Add a component

curl https://api.scaledpapers.com/v1/sites/acme/components \
  -H "Authorization: Bearer sp_…" \
  -H "Content-Type: application/json" \
  -d '{"name": "Payments API", "url": "https://api.acme.com"}'

Components are the services shown on the public page — they are not checks. Rename with PATCH /v1/sites/{slug}/components/{id}; delete with DELETE.

Use the Checks API: send site_id, site_slug, and component_id together on PATCH /v1/endpoints/{id}. alert_incident_enabled opens one incident for a flapping period, not a new incident on every recovery. See Incidents. display_metrics shows latency on the public page. A component can be linked to only one check.

Create an incident

curl https://api.scaledpapers.com/v1/sites/acme/incidents \
  -H "Authorization: Bearer sp_…" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Payments API errors",
    "body": "We are looking into the issue.",
    "status": "investigating",
    "impact": "major",
    "component_ids": ["m3vnq6ytahvq"]
  }'
  • title and body are required. component_ids is optional: it takes component public ids — the same 12-character ids as in console component URLs (/app/{slug}/components/{id}) — internal integer ids also work. Omit it for a site-wide incident with no affected components.
  • status: investigating, identified, monitoring, resolved. impact: minor, major, critical.
  • Backfill a past incident with opened_at + resolved_at (status is forced to resolved).
  • Email subscribers and Slack notifications fire exactly as they do from the console. A site-wide incident notifies only visitors subscribed to all components; a component incident also notifies subscribers watching that component.

Post an update

curl https://api.scaledpapers.com/v1/sites/acme/incidents/{public_id}/updates \
  -H "Authorization: Bearer sp_…" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "identified",
    "body": "Root cause found, deploying a fix."
  }'

{public_id} is the 12-character id from the incident (incidents/{id} on the public page). Status resolved closes the incident. Resolving from the Checks API (a linked check recovering) posts the same update shape.

The response is 201 with the full incident: status is the new current status, updates lists all updates newest-first (the first entry is the one you just posted), and resolved_at stays null until a resolved update sets it. Subscribers and Slack are notified before the response returns.

Component groups

curl https://api.scaledpapers.com/v1/sites/acme/component-groups \
  -H "Authorization: Bearer sp_…" \
  -H "Content-Type: application/json" \
  -d '{"name": "APIs"}'

POST /v1/sites/{slug}/component-groups adds a group. PATCH /v1/sites/{slug}/component-groups/{id} renames it (name) or sets position. DELETE /v1/sites/{slug}/component-groups/{id} removes it. The id is the integer from the create response.

Slack

POST /v1/sites/{slug}/integrations/slack/start returns a URL. Open it to finish connecting Slack. POST /v1/sites/{slug}/integrations/slack/disconnect removes the connection. GET /v1/sites/{slug} includes whether Slack is connected.

What is not on the API yet

Visitor subscriber management stays console-only for now.