# Status page JSON API

Every Spectate status page serves its status as JSON in the Atlassian Statuspage v2 format. Tools that read Statuspage pages, such as status aggregators, chat bots and dashboards, can read a Spectate page without changes. The API is read-only, needs no token for public pages, and any website can call it.

## Endpoints

All endpoints are on the domain of the page: the default address `https://<slug>.spectate.page`, or the [custom domain](/status-pages/custom-domains).

| Endpoint | Returns |
|---|---|
| `GET /api/v2/summary.json` | The page, all components, unresolved incidents, maintenance in progress and upcoming, and the overall status. |
| `GET /api/v2/status.json` | The page and the overall status. |
| `GET /api/v2/components.json` | The page and all components. |
| `GET /api/v2/incidents.json` | The page and the 50 newest incidents. |
| `GET /api/v2/incidents/unresolved.json` | The page and the incidents that are not resolved. |
| `GET /api/v2/scheduled-maintenances.json` | The page and the 50 maintenances with the latest start. |
| `GET /api/v2/scheduled-maintenances/upcoming.json` | The page and the maintenances with the status `scheduled`. |
| `GET /api/v2/scheduled-maintenances/active.json` | The page and the maintenances with the status `in_progress`. |

The **Overview** tab of the status page in the dashboard shows the `summary.json` URL of the page.

## Example

```bash
curl https://acme.spectate.page/api/v2/status.json
```

```json
{
  "page": {
    "id": "9b2f6d1e-4c3a-4f7e-8a51-2d0c9e7b6a14",
    "name": "Acme Cloud",
    "url": "https://acme.spectate.page",
    "time_zone": "Etc/UTC",
    "updated_at": "2026-10-27T09:41:12Z"
  },
  "status": {
    "indicator": "major",
    "description": "Partial System Outage"
  }
}
```

`summary.json` returns `page`, `components`, `incidents`, `scheduled_maintenances` and `status`:

```json
{
  "page": { "id": "9b2f6d1e-...", "name": "Acme Cloud", "url": "https://acme.spectate.page", "time_zone": "Etc/UTC", "updated_at": "2026-10-27T09:41:12Z" },
  "components": [
    {
      "id": "5e0c2a77-...",
      "name": "Core services",
      "status": "partial_outage",
      "created_at": "2026-03-02T10:00:00Z",
      "updated_at": "2026-10-27T09:12:00Z",
      "position": 1,
      "description": null,
      "showcase": false,
      "start_date": null,
      "group_id": null,
      "page_id": "9b2f6d1e-...",
      "group": true,
      "only_show_if_degraded": false,
      "components": ["c41d8e02-..."]
    },
    {
      "id": "c41d8e02-...",
      "name": "API",
      "status": "partial_outage",
      "created_at": "2026-03-02T10:00:00Z",
      "updated_at": "2026-10-27T09:12:00Z",
      "position": 2,
      "description": "Public REST API",
      "showcase": true,
      "start_date": "2026-03-02",
      "group_id": "5e0c2a77-...",
      "page_id": "9b2f6d1e-...",
      "group": false,
      "only_show_if_degraded": false
    }
  ],
  "incidents": [
    {
      "id": "0f7a3b9c-...",
      "name": "Elevated API error rates",
      "status": "identified",
      "created_at": "2026-10-27T09:14:30Z",
      "updated_at": "2026-10-27T09:41:12Z",
      "monitoring_at": null,
      "resolved_at": null,
      "impact": "major",
      "shortlink": "https://acme.spectate.page/incidents/0f7a3b9c-...",
      "started_at": "2026-10-27T09:12:00Z",
      "page_id": "9b2f6d1e-...",
      "incident_updates": [
        {
          "id": "a83e5d10-...",
          "status": "identified",
          "body": "We found the cause and are applying a fix.",
          "incident_id": "0f7a3b9c-...",
          "created_at": "2026-10-27T09:41:12Z",
          "updated_at": "2026-10-27T09:41:12Z",
          "display_at": "2026-10-27T09:41:12Z"
        }
      ],
      "components": [{ "id": "c41d8e02-...", "name": "API", "status": "partial_outage" }]
    }
  ],
  "scheduled_maintenances": [],
  "status": { "indicator": "major", "description": "Partial System Outage" }
}
```

The example shortens IDs and the components of the incident. The API returns full UUIDs and full component objects.

## Fields

### Overall status

| Page headline | `indicator` | `description` |
|---|---|---|
| All components operational | `none` | All Systems Operational |
| Degraded performance | `minor` | Minor Service Outage |
| Partial outage | `major` | Partial System Outage |
| Full outage | `critical` | Major System Outage |
| Maintenance | `maintenance` | Service Under Maintenance |

### Components

A component's `status` is `operational`, `degraded_performance`, `partial_outage`, `major_outage` or `under_maintenance`. See [component statuses](/status-pages/components#component-statuses).

A group is a component with `group: true`. Its `components` field lists the IDs of its components. Each component in a group has the group's ID in `group_id`. The status of a group is the worst status of its components.

### Incidents

| Field | Values |
|---|---|
| `status` | `investigating`, `identified`, `monitoring` or `resolved` |
| `impact` | `none`, `minor` (degraded performance), `major` (partial outage) or `critical` (full outage). The worst current impact, or the worst impact it had once it is resolved. |
| `started_at` | The earliest of the first impact, the first update and the creation of the incident. |
| `monitoring_at`, `resolved_at` | The time of the first update with that status, or `null`. |
| `incident_updates` | The public updates. `created_at` and `display_at` are the **Happened at** time of the update. |
| `components` | Every component that the incident affected, also after it is resolved. |
| `shortlink` | The incident page on the status page. |

### Scheduled maintenances

Maintenances have the same fields as incidents, and also these:

| Field | Values |
|---|---|
| `status` | `scheduled`, `in_progress` or `completed` |
| `impact` | Always `maintenance`. |
| `scheduled_for` | The planned start. |
| `scheduled_until` | The planned end, or `null`. |
| `started_at` | When the maintenance went in progress, or `null`. |
| `incident_updates` | One update with the description of the maintenance, or empty without a description. |

## Private pages

A [private page](/status-pages/access) returns `404` without access. Add the access key of the page to the URL:

```bash
curl "https://acme.spectate.page/api/v2/summary.json?key=YOUR_ACCESS_KEY"
```

Responses of a private page have `Cache-Control: private, no-store`. Anyone with the key can read the page, so keep the key out of public code.

## Caching and errors

Spectate builds the data of a page at most once per 30 seconds. Public responses have `Cache-Control: public, max-age=30`. A change can take up to 30 seconds to show in the API.

| Status | Body | When |
|---|---|---|
| `200` | The resource | The page exists and you have access. |
| `404` | `{"error": "Not found"}` | The page or resource does not exist, the page is private without a valid key, or the path does not end in `.json`. |
| `503` | `{"error": "Unavailable"}` | Spectate cannot read the page right now. The response has `Retry-After: 30`. |

## CORS

Every response has `Access-Control-Allow-Origin: *`, so a script on any website can read the API. `OPTIONS` requests return `204` with `Access-Control-Allow-Methods: GET, OPTIONS`.

## Differences from Atlassian Statuspage

- `time_zone` is always `Etc/UTC`. All times are UTC, in the format `2026-10-27T09:41:12Z`.
- Spectate calculates group IDs from the page and the group name. If you rename a group, its ID changes.
- `showcase` is `true` for components and `false` for groups. `only_show_if_degraded` is always `false`. `start_date` is the date that the component was created.
- Incidents never have the status `postmortem`. Maintenances never have the status `verifying`.
- A maintenance has no separate updates. Its description is its only update.
- If you hide incidents or maintenance in **Settings → Display**, `incidents` or `scheduled_maintenances` is an empty list.
- The API is read-only. It has no endpoints for subscribers or for changes. To change a status page, use the [public API](/developers/api) of Spectate.

## Related

- [RSS and Atom feeds](/status-pages/introduction#feeds)
- [Status pages in the API reference](/api-reference/status-pages)
