Beacon

API Reference

API: REST resources

Everything you can do in the dashboard for a workspace — pages, components, monitors, incidents, maintenance, subscribers and webhooks — is available over the REST API with the same plan limits. The machine-readable contract is the OpenAPI 3.1 document:

https://usebeacon.pro/api/v1/openapi.json

Conventions

  • Authenticate with a workspace token (see Authentication). GET needs the read scope; everything else needs write.
  • Resources live under the status page slug. A slug or id from another workspace is always 404.
  • Single objects come back as {"data": {…}}. Lists add links and meta.
  • PATCH accepts any subset of fields; omitted fields keep their values. Deletes return 204.
  • Errors are JSON with a stable code. Plan limits return 402 plan_limit_reached. See Errors & Rate Limits.
  • The older ingest endpoints (POST pages/{slug}/incidents, PATCH incidents/{id}, …) still work unchanged and keep their flat response shape.

Cursor pagination

Lists return up to per_page items (default 25, max 100). Pass meta.next_cursor back as cursor until it is null.

curl "https://usebeacon.pro/api/v1/status-pages/acme/incidents?per_page=50&state=open" \
  -H "Authorization: Bearer bchk_..."

{
  "data": [ { "id": 42, "title": "Elevated errors", "state": "investigating", "updates": [ … ], … } ],
  "links": { "next": "…?cursor=eyJpZCI6NDIsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0" , … },
  "meta": { "per_page": 50, "next_cursor": "eyJpZCI6NDIsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0", "prev_cursor": null, … }
}

Status pages

GET /api/v1/status-pages List pages
POST /api/v1/status-pages Create (name required; slug derived if omitted). Counts against max_status_pages.
GET /api/v1/status-pages/{pageSlug} Get one page
PATCH /api/v1/status-pages/{pageSlug} Update name, slug, description, timezone, is_public, theme, incident_notifications_enabled
DELETE /api/v1/status-pages/{pageSlug} Delete the page and everything on it

Components

GET /api/v1/status-pages/{pageSlug}/components List in display order
POST /api/v1/status-pages/{pageSlug}/components Create (name; status defaults to operational; appended to the end)
PATCH /api/v1/status-pages/{pageSlug}/components/{componentId} Update name, description, status, position. A status change fires component webhooks and dependency cascades.
DELETE /api/v1/status-pages/{pageSlug}/components/{componentId} Delete (auto-created monitors go with it)
POST /api/v1/status-pages/{pageSlug}/components/reorder Body {"ids": [...]} with every component id in the new order

Monitors

GET /api/v1/status-pages/{pageSlug}/monitors List with live state, last check and uptime
POST /api/v1/status-pages/{pageSlug}/monitors Create: name, type (http|heartbeat|tcp|ping|dns), url, host, port, dns_record_type, dns_expected_value, http_method, expected_status_code, keyword, keyword_match_type, interval_minutes, timeout_seconds, consecutive_threshold, confirm_from_locations, confirmation_quorum, expiry_alerts_enabled, expiry_alert_days, allow_cold_start, cold_start_timeout_seconds, check_window_start/end (HH:MM), status_component_id, enabled
PATCH /api/v1/status-pages/{pageSlug}/monitors/{monitorId} Update any subset (type is create-only)
DELETE /api/v1/status-pages/{pageSlug}/monitors/{monitorId} Delete

Incidents

GET /api/v1/status-pages/{pageSlug}/incidents?state=open List newest first, with updates and component_ids. state takes comma-separated states or "open".
POST /api/v1/status-pages/{pageSlug}/incidents Open: title, impact, state, message, component_ids, started_at. Notifies like the dashboard.
PATCH /api/v1/status-pages/{pageSlug}/incidents/{incidentId} Update title, impact, state, component_ids; a message also posts a timeline update.
DELETE /api/v1/status-pages/{pageSlug}/incidents/{incidentId} Delete
GET /api/v1/status-pages/{pageSlug}/incidents/{incidentId}/updates Timeline, oldest first
POST /api/v1/status-pages/{pageSlug}/incidents/{incidentId}/updates Post a timeline update (message)

Scheduled maintenances

GET /api/v1/status-pages/{pageSlug}/maintenances?state=scheduled List
POST /api/v1/status-pages/{pageSlug}/maintenances Create: title, description, starts_at, ends_at, state, component_ids
PATCH /api/v1/status-pages/{pageSlug}/maintenances/{maintenanceId} Update any subset
DELETE /api/v1/status-pages/{pageSlug}/maintenances/{maintenanceId} Delete

Subscribers

GET /api/v1/status-pages/{pageSlug}/subscribers?confirmed=true List, optionally by confirmation
POST /api/v1/status-pages/{pageSlug}/subscribers Add: email, component_ids, confirmed (see below)
PATCH /api/v1/status-pages/{pageSlug}/subscribers/{subscriberId} Change component_ids (empty = all components)
DELETE /api/v1/status-pages/{pageSlug}/subscribers/{subscriberId} Remove

Webhooks

GET /api/v1/status-pages/{pageSlug}/webhooks List (secrets are never returned)
POST /api/v1/status-pages/{pageSlug}/webhooks Create: url, enabled, status_component_id, secret (optional)
PATCH /api/v1/status-pages/{pageSlug}/webhooks/{webhookId} Update; send secret to rotate it
DELETE /api/v1/status-pages/{pageSlug}/webhooks/{webhookId} Delete

Statuspage imports

POST /api/v1/status-pages/{pageSlug}/imports Start an Atlassian Statuspage import (202). Body: source=api with api_key + page_id, or source=public with url; include_subscribers, subscribers_consent.
GET /api/v1/status-pages/{pageSlug}/imports List imports for the page
GET /api/v1/status-pages/{pageSlug}/imports/{importId} Progress: state (queued, running, completed, stopped, failed), stage, counts, message

A subscriber added over the API is unconfirmed and receives the same confirmation email as the public subscribe form; they get incident emails only after clicking it. This needs a public page (otherwise 422 page_not_public).

If you already hold consent (for example, migrating an existing list), send "confirmed": true with a token that has the subscribers:confirm scope. No email is sent. Without that scope the request is rejected with 403 insufficient_scope.

Importing from Atlassian Statuspage

Owners can also start an import from Settings → Import from Statuspage. Components are imported flat (a group’s name is kept in each component’s description) with their current status, plus incidents with every update and original timestamps, and scheduled maintenance. Imported history notifies no one.

  • API key + page id reads everything through the Statuspage Manage API, and is the only way to bring subscribers. The key is passed encrypted to the import job and discarded afterwards; it is never stored.
  • A public page URL (https) reads /api/v2/summary.json, incidents.json and scheduled-maintenances.json: components, the most recent incidents and maintenance. No key needed.
  • Imported subscribers are unconfirmed and get a confirmation email, unless subscribers_consent is true (needs the subscribers:confirm scope via the API, or the owner’s explicit confirmation in Settings).
  • Re-running is safe: rows are matched by their Statuspage id and updated, not duplicated. When a plan limit is hit the import stops with state stopped and a message; upgrade and run it again to continue.

Webhook secrets

Secrets are write-only. Send your own (16+ characters) or omit it on create and Beacon generates one, returned once as a top-level "secret" field in the 201 response. Rotate it with PATCH; it is never shown again.

{
  "data": { "id": 7, "url": "https://hooks.example.com/beacon", "enabled": true, "status_component_id": null, … },
  "secret": "q3V…32 chars"
}