# Statuspage & Outage Monitor: Vendor Incident & SLA Monitor (`adastra-connect/vendor-status-incident-monitor`) Actor

Public statuspage outage monitor, SLA monitor and incident monitor for vendor incidents, maintenance and dated outage evidence.

- **URL**: https://apify.com/adastra-connect/vendor-status-incident-monitor.md
- **Developed by:** [Ad Astra Connect](https://apify.com/adastra-connect) (community)
- **Categories:** Developer tools, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 incidents

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Monitor vendor incidents and collect dated SLA evidence

Vendor Status Page & Incident Monitor normalizes public SaaS and cloud status pages into one incident dataset. Use this Statuspage and Instatus incident monitor for SRE alerts, MSP customer reporting, vendor risk reviews and dated evidence for SLA credit requests. Collect incidents, maintenance windows and degraded components without logging in or scraping status page HTML.

### Statuspage and Instatus incident monitoring

The Actor reads public JSON status feeds, checks robots.txt and combines recent incident history with current summary notices. The live-tested defaults are Cloudflare Status, OpenAI Status and Linear Status. A successful empty run can mean no matching incidents, an unchanged monitor, a spending limit or unavailable upstream pages. Check RUN_SUMMARY to distinguish them.

### What data can you get

Each dataset row represents one incident, maintenance notice or component degradation observation. Each row uses the `incident` billing event.

| Fields | Meaning |
| --- | --- |
| `id`, `incidentId` | Status host plus native incident ID, and the native ID separately |
| `vendorName`, `vendorHost`, `platform` | Published page name, canonical input hostname and API format |
| `pageOverallStatus` | `none`, `minor`, `major`, `critical`, `maintenance` or `unknown` |
| `title`, `status`, `impact`, `isActive` | Redacted title, normalized lifecycle, severity and active flag |
| `affectedComponents` | Published component names with personal data redaction |
| `createdAt`, `updatedAt`, `resolvedAt` | UTC timestamps; unavailable update or resolution times are null |
| `durationMinutes` | Minutes from creation to resolution, otherwise null |
| `updatesCount` | Number of published updates returned by the endpoint |
| `latestUpdateBody` | Optional redacted plain text excerpt, at most 1,000 characters |
| `shortlink`, `sourceUrl`, `attribution` | Official HTTPS source and vendor attribution |
| `firstSeenAt`, `changeType` | Monitor-only first observation and prioritized change category |

Component-only observations use `component-<nativeComponentId>` as `incidentId`. Their source is the page root, and their creation time uses the component change timestamp, falling back to its published creation timestamp. They are observations, not vendor-authored incident notices. The Actor does not infer recovery when a component disappears from a later summary.

### How to use the vendor status tracker

1. Open the Actor input and enter public status page root URLs or hostnames.
2. Choose the age window, impact and optional title/component keywords.
3. Set a small result limit and run. Empty API input `{}` uses the verified defaults.
4. Open the dataset or overview table. Export the rows as JSON or CSV.
5. Inspect RUN_SUMMARY for each vendor's availability, cache status, warnings and limits.

```json
{
  "statusPages": ["https://www.cloudflarestatus.com", "https://status.openai.com", "https://linearstatus.com"],
  "activeOnly": false,
  "minImpact": "all",
  "updatedWithinDays": 14,
  "includeUpdateText": false,
  "maxIncidentsPerPage": 15,
  "maxResults": 30,
  "monitorMode": false,
  "requestDelayMs": 750
}
```

### Incident output example

This shortened real observation illustrates the dataset shape. Source status changes over time.

```json
{
  "id": "www.cloudflarestatus.com:575028s1mgk1",
  "vendorName": "Cloudflare Status",
  "vendorHost": "www.cloudflarestatus.com",
  "platform": "statuspage",
  "pageOverallStatus": "major",
  "incidentId": "575028s1mgk1",
  "title": "DTW (Detroit) on 2026-10-26",
  "status": "scheduled",
  "impact": "maintenance",
  "isActive": true,
  "affectedComponents": ["Detroit, MI, United States - (DTW)"],
  "createdAt": "2026-10-25T13:40:40.000Z",
  "updatedAt": "2026-10-25T13:40:40.419Z",
  "resolvedAt": null,
  "durationMinutes": null,
  "updatesCount": 1,
  "shortlink": "https://www.cloudflarestatus.com/incidents/575028s1mgk1",
  "sourceUrl": "https://www.cloudflarestatus.com/incidents/575028s1mgk1",
  "attribution": "Cloudflare Status public status page"
}
```

| Vendor | Notice | Status | Impact |
| --- | --- | --- | --- |
| Cloudflare Status | DTW (Detroit) on 2026-10-26 | scheduled | maintenance |
| Cloudflare Status | Kampala, Uganda - (EBB) degradation | investigating | critical |

### Inputs and filters

| Input | Default | Behavior |
| --- | --- | --- |
| `statusPages` | Three verified defaults | 1 to 30 unique public HTTPS root URLs; required in the Store editor |
| `activeOnly` | false | Excludes resolved, postmortem and completed notices |
| `minImpact` | all | all, minor, major or critical; maintenance matches only all |
| `updatedWithinDays` | 30 | Age based on latest update or creation; zero disables age filtering within the recent window |
| `keywords` | empty | Case-insensitive OR matching of title and component names |
| `includeUpdateText` | false | Adds the latest redacted excerpt |
| `maxIncidentsPerPage` | 20 | 1 to 50 newest candidates per vendor, before filtering |
| `maxResults` | 100 | 1 to 1,000 rows, hard output cap |
| `monitorMode` | false | Emit baseline, then changed versions only |
| `monitorKey` | default | Independent persistent watch namespace |
| `requestDelayMs` | 750 | At least 250 milliseconds between requests to the same host |

The tiny Store prefill uses 14 days, 15 candidates per vendor and 30 results. Instatus summaries sometimes expose only the last update, so `updatesCount` is the returned count, not a guaranteed lifetime count. If creation is unavailable in a maintenance summary, its scheduled start is used as `createdAt`.

### Incremental runs / monitoring

Set `monitorMode: true` and reuse `monitorKey` across scheduled runs. The first run emits matching notices as `new_incident`. Later runs emit `resolved` when a notice enters a terminal state, `status_changed` for status or impact changes, or `update_added` for a changed latest timestamp. Only one category is emitted per notice per run, in that order of precedence. `firstSeenAt` persists for acknowledged versions.

State is kept in a named key-value store, separate from the default dataset. Filters isolate watches; changing filters or `monitorKey` creates a new baseline. Page lists and row caps do not reset state. A capped first run can leave more new rows for subsequent runs. Update text edits without a timestamp change are not detected.

Schedule one run at a time for a watch. Delivery reservations prevent a second charge for a previously claimed version. If a dataset write has an ambiguous failure, a reserved version can be skipped on retry. This favors duplicate-charge prevention and does not guarantee exactly-once delivery. A one-minute shared cache and error cooldown reduce repeated upstream traffic. Data can be up to one minute old. Purging local default storage clears the default dataset, not the named watch state.

### Pricing

Planned price: **$2.00 per 1,000 incidents**. One dataset row is one `incident` event, including maintenance, component observations and changed incident versions. Unchanged monitor checks emit no rows. The final price is shown on the Store page. The run also has an `apify-actor-start` event. Check the Store pricing for its current price. The Actor checks the remaining event allowance before dataset writes and stops gracefully when the spending limit is reached. This source package does not configure Store pricing.

### Scheduling and integrations

Use Apify schedules for regular checks and webhooks for run completion. Read datasets and RUN_SUMMARY with the Apify API. Connect results to Make, Zapier or n8n for alerts, vendor risk reports and evidence archives. AI agents can consume results through Apify MCP integrations. This Actor collects data; it does not send alerts or submit credit claims itself.

### Is it legal?

The Actor uses public official JSON endpoints, no login, no cookies and no proxies. It respects each target's robots.txt and refuses restricted endpoints. Text passes through personal data redaction; author objects, emails and phone fields are not copied into the schema. Automated redaction can suppress useful terms and cannot certify anonymity. Review evidence before sharing it. You are responsible for complying with vendor terms and your intended use.

This Actor and its output are not legal advice. A public incident is not proof that a specific contract, tenant or region qualifies for SLA credits. Contract terms and submission deadlines require independent review.

### Limitations

- This is a recent-window monitor, not a complete historical archive. Each vendor provides at most 50 retained candidates, including current maintenance and component observations. No historical pagination is performed.
- Age and keyword filters apply after the per-vendor candidate cap. Increase that cap if current maintenance or components crowd out older incidents.
- Duration runs from published creation to resolution. It is not measured downtime, monthly uptime or a contractual SLA calculation.
- Summary maintenance coverage varies. Completed maintenance absent from a summary is not fetched from separate maintenance history routes.
- `platform` describes the public response format. A vendor can serve Statuspage-compatible JSON through different hosting software.
- Instatus pages must expose the documented legacy summary route. Instatus history is disabled because the legacy history route has no verified public documentation; RUN_SUMMARY reports summary-only coverage. Authenticated management APIs and current v3-only routes are outside this Actor's scope.
- Robots restrictions, redirects, network failures, schema changes and rate limits can reduce coverage. Unsafe API redirects are refused. Only an absent robots.txt (404 or 410) means no published restriction.
- All unavailable targets produce a successful zero-row run with `upstream_unavailable` in RUN_SUMMARY. Invalid input and dataset or persistent watch storage errors fail the run.
- Collection stops within a 45-second budget and reserves time before a platform timeout. Inspect `time_limit` before assuming a scan was complete.

### FAQ

**Why did a status page with a working API produce no rows?** Its robots policy can disallow automated API access. Other causes include filters, a candidate cap, an unchanged watch or upstream failure. RUN_SUMMARY records the distinction.

**Does activeOnly exclude scheduled maintenance?** No. Scheduled, in-progress and verifying maintenance remain active until completed.

**Can I claim SLA credits automatically?** No. Use the dated observations as a starting point for review against your own agreement and service telemetry.

**Can I monitor arbitrary websites?** No. Inputs must be public HTTPS status page roots exposing supported JSON routes. Private addresses, credentials, nonstandard ports and arbitrary paths are rejected.

**What happens when my spending limit is reached?** Collection stops gracefully. Only delivered versions are acknowledged in monitor state, subject to the reservation limitation described above.

### Support

Use this Actor's Issues tab on Apify with the input, RUN_SUMMARY and a description of the expected result. Remove sensitive data first.

### Trademark disclaimer

Cloudflare, OpenAI, Linear, Atlassian, Statuspage, Instatus, Apify, Make, Zapier and n8n are trademarks of their respective owners. This Actor is not affiliated with, endorsed or sponsored by any of the named trademark owners.

# Actor input Schema

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

Public HTTPS root status page URLs or hostnames. Current robots restrictions are enforced. Up to 30 pages.

## `activeOnly` (type: `boolean`):

Exclude resolved, postmortem and completed notices.

## `minImpact` (type: `string`):

Minimum severity. Maintenance is included only with all.

## `updatedWithinDays` (type: `integer`):

Filter by latest update time, falling back to creation. Zero disables the age filter within the recent window.

## `keywords` (type: `array`):

Case-insensitive OR matching against incident titles and component names.

## `includeUpdateText` (type: `boolean`):

Include redacted plain text up to 1000 characters. Disabled by default.

## `maxIncidentsPerPage` (type: `integer`):

Newest candidate notices considered per vendor before filters, from a recent window of up to 50.

## `maxResults` (type: `integer`):

Hard dataset and billing row cap.

## `monitorMode` (type: `boolean`):

First run emits matching baseline. Later runs emit only changed status, impact or update timestamp.

## `monitorKey` (type: `string`):

Persistent watch namespace. Use a different key for an independent baseline.

## `requestDelayMs` (type: `integer`):

Minimum per-host delay in milliseconds. Robots crawl delays can increase it.

## Actor input object example

```json
{
  "statusPages": [
    "https://www.cloudflarestatus.com",
    "https://status.openai.com",
    "https://linearstatus.com"
  ],
  "activeOnly": false,
  "minImpact": "all",
  "updatedWithinDays": 14,
  "keywords": [],
  "includeUpdateText": false,
  "maxIncidentsPerPage": 15,
  "maxResults": 30,
  "monitorMode": false,
  "monitorKey": "default",
  "requestDelayMs": 750
}
```

# Actor output Schema

## `results` (type: `string`):

One normalized notice per row.

## `overview` (type: `string`):

Dataset table.

## `runSummary` (type: `string`):

Per-target outcomes, warnings, cache and stop reason.

# 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.cloudflarestatus.com",
        "https://status.openai.com",
        "https://linearstatus.com"
    ],
    "updatedWithinDays": 14,
    "maxIncidentsPerPage": 15,
    "maxResults": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("adastra-connect/vendor-status-incident-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.cloudflarestatus.com",
        "https://status.openai.com",
        "https://linearstatus.com",
    ],
    "updatedWithinDays": 14,
    "maxIncidentsPerPage": 15,
    "maxResults": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("adastra-connect/vendor-status-incident-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.cloudflarestatus.com",
    "https://status.openai.com",
    "https://linearstatus.com"
  ],
  "updatedWithinDays": 14,
  "maxIncidentsPerPage": 15,
  "maxResults": 30
}' |
apify call adastra-connect/vendor-status-incident-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,adastra-connect/vendor-status-incident-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/fJsjvdx0cCfnFKnDr/builds/T2mabmc04vBbYSyd6/openapi.json
