Two surfaces: the authenticated /api/v1/monitorsREST API for managing monitors, and the unauthenticated ping & badge endpoints your jobs hit by UUID or slug. New to PingWatch? Start with the quickstart.
Base URL & authentication
The base URL is https://pingwatch.dev. The /api/v1 management routes require a Bearer token (pw_live_…) created in Settings → API keys. A missing, placeholder, invalid, or revoked key returns 401. Create / update / delete also require a key with the write scope; read-only keys get 403.
Header
Authorization:Bearerpw_live_a1b2c3d4e5f6...
Monitors
A monitor is one heartbeat expectation. Full CRUD lives under /api/v1/monitors (GET, POST, GET /:id, PATCH /:id, DELETE /:id).
POST/api/v1/monitorsBearertier monitor cap
Create a monitor. Returns the full monitor object in status 'new'.
Request body
name
string·REQUIRED
Human-readable label for the monitor. Max 100 characters.
schedule
string·REQUIRED
Expected interval between heartbeats. A number plus a unit: s, m, h, or d.
"30s""5m""1h""24h"
gracePeriodSeconds
integer·OPTIONAL
Slack allowed past the interval before the monitor is considered late. 60–86400 seconds.
default·300
slug
string·OPTIONAL
Optional custom ping slug (lowercase letters, numbers, single dashes; 2–64 chars). Globally unique. Send null or "" to leave unset.
Responses
201Created
Monitor created. The body is the full monitor object, starting in status "new" with no pings yet.
400Bad Request
Validation failed — missing/oversized name, unparseable schedule, grace period out of range, or an invalid slug.
error.codeName is required (max 100 chars)Invalid schedule. Use format like 5m, 1h, 24hGrace period must be between 60 and 86400 secondsslug must be lowercase letters, numbers, and single dashes …
401Unauthorized
Missing, placeholder, invalid, or revoked API key.
403Forbidden
Read-only key (no write scope), or your tier's monitor limit has been reached.
error.codeThis API key is read-only …Monitor limit reached (N). Upgrade your plan for more.
409Conflict
The requested slug is already in use by another monitor.
error.codeSlug "…" is already in use by another monitor.
Request
POST /api/v1/monitors
curl-XPOST"https://pingwatch.dev/api/v1/monitors"\-H"Authorization: Bearer <PINGWATCH_API_KEY>"\-H"Content-Type: application/json"\-d{"name":"Nightly DB backup","schedule":"24h","gracePeriodSeconds":600}'
Response201Created
application/json
{
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"userId": "8RXc1Pm9-2b3c-4d5e-6f70-8192a3b4c5d6",
"name": "Nightly DB backup",
"slug": null,
"schedule": "24h",
"scheduleType": "interval",
"gracePeriodSeconds": 600,
"status": "new",
"lastPingAt": null,
"lastPingType": null,
"nextExpectedAt": null,
"alertSentAt": null,
"consecutiveMisses": 0,
"isPaused": false,
"createdAt": "2026-05-29T17:55:00.000Z",
"updatedAt": "2026-05-29T17:55:00.000Z"
}
GET/api/v1/monitorsBearerread
List every monitor owned by the key's user, oldest first.
Responses
200OK
Body is { monitors: [...] } — every monitor owned by the key's user, oldest first.
These are the URLs your job actually calls. No auth — the monitor's UUID (or slug) is the secret. Each accepts GET or POST; a POSTbody is captured with the event, subject to your tier's body cap. The HTTP response is always the plain text OK (200) or Not found (404); the monitor state is updated asynchronously after the response is returned.
GET/api/ping/{id}Bearerunauthenticated
Record a SUCCESS beat: monitor → healthy, stale timer reset, consecutive misses cleared, and a recovery alert fired if it had been down or late.
Path parameters
id
string·REQUIRED
The monitor's UUID or its custom slug. Anything matching the UUID shape resolves by id; otherwise it resolves by slug.
Responses
200OK
Beat accepted. The response body is the literal text OK; the monitor is updated asynchronously. A paused monitor still returns 200 but records the ping without changing state or alerting.
404Not Found
No monitor matched the id or slug. Body is the literal text Not found.
Record a START: stamps the run-start so a later success can be timed (start → success duration). Does not reset the stale timer on its own.
Path parameters
id
string·REQUIRED
The monitor's UUID or its custom slug. Anything matching the UUID shape resolves by id; otherwise it resolves by slug.
Responses
200OK
Beat accepted. The response body is the literal text OK; the monitor is updated asynchronously. A paused monitor still returns 200 but records the ping without changing state or alerting.
404Not Found
No monitor matched the id or slug. Body is the literal text Not found.
Record a FAIL: monitor → down immediately and an alert fires (deduplicated — one per outage). Use this when the job itself errored.
Path parameters
id
string·REQUIRED
The monitor's UUID or its custom slug. Anything matching the UUID shape resolves by id; otherwise it resolves by slug.
Responses
200OK
Beat accepted. The response body is the literal text OK; the monitor is updated asynchronously. A paused monitor still returns 200 but records the ping without changing state or alerting.
404Not Found
No monitor matched the id or slug. Body is the literal text Not found.
A live SVG badge for any monitor, by UUID or slug. No auth. Embed it in a README, wiki, or status page. The badge shows the monitor name and its current state; a paused monitor reads paused, and an unknown id renders a not found badge with a 404 status.
GET/api/badge/{id}Bearerunauthenticated
Render the monitor's status as an SVG (image/svg+xml). Cached 30s for a real monitor, 60s for a miss.
Path parameters
id
string·REQUIRED
The monitor's UUID or its custom slug. Anything matching the UUID shape resolves by id; otherwise it resolves by slug.
Responses
200OK
An SVG badge labelled with the monitor name and its state (healthy / new / late / down / paused). Content-Type: image/svg+xml.
404Not Found
No monitor matched. Still returns an SVG — a grey "not found" badge — with a 404 status.
The /api/v1 routes return JSON with an error string. The ping and badge routes are plain-text / SVG instead (they aren't meant to be parsed by a client).
Status
Meaning
200
Beat accepted, or monitor read/updated
400
Invalid body, missing/oversized name, bad schedule, grace out of range, or invalid slug
401
Missing, placeholder, invalid, or revoked API key (v1 routes)
403
Read-only key (no write scope), or tier monitor limit reached
404
Monitor not found (v1 by owned id; ping/badge by id or slug)
409
Slug already in use by another monitor
Tier limits
Tier
Max monitors
History
Body capture
Alert channels
Free
5
7 days
none
email
Starter
20
30 days
10 KB
email · slack · webhook
Pro
100
90 days
100 KB
+ pagerduty
Business
500
365 days
512 KB
+ discord
tip Custom slugs are available on every tier. See live numbers and upgrade on the pricing page.