# Vendor Status Page Monitor - Incident Alerts (`lowlanddata/status-page-monitor`) Actor

Watch the status pages of the services you depend on and get told when one declares an incident. One feed for every vendor, read from the Statuspage and Instatus documents they publish themselves.

- **URL**: https://apify.com/lowlanddata/status-page-monitor.md
- **Developed by:** [Lowland Data](https://apify.com/lowlanddata) (community)
- **Categories:** Automation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $18.50 / 1,000 per alert delivereds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Vendor Status Page Monitor - Incident Alerts

Watches the status pages of the services you depend on - GitHub, Cloudflare, OpenAI, AWS, your payment provider - and tells you when one of them declares an incident. One feed for every vendor, so the next time something breaks you can answer the first question quickly: **is it us, or is it them?**

**Live health record:** [lowlanddata.com/status/status-page-monitor](https://lowlanddata.com/status/status-page-monitor/) - 30-day success rate and daily canary results, failures included. Full input/output reference: [tool page](https://lowlanddata.com/tools/status-page-monitor/).

It reads the machine-readable summary that status pages publish for exactly this purpose - the same document their own dashboards run on. Most vendor pages are hosted on Atlassian Statuspage or Instatus, and both are read directly. No API key, no scraping, no account with a monitoring service.

### Quick start (30 seconds, no keys needed)

1. Hit **Start** with the prefilled pages. You get one row per page - GitHub, Cloudflare, OpenAI - plus a row for every incident open right now.
2. Replace the list with your own vendors. A hostname (`status.example.com`) or a full URL both work.
3. Add a schedule (every 5-15 minutes is sensible) and set `alertsOnly: true`. From then on the runs are silent until a vendor posts something new.

### Who uses this

- **On-call engineers** get a Slack message when a dependency declares an incident, instead of finding out from a customer.
- **Support teams** watch the vendors behind their product, so the first ticket about checkout gets answered with "our payment provider has an open incident" rather than a shrug.
- **SRE and platform teams** feed `impact` and `affectedComponents` into an incident channel, and use the page-summary rows for an internal dashboard.
- **Anyone running an AI product** watches model providers, where a `monitoring` status on inference explains a bad afternoon better than any log.
- **Agencies** keep one profile per client stack.

### What you get

Two kinds of row. An **incident** row for anything open:

```json
{
  "statusPage": "https://www.cloudflarestatus.com",
  "vendor": "Cloudflare",
  "platform": "statuspage",
  "indicator": "minor",
  "isIncident": true,
  "incidentId": "9g65dxfbcjln",
  "title": "Incorrect geo location for some Cloudflare WARP users",
  "incidentStatus": "identified",
  "impact": "minor",
  "startedAt": "2026-08-27T18:46:19.000Z",
  "updatedAt": "2026-09-01T08:29:56.000Z",
  "affectedComponents": ["WARP"],
  "latestUpdate": "We are continuing to work on a fix for this issue.",
  "url": "https://www.cloudflarestatus.com/incidents/9g65dxfbcjln",
  "isNewOrChanged": true,
  "checkedAt": "2026-09-08T21:12:00.000Z"
}
```

And a **page summary** row for each vendor, healthy or not - the one that makes a dashboard:

```json
{
  "statusPage": "https://www.githubstatus.com",
  "vendor": "GitHub",
  "indicator": "none",
  "isIncident": false,
  "statusDescription": "All Systems Operational",
  "openIncidents": 0,
  "componentsDown": [],
  "componentCount": 12,
  "pageUpdatedAt": "2026-09-08T17:54:17.149Z"
}
```

A vendor whose page cannot be read does not sink the run. The failure is recorded, every other vendor still reports, and the run says so:

```text
WARN  status.customvendor.com failed: No status API found - tried /api/v2/summary.json, /summary.json
INFO  [Status message]: 4 status pages read, 3 open incidents (1 new or changed since the last run).
```

#### Reading the fields

| Field            | What it tells you                                                                                        |
| ---------------- | -------------------------------------------------------------------------------------------------------- |
| `indicator`      | The page's own verdict: `none`, `minor`, `major`, `critical`, `maintenance`. Filter a dashboard on this. |
| `incidentStatus` | Where the vendor is in the lifecycle: `investigating` -> `identified` -> `monitoring` -> `resolved`.     |
| `impact`         | How bad the vendor says it is. `major` and `critical` are the ones worth waking someone for.             |
| `componentsDown` | Which named parts are not operational, with the state - often more precise than the headline indicator.  |
| `isNewOrChanged` | True when this row differs from the previous run: a new incident, or an existing one the vendor updated. |

### How change detection works

Every monitor on this store is vague about this, so here it is in full:

- **Where the memory lives.** A named key-value store on *your* account (`stateStoreName`). It holds one fingerprint per incident - its status plus the vendor's own last-update timestamp - and one per page. There is no server on my side holding your vendor list.
- **What counts as a change.** A new incident, an incident the vendor updated (a new post, or a move from `investigating` to `identified`), or a page whose overall indicator shifted. An unchanged incident stays quiet, however long it runs.
- **`alertsOnly: false`** (the default) returns the full picture every run: a row per page plus every open incident. Good for a dashboard refresh.
- **`alertsOnly: true`** returns only new or changed incidents. A quiet run finishes empty, and the status line still tells the truth: `12 status pages read, 2 open incidents (0 new or changed since the last run)`.
- **Resolution.** An incident being resolved is itself a change, so with `includeResolved: true` you get the all-clear as a row.
- **Starting over.** `resetState: true` forgets the fingerprints, and everything currently open alerts again.

### What watching 12 vendors costs

Pay per outcome, so quiet minutes are nearly free.

| Event              | Price                                | When it is charged                                       |
| ------------------ | ------------------------------------ | -------------------------------------------------------- |
| **Incident alert** | $0.0199 (from $0.0185 on paid plans) | An incident row - something a vendor has declared        |
| **Page checked**   | $0.00199                             | A page-summary row in a full audit (`alertsOnly: false`) |
| **Actor start**    | $0.005                               | Per run, whatever it finds                               |

Live prices are always the ones on this page's Pricing tab. A worked example: 12 vendors, checked every 15 minutes with `alertsOnly: true`. A quiet run costs the actor start alone - about $14 a month for 2,880 checks - and you pay about 2 cents only when a vendor actually declares something. Drop to hourly and the same watch costs about $3.60 a month. New Apify accounts come with free monthly platform credits.

### Input reference

| Field                         | Type     | Default                | What it does                                                      |
| ----------------------------- | -------- | ---------------------- | ----------------------------------------------------------------- |
| `statusPages`                 | string\[] | three sample vendors   | Status page URLs or hostnames                                     |
| `alertsOnly`                  | boolean  | `false`                | Report only new or changed incidents - the setting for a schedule |
| `includeScheduledMaintenance` | boolean  | `false`                | Include announced maintenance windows                             |
| `includeResolved`             | boolean  | `false`                | Include incidents the vendor has already closed                   |
| `concurrency`                 | integer  | `6`                    | Pages read in parallel                                            |
| `resetState`                  | boolean  | `false`                | Forget the fingerprints and alert on everything open              |
| `stateStoreName`              | string   | `status-monitor-state` | Which named store holds this monitor's memory                     |
| `maxItems`                    | integer  | `500`                  | Stop after this many rows                                         |

The list is also accepted under `pages`, `vendors`, `urls` or `services`, and a single comma-separated string works as well as a list - so an AI agent's first guess at the input tends to run.

### Scheduling and API use

```bash
curl -X POST "https://api.apify.com/v2/acts/lowlanddata~status-page-monitor/runs?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"statusPages":["https://www.githubstatus.com","https://status.openai.com"],"alertsOnly":true}'
```

Pull only what a vendor has declared:

```bash
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?format=json&filter=isIncident"
```

In n8n or Make: Schedule -> this actor with `alertsOnly: true` -> Slack. A quiet run returns zero items, so the message fires only when there is something to say.

### Use it with AI agents (MCP)

Every tool here doubles as an MCP endpoint: [status-page-monitor/api/mcp](https://apify.com/lowlanddata/status-page-monitor/api/mcp). A prompt worth keeping around when something breaks:

```text
Check the status pages of GitHub, Cloudflare, OpenAI and Stripe and tell me
whether any of them has an open incident right now.
```

### Which pages can it read

- **Atlassian Statuspage** - the majority of vendor status pages, including GitHub, Cloudflare, OpenAI, DigitalOcean, Reddit, Twilio and Atlassian's own.
- **Instatus** - the other common host, read at its own summary endpoint.
- **Custom-built status pages** have no standard machine-readable document, so they cannot be read. The run reports the vendor as failed rather than pretending it is healthy - a monitor that invents an "all clear" is worse than no monitor. If a vendor you need is missing, [tell me](mailto:contact@lowlanddata.com) and I will look at whether it publishes anything readable.
- Some vendors redirect an old status hostname to a new one; redirects are followed.

### Is this legal, and what about personal data

Yes. These endpoints exist to be polled - they are what the vendor's own status widgets and third-party dashboards read, and a check is one request per page. Nothing is authenticated to.

Incident updates are written by the vendor's on-call staff, and the raw document carries author names, addresses and social handles alongside the text. **Those are never read.** The parser takes the update body, the status, the timestamps and the affected component names; a test in the build feeds it an incident stuffed with fake author details and fails if any of it reaches the output. So the rows are safe to store, forward into a ticket system and keep.

### FAQ

**Is this an uptime monitor?** No, and the difference matters. This reports what a vendor *admits* on its own page. It will not notice an outage the vendor has not posted yet - but when they do post, you get it in seconds, with their own wording and component list.

**How often should I run it?** Every 5-15 minutes for vendors you would page someone about; hourly for the rest. Quiet runs charge only the actor start.

**Why is one of my vendors always failing?** Their status page is probably custom-built with no machine-readable feed. See the coverage list above.

**Do I get an alert when it is fixed?** Set `includeResolved: true` and the resolution arrives as a change, so the all-clear reaches the same channel.

**Will a week-long incident alert me every run?** No. It alerts when it appears and again each time the vendor posts an update or changes its status.

### More tools from Lowland Data

Same house rules everywhere: clean schemas, public sources, no personal data in the output.

| Tool                                                                                   | What it does                                                  |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| [SSL & Domain Expiry Monitor](https://apify.com/lowlanddata/ssl-domain-monitor)        | Certificate and domain-registration countdowns for your hosts |
| [Dependency Release Monitor](https://apify.com/lowlanddata/dependency-release-monitor) | New npm, PyPI and GitHub releases, with breaking-change flags |
| [US Federal Grants Monitor](https://apify.com/lowlanddata/grants-gov-monitor)          | New federal funding opportunities matching your profile       |

Full catalogue: [lowlanddata.com/catalogue](https://lowlanddata.com/catalogue/).

### Support

A vendor page that will not read, or one you need supported? Open an issue on the **Issues** tab with the run ID, or write to <contact@lowlanddata.com>. Reports get read the same day.

# Actor input Schema

## `statusPages` (type: `array`):

One per line: https://www.githubstatus.com, status.openai.com. Statuspage and Instatus pages are read directly. Also accepted under pages, vendors or urls. Leave empty to use the sample list.

## `alertsOnly` (type: `boolean`):

Scheduled monitors want silence when nothing is happening. Off returns the full picture: one row per page plus every open incident.

## `includeScheduledMaintenance` (type: `boolean`):

Announced maintenance windows are planned work, not outages. Off by default.

## `includeResolved` (type: `boolean`):

Adds incidents the vendor has already closed, as the page still lists them.

## `concurrency` (type: `integer`):

Higher finishes a long vendor list sooner.

## `resetState` (type: `boolean`):

Forget what was already reported, so every open incident alerts again.

## `stateStoreName` (type: `string`):

Named key-value store holding the last reported state per incident.

## `maxItems` (type: `integer`):

Stop after this many rows.

## `proxyConfiguration` (type: `object`):

Status APIs are public; the default datacenter proxy is plenty.

## Actor input object example

```json
{
  "statusPages": [
    "https://www.githubstatus.com",
    "https://www.cloudflarestatus.com",
    "https://status.openai.com"
  ],
  "alertsOnly": false,
  "includeScheduledMaintenance": false,
  "includeResolved": false,
  "concurrency": 6,
  "resetState": false,
  "stateStoreName": "status-monitor-state",
  "maxItems": 500,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `incidents` (type: `string`):

One row per open incident, plus one row per page carrying its overall indicator and which components are down.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "statusPages": [
        "https://www.githubstatus.com",
        "https://www.cloudflarestatus.com",
        "https://status.openai.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lowlanddata/status-page-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "statusPages": [
        "https://www.githubstatus.com",
        "https://www.cloudflarestatus.com",
        "https://status.openai.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lowlanddata/status-page-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "statusPages": [
    "https://www.githubstatus.com",
    "https://www.cloudflarestatus.com",
    "https://status.openai.com"
  ]
}' |
apify call lowlanddata/status-page-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lowlanddata/status-page-monitor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/KeQ4yN3ndAgbLpe7s/builds/2Bn8cB69hClnO4aCD/openapi.json
