---
title: WatchFor REST API reference
description: The WatchFor REST API — monitors, alert rules, incidents, maintenance windows, status pages and reports over JSON, plus the MCP server, A2A and SDKs.
canonical: https://watchfor.io/docs/api
---

# WatchFor REST API reference

The WatchFor REST API — monitors, alert rules, incidents, maintenance windows, status pages and reports over JSON, plus the MCP server, A2A and SDKs.

[![ora agent-readiness score](https://ora.ai/api/badge/watchfor.io)](https://ora.ai/scan/watchfor.io)
  [![is-agentic agent-readiness score](/api/badge/is-agentic)](https://is-agentic.com/scan/watchfor.io)
  [![WebMCP audit score](/api/badge/webmcp)](https://webmcp.ora.ai/watchfor.io)

WatchFor is modern uptime & infrastructure monitoring, for humans and AI
agents. Everything you can do in the dashboard is also available
programmatically: a REST API, an [MCP server](/docs/api/mcp) for AI
agents, an [A2A agent](/docs/api/a2a) for agent-to-agent delegation, and
official SDKs with a CLI. All of them run on the same API, the same
credentials and the same per-plan limits.

The REST API is a predictable JSON API over HTTPS: Bearer API keys (or
OAuth 2.1 tokens), stable versioning in the path, cursor pagination,
idempotent writes and one error envelope.

```
https://watchfor.io/api/v1
```

## Your first three calls

### Create an API key

In the dashboard go to **Settings → API keys** and create a key (owners
and admins only). Choose `read` for integrations that only read data, or
`read + write` for automation that creates or changes things. The full
`wf_live_…` value is shown once. See [Authentication](/docs/api/authentication).

### Verify the key

```bash
curl https://watchfor.io/api/v1/me \
  -H "Authorization: Bearer wf_live_YOUR_KEY"
```

```json
{
  "object": "api_key_identity",
  "organization": { "id": "6f0a…", "name": "Acme Cloud", "slug": "acme-cloud" },
  "scope": "read"
}
```

### Get the state of everything

```bash
curl https://watchfor.io/api/v1/summary \
  -H "Authorization: Bearer wf_live_YOUR_KEY"
```

`GET /v1/summary` returns monitor status counts, a health score, active
incident counts and open maintenance windows in one call — see
[Organization summary](/docs/api/summary). Before creating monitors or
alert rules, read the [monitor type catalog](/docs/api/monitor-types)
(`GET /v1/meta/monitor-types`, no key needed) for the exact `type`,
`config` and `metric` values.

> **Try it without a key**
>
> The read-only [sandbox](/docs/api/sandbox) at
> `https://watchfor.io/api/v1/sandbox` serves sample data in the exact
> production shapes — no account, no key.

## Conventions

- **Versioning** — the version lives in the path (`/api/v1`). Within `v1`,
  responses may gain new fields but never lose or repurpose existing ones.
  Breaking changes ship as a new version. See
  [Operations & reliability](/docs/api/operations).
- **Authentication** — `Authorization: Bearer wf_live_…` (API key) or an
  OAuth 2.1 access token; the `Bearer` scheme is case-insensitive and any
  other scheme is `401`. Keys carry a `read` or `write` scope; mutating
  endpoints require `write`.
- **Timestamps** — ISO 8601 in UTC everywhere (`2026-08-24T10:00:00.000Z`).
- **Objects** — every resource carries an `object` field (`monitor`,
  `incident`, `alert_rule`, …); lists are wrapped in
  `{ "object": "list", "data": [...], "has_more": true|false }`.
- **Pagination** — cursor-based: pass the previous page's `next_cursor`
  as `?cursor=`. `limit` is 1–100 (default 50); any other value is `400`,
  and so is a `sort` parameter — every list has one fixed order. Cursors
  are opaque positions: the page after a cursor is stable even if the item
  it pointed at has been deleted; a malformed cursor returns
  `400 invalid_request`.
- **Deletes** — return `200` with
  `{ "object": "deleted", "id": "…", "deleted": true }`.
- **Errors** — always `{ "error": { "code", "message" } }` with a stable
  machine-readable code (`413 payload_too_large` for oversize bodies);
  see [Errors & rate limits](/docs/api/errors).
- **Retries** — POST endpoints accept an `Idempotency-Key` header;
  action endpoints (pause, acknowledge, …) are idempotent by design.
- **CORS** — enabled for every origin, so browser-side and edge callers
  work without a proxy.
- **Secrets** — credential-bearing config values (passwords, tokens,
  request bodies, sensitive headers) are returned as `"[redacted]"`.

## OpenAPI specification

The machine-readable contract is an OpenAPI 3.1 document, public (no key
needed) and served from one source at three conventional locations:

- [`/openapi.json`](https://watchfor.io/openapi.json)
- [`/.well-known/openapi.json`](https://watchfor.io/.well-known/openapi.json)
- [`/api/v1/openapi.json`](https://watchfor.io/api/v1/openapi.json)

Every operation has a stable `operationId`, and every authenticated one
an `x-required-scope`, so generated clients and AI-agent tool converters
get typed, scoped functions. An [RFC 9727 API catalog](https://watchfor.io/.well-known/api-catalog)
at `/.well-known/api-catalog` points at the spec, the docs and the agent
endpoints.

## Resources

| Page | Endpoints |
| --- | --- |
| [Monitors](/docs/api/monitors) | list, create, get, update, delete, pause, resume, reset, bulk pause/resume/delete; page integrity baseline get/accept (deploy hook); browser check runs, script versions, test runs and variables |
| [Checks, uptime & run now](/docs/api/checks-uptime) | uptime & response-time stats, raw check history (with failure filter), one check in full detail (redacted), on-demand check |
| [Live diagnostics](/docs/api/diagnostics) | 24 ad-hoc checks run from the probe fleet on demand — DNS, propagation, TLS, HTTP, ping, ports, blacklists, email policy — plus the one-call `diagnose-target` bundle |
| [Alert rules](/docs/api/alert-rules) | list, create, get, update/enable/disable, delete — catalog-validated |
| [Monitor types](/docs/api/monitor-types) | per-type target format, alert metrics, config fields, default rules (`GET /meta/monitor-types`) |
| [Locations](/docs/api/locations) | list probe locations |
| [Incidents](/docs/api/incidents) | list (filters + cursor), get, acknowledge, resolve, mark as maintenance, statistics (MTTR/MTBF) |
| [Organization summary](/docs/api/summary) | one-call health snapshot |
| [Prometheus metrics](/docs/api/prometheus) | monitor status, uptime, response times, expiry, heartbeats and hosts in Prometheus format, plus a Grafana dashboard (Pro plan and above) |
| [Reports](/docs/api/reports) | period-over-period org report; weekly/monthly report-email schedules |
| [Notification channels](/docs/api/notification-channels) | list, get (secrets masked) |
| [Hosts](/docs/api/hosts) | list, get, metrics (servers running watchfor-agent) |
| [Maintenance windows](/docs/api/maintenance-windows) | list, create, get, update, delete |
| [Contacts & groups](/docs/api/contacts) | contacts and contact groups: list, create, get, update, delete |
| [Status pages](/docs/api/status-pages) | pages: list, create, get, update, delete; announcements: list, create, get, update, delete |
| [Notifications](/docs/api/notifications) | alerting delivery history — every notification attempt per channel |
| [Activity log](/docs/api/activity) | organization audit trail with search and filters |
| [Plan, limits & on-call](/docs/api/plan) | current plan, limits and usage; who is on call |
| [Identity, spec & batch](/docs/api/meta) | `GET /me`, `GET /organizations` (the organizations a credential can act on), the OpenAPI document, `POST /batch` (up to 20 operations per request) |

> **Info**
>
> Heartbeat check-ins don't need an API key — each heartbeat monitor has
> its own unique ping URL. See
> [heartbeat monitoring](/docs/monitors/heartbeat).

## SDKs & CLI

Official clients — zero runtime dependencies, resource-for-resource
mirrors of the REST API, each shipping a `watchfor` CLI:

**TypeScript**

```bash
npm install watchfor
```

```ts

const wf = new WatchFor({ apiKey: process.env.WATCHFOR_API_KEY! });
const summary = await wf.summary();
const firing = await wf.incidents.list({ status: "firing" });
const monitor = await wf.monitors.create(
  { name: "My site", type: "http", target: "https://example.com",
    interval: 300, locations: ["<location-id>"] },
  "create-my-site", // optional Idempotency-Key for safe retries
);
```

Typed from the OpenAPI spec; `WatchForError` carries `status`, `code` and
`retryAfterSeconds`. Package:
[npmjs.com/package/watchfor](https://www.npmjs.com/package/watchfor).

**Python**

```bash
pip install watchfor
```

```python
from watchfor import WatchFor

wf = WatchFor(api_key="wf_live_...")
print(wf.summary())
for inc in wf.incidents.list(status="firing")["data"]:
    print(inc["message"], inc["severity"])
```

Namespaces: `wf.monitors`, `wf.alert_rules`, `wf.incidents`,
`wf.maintenance_windows`, `wf.contacts`, `wf.contact_groups`; errors raise
`WatchForError` with `.status`, `.code`, `.message`. Package:
[pypi.org/project/watchfor](https://pypi.org/project/watchfor/).

**Ruby**

```bash
gem install watchfor
```

```ruby
require "watchfor"

wf = Watchfor::Client.new(api_key: "wf_live_...")
pp wf.summary
wf.incidents.list(status: "firing")["data"].each { |i| puts i["message"] }
```

Same namespaces as Python; errors raise `Watchfor::Error`. Package:
[rubygems.org/gems/watchfor](https://rubygems.org/gems/watchfor).

The CLI works the same in all three:

```bash
npx watchfor summary                 # or: watchfor summary (pip / gem)
watchfor incidents --status firing
watchfor monitors example.com
watchfor checks <monitor-id> --failed
watchfor report --period 30d
```

### Organizations in the SDKs

An API key always acts on its own organization. An
[OAuth access token](/docs/api/authentication#how-oauth-maps-to-your-data)
reaches every organization its user belongs to, and all three SDKs take the
organization to act on as a client option, sent as the
`X-WatchFor-Organization` header:

| | List organizations | Client option | Switch organization | CLI |
| --- | --- | --- | --- | --- |
| TypeScript | `wf.organizations.list()` | `new WatchFor({ apiKey, organization })` | `wf.withOrganization(id)` | `watchfor organizations`; `--organization <id>` or `WATCHFOR_ORGANIZATION` |
| Python | `wf.organizations.list()` | `WatchFor(api_key=..., organization=...)` | `wf.with_organization(id)` | same |
| Ruby | `wf.organizations.list` | `Watchfor::Client.new(api_key:, organization:)` | `wf.with_organization(id)` | same |

The list ([`GET /v1/organizations`](/docs/api/meta#list-organizations))
gives the ids to pass, with `is_default` and `is_current` flags. Switching
returns a new client with the same token. `wf.me()` (CLI: `watchfor me`)
shows which organization a client acts on. With an API key
leave the option unset — any id other than the key's own organization is
`403`.

## For AI agents

The same API is exposed through protocols built for AI agents, and every
discovery surface answers without a key:

| Surface | Where |
| --- | --- |
| [MCP server](/docs/api/mcp) (59 tools, resources, prompts) | `https://watchfor.io/api/mcp` — manifest at [`/.well-known/mcp.json`](https://watchfor.io/.well-known/mcp.json), server card at [`/.well-known/mcp/server-card.json`](https://watchfor.io/.well-known/mcp/server-card.json) |
| [Documentation MCP server](/docs/api/mcp#documentation-mcp-server) (3 read-only tools) | `https://watchfor.io/api/docs-mcp` |
| [A2A agent](/docs/api/a2a) (18 skills) | `https://watchfor.io/api/a2a` — Agent Card at [`/.well-known/agent-card.json`](https://watchfor.io/.well-known/agent-card.json) |
| [Live diagnostics](/docs/api/diagnostics) (24 checks, MCP + A2A + REST) | `POST https://watchfor.io/api/v1/diagnostics/{slug}` — catalog and budget at `GET /v1/diagnostics` |
| Agent quickstart | [`/agents.md`](https://watchfor.io/agents.md) |
| Site overview for LLMs | [`/llms.txt`](https://watchfor.io/llms.txt) |
| Agent skills (SKILL.md) | [`/.well-known/agent-skills/index.json`](https://watchfor.io/.well-known/agent-skills/index.json) — also in the [agent-toolkit repo](https://github.com/watchfor-io/agent-toolkit) |
| OAuth 2.1 discovery | [`/.well-known/oauth-authorization-server`](https://watchfor.io/.well-known/oauth-authorization-server) |
| Machine-readable pricing | [`/pricing.md`](https://watchfor.io/pricing.md) |

Agents that want to act on an account can authenticate with a key or
complete the [OAuth 2.1 flow](/docs/api/authentication#oauth-21) with no
human-issued key at all.

## Reports

The full organization report (uptime, incidents, MTTR/MTBF, response
time, per-monitor rows, type-aware sections and insights, always compared
with the previous period) is `GET /v1/reports`, and the weekly/monthly
report-email cadences are managed with `GET /v1/reports/schedules` and
`PATCH /v1/reports/schedules/{frequency}`. Full reference:
[Reports](/docs/api/reports).

---

Canonical page: https://watchfor.io/docs/api · All docs: https://watchfor.io/docs · Site guide: https://watchfor.io/llms.txt
