diff --git a/apps/web/src/views/docs.ejs b/apps/web/src/views/docs.ejs index 334887f..598c05d 100644 --- a/apps/web/src/views/docs.ejs +++ b/apps/web/src/views/docs.ejs @@ -53,13 +53,11 @@
Overview Authentication - Reliability & noise Account Monitors Notifications - Webhook payload Status Pages Incidents @@ -71,6 +69,10 @@ Logical $consider Examples + + + Reliability & noise + Webhook payload @@ -95,26 +97,6 @@ -PingQL doesn't immediately fire on a single failed check. A few knobs let you tune how reactive vs. how stable the alerting is. These are concepts you'll see referenced throughout the API reference below.
- -If a check fails and max_retries is greater than zero, the runner waits retry_interval_s seconds and retries up to that many times before recording a DOWN result. A successful retry posts a single UP ping with meta.retries noting how many attempts it took. This kills almost all flapping caused by transient TCP resets, brief 5xx blips, or network jitter.
Every check is recorded, but the important flag on a ping is only set when the monitor's state changes (UP↔DOWN) for that region. Notifications fire on important beats only — never on every routine check. State is tracked independently per region: if us-west goes DOWN, only a subsequent us-west UP clears it. eu-central being healthy will not silence a us-west outage.
For long outages, set resend_interval to re-fire the notification every Nth consecutive DOWN beat. With resend_interval: 10, a still-broken monitor produces an extra alert every 10 down checks. 0 (the default) means: alert once on the transition, then stay quiet until recovery.
For HTTPS monitors PingQL extracts the TLS leaf certificate's days-until-expiry on every check. When that drops at or below cert_alert_days for the first time, a separate cert notification fires (one per region). The flag clears when the cert is renewed, so each renewal cycle gets exactly one alert. Set cert_alert_days: 0 to disable.
If you don't supply a query, the monitor is considered up only on a 2xx response. Redirects (3xx), client errors (4xx) and server errors (5xx) all count as DOWN. Use the QL if you want different behaviour.
Webhook channels POST a JSON body to the configured URL on every event. The HTTP method is POST, the request times out after 5 seconds, and PingQL does not retry — the next important beat is the retry. Failures are logged but never block ingest.
| Header | Description |
|---|---|
| content-type | application/json |
| user-agent | PingQL-Notifier/1 |
| x-pingql-signature | Hex-encoded HMAC-SHA256 of the raw request body, keyed by config.secret. Only present when a secret is configured. Verify it server-side to confirm the request came from PingQL. |
| custom | Any headers from config.headers are forwarded as-is. |
Every payload has the same envelope:
-{
- "channel": { "id": "<uuid>", "name": "On-call webhook" },
- "event": { "kind": "down" | "up" | "cert" | "test", ... }
-}
- down — fired on the first DOWN important beat for a region, and again every resend_intervalth consecutive down if configured.
{
- "kind": "down",
- "monitor": {
- "id": "abc123def456",
- "name": "My API",
- "url": "https://api.example.com/health",
- "region": "us-west" // always present — runners default to "default" if REGION env var is unset
- },
- "ping": {
- "status_code": 503,
- "latency_ms": 412,
- "error": null,
- "checked_at": "2026-04-08T14:23:00.000Z"
- }
-}up — fired on recovery, only when that same region transitions back from DOWN. Same shape as down.
cert — fired once per renewal cycle when the TLS leaf cert drops at or below cert_alert_days for a region.
{
- "kind": "cert",
- "monitor": { "id": "…", "name": "…", "url": "…", "region": "us-west" },
- "days": 9 // days until certificate expires
-}test — synthetic event from POST /notifications/channels/:id/test. The monitor object is a placeholder.
{
- "kind": "test",
- "monitor": { "id": "test", "name": "Test event", "url": "https://example.com", "region": "" }
-}import { createHmac, timingSafeEqual } from "crypto"; - -function verify(rawBody, headerSig, secret) { - const expected = createHmac("sha256", secret).update(rawBody).digest("hex"); - return timingSafeEqual(Buffer.from(expected), Buffer.from(headerSig)); -}-
Always verify against the raw request body before parsing JSON.
-PingQL doesn't immediately fire on a single failed check. A few knobs let you tune how reactive vs. how stable the alerting is.
+ +If a check fails and max_retries is greater than zero, the runner waits retry_interval_s seconds and retries up to that many times before recording a DOWN result. A successful retry posts a single UP ping with meta.retries noting how many attempts it took. This kills almost all flapping caused by transient TCP resets, brief 5xx blips, or network jitter.
Every check is recorded, but the important flag on a ping is only set when the monitor's state changes (UP↔DOWN) for that region. Notifications fire on important beats only — never on every routine check. State is tracked independently per region: if us-west goes DOWN, only a subsequent us-west UP clears it. eu-central being healthy will not silence a us-west outage.
For long outages, set resend_interval to re-fire the notification every Nth consecutive DOWN beat. With resend_interval: 10, a still-broken monitor produces an extra alert every 10 down checks. 0 (the default) means: alert once on the transition, then stay quiet until recovery.
For HTTPS monitors PingQL extracts the TLS leaf certificate's days-until-expiry on every check. When that drops at or below cert_alert_days for the first time, a separate cert notification fires (one per region). The flag clears when the cert is renewed, so each renewal cycle gets exactly one alert. Set cert_alert_days: 0 to disable.
If you don't supply a query, the monitor is considered up only on a 2xx response. Redirects (3xx), client errors (4xx) and server errors (5xx) all count as DOWN. Use the QL if you want different behaviour.
Webhook channels POST a JSON body to the configured URL on every event. The HTTP method is POST, the request times out after 5 seconds, and PingQL does not retry — the next important beat is the retry. Failures are logged but never block ingest.
| Header | Description |
|---|---|
| content-type | application/json |
| user-agent | PingQL-Notifier/1 |
| x-pingql-signature | Hex-encoded HMAC-SHA256 of the raw request body, keyed by config.secret. Only present when a secret is configured. Verify it server-side to confirm the request came from PingQL. |
| custom | Any headers from config.headers are forwarded as-is. |
Every payload has the same envelope:
+{
+ "channel": { "id": "<uuid>", "name": "On-call webhook" },
+ "event": { "kind": "down" | "up" | "cert" | "test", ... }
+}
+ down — fired on the first DOWN important beat for a region, and again every resend_intervalth consecutive down if configured.
{
+ "kind": "down",
+ "monitor": {
+ "id": "abc123def456",
+ "name": "My API",
+ "url": "https://api.example.com/health",
+ "region": "us-west" // always present — runners default to "default" if REGION env var is unset
+ },
+ "ping": {
+ "status_code": 503,
+ "latency_ms": 412,
+ "error": null,
+ "checked_at": "2026-04-08T14:23:00.000Z"
+ }
+}up — fired on recovery, only when that same region transitions back from DOWN. Same shape as down.
cert — fired once per renewal cycle when the TLS leaf cert drops at or below cert_alert_days for a region.
{
+ "kind": "cert",
+ "monitor": { "id": "…", "name": "…", "url": "…", "region": "us-west" },
+ "days": 9 // days until certificate expires
+}test — synthetic event from POST /notifications/channels/:id/test. The monitor object is a placeholder.
{
+ "kind": "test",
+ "monitor": { "id": "test", "name": "Test event", "url": "https://example.com", "region": "" }
+}import { createHmac, timingSafeEqual } from "crypto"; + +function verify(rawBody, headerSig, secret) { + const expected = createHmac("sha256", secret).update(rawBody).digest("hex"); + return timingSafeEqual(Buffer.from(expected), Buffer.from(headerSig)); +}+
Always verify against the raw request body before parsing JSON.
+