watchfor (Python)
Official Python SDK + CLI for WatchFor — uptime & infrastructure monitoring (monitors, alert rules, incidents, maintenance windows) over the REST API. Zero dependencies (standard library only).
There is also a TypeScript SDK, an MCP server and an A2A agent for AI agents.
Install
pip install watchfor
Quick start
from watchfor import WatchFor
wf = WatchFor(api_key="wf_live_...") # create keys in Settings → API keys
# One-call org snapshot
print(wf.summary())
# List monitors
for m in wf.monitors.list()["data"]:
print(m["name"], m["status"])
# Create a monitor (idempotency key optional, for safe retries)
mon = wf.monitors.create(
{
"name": "example.com",
"type": "http",
"target": "https://example.com",
"interval": 300,
"locations": ["<location-id>"], # from wf.locations()
},
idempotency_key="create-example-1",
)
# Diagnose: firing incidents right now
for inc in wf.incidents.list(status="firing")["data"]:
print(inc["message"], inc["severity"])
# False positive? Keep the resolved incident on record but drop it from
# uptime, SLA, reports and the status page (include() undoes it)
wf.incidents.exclude(19351, reason="Probe-side DNS hiccup")
# Irreversible: wipe a monitor's checks and incidents; uptime restarts "since reset"
wf.monitors.reset(mon["id"])
# Page integrity: after a deploy, accept what the newest check saw as the new baseline
wf.monitors.accept_baseline(integrity_monitor_id)
# Browser checks: try a Playwright script once (nothing saved), then read the result
run = wf.playwright.test_run(script=script, target="https://shop.example.com")
wf.playwright.get_test_run(run["id"]) # status: queued | running | done | error
wf.variables.put("LOGIN_PASSWORD", value=password, secret=True)
# The same org secrets in HTTP/API/MCP checks: {{NAME}} in auth, a header or the body
wf.variables.put("API_TOKEN", value=token, secret=True)
wf.monitors.update(api_monitor_id, {"config": {"requestHeaders": [
{"key": "Authorization", "value": "Bearer {{API_TOKEN}}"}]}})
# Older checks: pass next_cursor back as cursor (keep the same hours/success)
page = wf.monitors.checks(mon["id"], hours=24, limit=100)
if page["next_cursor"]:
wf.monitors.checks(mon["id"], hours=24, limit=100, cursor=page["next_cursor"])
# Delete a contact group that alert rules still use (409 without force)
wf.contact_groups.delete("<group-id>", force=True)
Live diagnostics
Run any of 22 checks from WatchFor's probe fleet against any public target, monitored or not — this measures right now, rather than reading what WatchFor recorded:
# What can I run, and how much budget is left?
catalog = wf.diagnostics.list()
# One check, optionally from a location you choose (plan-gated)
dns = wf.diagnostics.run(
"dns-lookup", "example.com", options={"recordType": "A", "resolver": "8.8.8.8"}
)
# A closed port / NXDOMAIN / failed handshake does NOT raise:
if not dns["success"]:
print("finding:", dns["error"])
print("runs left this hour:", dns["remaining"])
# The whole picture in one call: DNS + propagation + TLS + HTTP + ping
# from up to 3 regions, aggregated into one verdict
report = wf.diagnostics.diagnose_target("example.com")
print(report["verdict"]["status"], report["verdict"]["summary"])
Runs need a write key (a probe sends real traffic from WatchFor's IPs)
and spend the same per-plan hourly allowance as the dashboard Toolbox.
Details: https://watchfor.io/docs/api/diagnostics
Resource namespaces: wf.monitors, wf.alert_rules, wf.incidents,
wf.hosts, wf.status_pages, wf.on_call, wf.notification_channels, wf.maintenance_windows, wf.contacts, wf.contact_groups,
wf.diagnostics. Top-level:
wf.summary(), wf.plan(), wf.me(), wf.locations(), wf.monitor_types(),
wf.incident_stats(period=...), wf.notifications(...), wf.activity(...).
Errors raise WatchForError with .status, .code and .message.
Prometheus metrics (Pro plan and above)
text = wf.metrics(tag="production") # Prometheus text format
Usually you point Prometheus at https://watchfor.io/api/v1/metrics directly; this is for scripts and one-off checks. See https://watchfor.io/docs/api/prometheus.
CLI
export WATCHFOR_API_KEY=wf_live_...
watchfor summary
watchfor monitors
watchfor incidents --status firing
watchfor checks <monitor_id> [--cursor <next_cursor>]
watchfor report --period 30d
Auth & scopes
Keys carry a scope: read (all GET endpoints) or write (read plus
create/update/delete). See
authentication. The API is also
reachable via OAuth 2.1 for MCP clients.
Reference
- OpenAPI spec: https://watchfor.io/openapi.json
- Guides: https://watchfor.io/docs/api
MIT License.
Releasing
./publish.sh # build, check, confirm, upload
./publish.sh --build # build and check only
Debian and Ubuntu mark the system Python "externally managed" (PEP 668), so
pip install build twine is refused and python3 -m build reports No module
named build. The script keeps its own .venv-publish instead of touching the
system Python. Credentials are read from ~/.pypirc as usual.
Metadata
Release files for watchfor 0.12.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| watchfor-0.12.1.tar.gz | 14.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| watchfor-0.12.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.0 kB
Release files / watchfor-0.12.1.tar.gz
| Download URL | watchfor-0.12.1.tar.gz |
|---|---|
| Size | 14.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9694e976faf331db1265286365a68790ff0562cbddb21a20db5ddb8c635174c7
|
|
BLAKE2b-256 checksum How to use checksums |
5476a07597cb18d10f7a575fdd9aacbba45b4b9347cba41986cbeb15359fbb61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / watchfor-0.12.1-py3-none-any.whl
| Download URL | watchfor-0.12.1-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d9dff3cd44ab62079eb4329f943fedac634c0edee6ea3788dd10b5b2b9b77f05
|
|
BLAKE2b-256 checksum How to use checksums |
6985f21968b449458a8628a421819cc82d265fbabb7ba32d42d60d24118d1940
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|