Reference
HTTP API
Four endpoints. They exist so an integration can discover your monitors and ping one by name, which is the one thing a ping URL alone cannot do.
You probably do not need this. If you just want a workflow to report that it ran, use the monitor's ping URL: it is a plain GET, it needs no authentication, and it is documented on the monitor's own page. The API is for tools that have to list your monitors before they can offer you one to choose.
Authentication
Every endpoint below takes an account API key as a bearer token. Create one under API keys in the dashboard. The key is shown once, at creation; only a hash is stored, so a lost key is replaced rather than recovered.
curl -fsS https://silentfailapp.com/api/v1/me \ -H "Authorization: Bearer sf_your_key_here"
A missing, malformed, unknown or revoked key all answer 401 with the same message. Keys do not expire; they end when you revoke them.
Responses
Every response is JSON with an ok boolean. Failures carry a human-readable error string and nothing else. Nothing is cacheable.
{ "ok": false, "error": "unknown monitor" }A monitor id that belongs to somebody else answers 404, not 403, so the API never confirms that an id it will not serve you exists.
Endpoints
GET /api/v1/me
The account behind the key: address, timezone, plan, and how many monitors exist versus how many are being watched. Reads nothing about pings, so it is safe to call as a connection test — testing a connection can never mark a monitor alive.
{
"ok": true,
"email": "you@example.com",
"timezone": "America/Port_of_Spain",
"plan": { "id": "solo", "name": "Solo", "monitorLimit": "25" },
"monitors": { "total": 7, "watched": 7 }
}GET /api/v1/monitors
Every monitor on the account, oldest first. Pass ?search= to filter by name, case-insensitively, on a substring.
The order is by creation and deliberately not by name or status, so an option does not move in a dropdown because a monitor went down while somebody was reading it.
{
"ok": true,
"monitors": [
{
"id": "clx8f2k1a0001",
"name": "Nightly invoice sync",
"status": "up",
"watching": true,
"schedule": {
"kind": "daily",
"intervalMin": null,
"dailyHour": 9,
"dailyMinute": 0,
"description": "Daily by 09:00"
},
"gracePeriodMin": 120,
"lastPingAt": "2026-09-05T09:02:11.402Z",
"nextPingDueAt": "2026-09-06T13:00:00.000Z",
"downAfterAt": "2026-09-06T15:00:00.000Z",
"pingUrl": "https://silentfailapp.com/api/ping/9_aR_n9KNdbZq9W3A9pBjw",
"createdAt": "2026-08-14T18:22:03.118Z"
}
]
}Two fields are worth reading carefully. status is evaluated at the moment you ask rather than read from a column the background checker updates, so a monitor that went overdue forty seconds ago already says down here. watching is false for a monitor switched off by a plan change: it still accepts pings and still appears in this list, but nothing is evaluating it and it will never alert.
GET /api/v1/monitors/{id}
One monitor, in the same shape as a list entry, under a monitor key. A read and only a read.
POST /api/v1/monitors/{id}/ping
Records a ping, exactly as a request to that monitor's ping URL would. It resets the clock, and if it closes an outage you were emailed about, it sends the all-clear and reports recovered: true.
curl -fsS -X POST https://silentfailapp.com/api/v1/monitors/clx8f2k1a0001/ping \ -H "Authorization: Bearer sf_your_key_here"
{
"ok": true,
"receivedAt": "2026-09-05T09:02:11.402Z",
"recovered": false,
"monitor": { "...": "as above, after the ping" }
}POST only. The public ping URL accepts GET, POST and HEAD because it has to fit whatever your automation tool makes easy; a program holding an API key has a choice, so this one asks for the right method.
Pinging a monitor whose watching is false still answers 200 and still records the ping. Your workflow has done nothing wrong, and a billing state on our side must not make it start failing.
Rate limits and versioning
There is no published rate limit. Be reasonable; if that stops being enough, a limit will appear here before it appears in your logs.
The /api/v1 prefix is a promise that the shapes above will not change underneath you. New fields may be added, so parse leniently and ignore what you do not recognise.