Everything you need to create uptime & SSL monitors, read their check history and incidents, verify domains, and schedule maintenance windows. New to WatchTower? Start with the quickstart.
Base URL & authentication
The base URL is https://watchtower.works and every route lives under /api/v1. Requests carry a Bearer token (wt_…) created in Settings → API keys. A missing, placeholder, invalid, or revoked key returns 401.
Monitors
A monitor is a recurring check against one URL. Full CRUD lives under /api/v1/monitors (GET, POST, GET /{id}, PATCH /{id}, DELETE /{id}). GET /api/v1/monitors returns { monitors: [...] }for the key's user.
POST/api/v1/monitorsBearer60 creates/hr · key
Create a monitor. Runs a synchronous first check and returns the full monitor object, including regions and the initialCheck result.
Request body
name
string·REQUIRED
Human-readable label. Trimmed and truncated to 100 chars.
url
string·REQUIRED
Target endpoint. HTTP monitors may use http://; SSL monitors must be https://. Run through an SSRF guard.
Substring that must appear in the response body for the check to pass. null disables.
headersJson
string·OPTIONAL
JSON-encoded string of custom request headers sent on each probe. null disables.
intervalSeconds
integer·OPTIONAL
Seconds between checks. Floored to your tier's minimum interval; unverified domains are capped at 3600.
default·300
flipsignComponentId
string·OPTIONAL
UUID of a FlipSign component to flip when this monitor changes state. null/"" clears it.
Responses
201Created
Monitor created and active. Body is the full monitor object, including its computed regions, cronpilotScheduleId, and an initialCheck (the synchronous first probe result, or null if it couldn't run).
400Bad Request
Invalid JSON, missing name/url, an unsupported checkType, a non-UUID flipsignComponentId, or a URL the SSRF guard rejected.
error.codename is requiredurl is requiredcheckType must be 'http' or 'ssl'flipsignComponentId must be a UUID
401Unauthorized
Missing, placeholder, invalid, or revoked API key.
403Forbidden
REST API requires Pro/Business; SSL monitoring requires Pro+; monitor cap reached; interval below tier minimum; or an unverified-domain cap hit.
error.codeSSL certificate monitoring is a Pro feature.Monitor limit reached (…). Upgrade to add more.Unverified domains support at most 1 monitor.Unverified domains must check at most once per hour.
429Too Many Requests
More than 60 monitors created via the API in the last hour for this key. A Retry-After header is included.
Update a monitor. Only the fields you send are changed; url/interval changes are re-validated against the SSRF guard and unverified-domain caps. Mirrors the change onto the underlying schedule.
Path parameters
id
string·REQUIRED
Monitor UUID from the create response.
Request body
name
string·OPTIONAL
New label. Must be a non-empty string.
url
string·OPTIONAL
New target. Re-checked by the SSRF guard; SSL monitors can't be repointed to http://.
method
string·OPTIONAL
New HTTP verb.
expectedStatus
integer·OPTIONAL
New expected status code.
keywordMatch
string·OPTIONAL
New body keyword, or null to disable.
headersJson
string·OPTIONAL
New JSON header string, or null to disable.
intervalSeconds
integer·OPTIONAL
New cadence. Floored to your tier's minimum; revalidated against the unverified-domain interval cap.
isPaused
boolean·OPTIONAL
Pause or resume the monitor (and its underlying schedule).
flipsignComponentId
string·OPTIONAL
UUID of a FlipSign component, or null/"" to clear.
Responses
200OK
Updated monitor object. With an empty body (no recognised fields), the unchanged monitor is returned.
400Bad Request
A supplied field had the wrong type, or a new url failed the SSRF guard.
403Forbidden
API tier gate, interval below tier minimum, or an unverified-domain cap when the url/interval changes.
The time-series of probe results for a monitor — status code, latency, up/down, and any error. This is the rollup row written each round (multi-location detail is aggregated into it).
GET/api/v1/monitors/{id}/checksBearertier · Pro+
List recent check results for a monitor, newest first.
Path parameters
id
string·REQUIRED
Monitor UUID.
Query parameters
limit
integer·OPTIONAL
How many recent results to return, newest first. Clamped to 1–500.
Down-periods for a monitor. An incident opens when a monitor crosses into a failing state and resolves when it recovers; resolvedAt: null means it's still open.
Unverified domains are capped at one monitor and an hourly minimum interval. Verifying the apex lifts both caps for every subdomain. Register a domain, prove ownership via a .well-known file or a DNS TXT record, then call /verify. List your domains with GET /api/v1/domains ({ domains: [...] }).
POST/api/v1/domainsBearertier · Pro+
Register a domain. Returns a pending entry with a pathToken (.well-known file path) and a verificationToken (the file body / TXT value). Idempotent: re-posting an existing domain returns it with 200.
Request body
domain
string·REQUIRED
The domain to verify (e.g. example.com). A full URL is accepted and normalised to its lowercase hostname.
Responses
201Created
{ domain } — a new pending entry carrying pathToken and verificationToken. Satisfy either the .well-known file or the DNS TXT record, then call /verify.
200OK
{ domain } — the domain already exists for you; the existing entry (and its tokens/status) is returned. Idempotent re-post.
400Bad Request
Invalid JSON, missing domain, or a value that didn't parse to a hostname.
Re-check a pending domain. WatchTower probes both the .well-known file and the DNS TXT record; the first that matches flips the entry to verified.
Request body
domain
string·REQUIRED
The domain whose pending verification to re-check. Normalised to its hostname.
Responses
200OK
{ status: "verified", method, verified_at } when ownership is confirmed via .well-known or DNS TXT; otherwise { status: "pending", message, pathToken, verificationToken } so you can retry. An already-verified domain returns { status: "verified", verified_at }.
400Bad Request
Invalid JSON, missing domain, or an unparseable value.
A window suppresses incident creation — and therefore alerts — for the covered monitors during [startsAt, endsAt]. Omit monitorId for a global window. Manage them under /api/v1/maintenance-windows (GET → { windows: [...] }, POST, GET /{id}, DELETE /{id}).
POST/api/v1/maintenance-windowsBearertier · Pro+
Create a maintenance window. Scope it to one monitor with monitorId, or leave it out for a global window.
Request body
title
string·REQUIRED
Window label. Trimmed and truncated to 200 chars.
startsAt
string·REQUIRED
ISO 8601 timestamp (with Z or ±HH:MM offset) when suppression begins.
endsAt
string·REQUIRED
ISO 8601 timestamp when suppression ends. Must be strictly after startsAt.
description
string·OPTIONAL
Optional note, or null.
monitorId
string·OPTIONAL
UUID of one monitor to scope the window to. Omit or null for a global window covering every monitor you own. Must be a monitor you own.
Responses
201Created
The maintenance window object. Incidents (and alerts) are suppressed for the covered monitors during [startsAt, endsAt].
400Bad Request
Non-object body, missing title, missing/invalid ISO timestamps, or endsAt not after startsAt.
error.codetitle is requiredstartsAt and endsAt are required (ISO 8601)startsAt and endsAt must be valid ISO 8601 timestampsendsAt must be after startsAt
403Forbidden
REST API requires Pro/Business.
404Not Found
monitorId referred to a monitor you don't own.
error.codeMonitor not found
Request
POST /api/v1/maintenance-windows
curl-XPOST"https://watchtower.works/api/v1/maintenance-windows"\-H"Authorization: Bearer <WATCHTOWER_API_KEY>"\-H"Content-Type: application/json"\-d{"title":"Quarterly DB migration","startsAt":"2026-06-01T02:00:00.000Z","endsAt":"2026-06-01T04:00:00.000Z"}'
Response201Created
application/json
{
"id": "a0b1c2d3-5678-4ef0-b123-456789abcdef",
"userId": "8R2c1Pm9-…",
"monitorId": null,
"title": "Quarterly DB migration",
"description": "Read-only window during the migration.",
"startsAt": "2026-06-01T02:00:00.000Z",
"endsAt": "2026-06-01T04:00:00.000Z",
"createdAt": "2026-05-29T15:32:00.000Z"
}
Errors
Every error returns JSON with an error field. Unverified-domain rejections add a stable code (monitor_cap or interval_cap) so you can branch on them programmatically.
Status
Meaning
400
Invalid JSON, missing/typed-wrong field, bad checkType, or a URL the SSRF guard rejected
401
Missing, placeholder, invalid, or revoked API key
403
API tier gate (Free/Starter), SSL on a non-Pro plan, monitor cap, interval below tier minimum, or an unverified-domain cap
404
Monitor, domain, maintenance window, or referenced monitorId not found / not yours
429
More than 60 monitor creates/hour for this key (Retry-After included)
Tiers & limits
Tier
Monitors
Min interval
API
SSL
Multi-location
Free
10
5 min
—
—
—
Starter
50
1 min
—
—
—
Pro
Unlimited
1 min
✓
✓
iad1 + fra1
Business
Unlimited
1 min
✓
✓
iad1 + fra1
note Alert channels also scale by tier — email (Free), +Slack/webhook (Starter), +Discord/PagerDuty (Pro+). See the live numbers on the pricing page.