Account
Status Pages API
The Status Pages API is at https://api.quickstatus.dev. 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.quickstatus.dev/v1/sites \
-H "Authorization: Bearer sp_…" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme",
"slug": "acme",
"url": "https://acme.com"
}'
nameandslugare required. Slug is lowercase letters, numbers, and hyphens (2-40 chars) and cannot change later.urlis optional — it creates a website component for the page.visibilityis optional (publicdefault, orinternalfor a private page). Private requires Pro and apasswordof at least 8 characters.custom_domainis optional on create (Pro). Subdomain only, such asstatus.acme.com. The page stays on{slug}.quickstatus.devuntil DNS is verified.- The page is live at
https://acme.quickstatus.dev. - A taken slug returns
409with{"detail":"That slug is taken"}. - A Free workspace that sends
visibility: "internal"or a custom domain gets403.
Create a private page (visibility stays internal on the wire):
curl https://api.quickstatus.dev/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.quickstatus.dev/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: checks (the page's components, each with id and public_id), 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 *.quickstatus.dev 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.quickstatus.dev 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.quickstatus.dev/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.
Link a check to a component
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.quickstatus.dev/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"]
}'
titleandbodyare required.component_idsis 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. An id that is not a component on this page is a400, so a typo never turns into a site-wide incident.status: investigating, identified, monitoring, resolved (default investigating).impact: minor, major, critical (default major). Any other value is a400.- Backfill a past incident with
opened_at+resolved_at(status is forced toresolved). - 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.quickstatus.dev/v1/sites/acme/incidents/{id}/updates \
-H "Authorization: Bearer sp_…" \
-H "Content-Type: application/json" \
-d '{
"status": "identified",
"body": "Root cause found, deploying a fix."
}'
{id} is the incident's 12-character id field (the same id as incidents/{id} on the public page). status must be one of investigating, identified, monitoring, resolved; leave it out to keep the current one. Anything else is a 400. 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.
PATCH /v1/sites/{slug}/incidents/{id} edits title, impact, opened_at, and resolved_at only. Sending status or body is a 400 that points to the updates route above. component_ids is also a 400: set components when you create the incident.
Component groups
curl https://api.quickstatus.dev/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.