# Monitors

## Types

| Type | Checks | Personal accounts |
| --- | --- | --- |
| `http` | Status, text, JSON field and latency of one request | GET or HEAD only |
| `certificate` | TLS certificate trust, hostname and days to expiry | Yes |
| `heartbeat` | `start` and `success`/`failure` events sent by your own job | Yes |
| `api` | An `e2e` test making requests with `fetch`; no browser | Yes, within your plan's script limits |
| `browser` | An `e2e` test driving Chromium, with screenshots and traces | Yes, within your plan's script limits |

Choose the simplest type that catches the failure you care about: `http` for a page or endpoint, `certificate` for expiry, `heartbeat` for a cron job or backup, `api` for a check that needs several requests, `browser` for a user journey. Pick two to five journeys whose failure you would act on rather than turning a whole test suite into monitors.

`waitcher monitor init --type TYPE --file example.json` writes a complete paused example of a type.

**Certificate.** Checks the leaf certificate of a public HTTPS host on port 443. `settings.certificateMinDays` is 1 to 90 (default 14). Expired or below the threshold is a failure; DNS, connection or chain problems are an error.

**Heartbeat.** Waitcher never starts your job; the job reports in. After a deploy, issue the job its own credential and send events from it:

```sh
waitcher heartbeat credential --id MONITOR_ID --expected-revision N --output ./private/heartbeat.json
waitcher heartbeat event --token-file ./private/heartbeat.json --run-id "$RUN_ID" --event start
waitcher heartbeat event --token-file ./private/heartbeat.json --run-id "$RUN_ID" --event success
```

Use a fresh UUID per job run and the same UUID for its completion. Event timestamps must be within five minutes of the server clock. A missing start or completion becomes a missed result. Pausing or editing the monitor resets its timing.

## Personal-account limits

Every account starts on the free **starter** plan. **Pro** is the paid plan ([Plan and billing](account.md#plan-and-billing)). Every account can try Pro free for 14 days. The administrator can move an account to **pilot** (the Pro limits, unpaid) for design partners; ask with the owner ID from `waitcher auth status`.

| Limit | Starter | Pro | Pilot |
| --- | --- | --- | --- |
| Monitors | 5 | 25 | 25 |
| HTTP, certificate and heartbeat interval | At least 30 minutes | At least 5 minutes | At least 5 minutes |
| Script monitors (`api`, `browser`) | 1 | 5 | 5 |
| Script interval | At least 2 hours | At least 30 minutes | At least 30 minutes |
| Script runs per UTC day | 12 | 240 | 240 |

The other limits are the same on every plan:

| Limit | Value |
| --- | --- |
| Monitors in one project | All the plan allows |
| Timeout | At most 15 seconds for HTTP and certificate checks; 3 to 60 seconds for API and browser checks |
| Manual runs | One per account per 10 minutes, and not within 30 minutes of that monitor's last run |
| Targets | Public HTTPS on port 443; private and reserved addresses are refused |
| HTTP requests | GET or HEAD, no custom headers or body |

**Script monitors.** A script monitor over the plan's count is refused with `QUOTA_EXCEEDED`, and a shorter interval with `VALIDATION_ERROR`. Daily runs count scheduled and manual runs together; runs that never started do not count. Over the daily cap, a manual run is refused with `DAILY_SCRIPT_BUDGET` and a scheduled run is recorded as missed without a request. Hosted scripts of all accounts share the runner's day, and free accounts together get at most half of it; past that a run is refused with `RUNNER_DAILY_BUDGET` the same way. On the starter plan the 2 hour interval and 12 runs a day leave room for manual runs.

`waitcher system capabilities` shows the monitor types and limits that apply to your account right now. A local pass never means the hosted check is allowed.

## One monitor without waitcher.json

For a single check outside a repository, write one JSON definition and apply it directly:

```sh
waitcher monitor init --type http --file home.json --target https://example.com/
waitcher monitor validate --file home.json         # offline
waitcher monitor apply --file home.json --dry-run  # server checks, saves nothing
waitcher monitor apply --file home.json
waitcher monitor resume --id MONITOR_ID
```

The file is a complete definition, not a patch. Edits need `--id ID --expected-revision N` (from `monitor get`). `monitor pause`, `monitor resume`, `monitor export --id ID --file PATH` and `monitor delete --id ID --yes` (removes history too) manage it. Monitors deployed from `waitcher.json` cannot be edited this way.
