Your clients' SSL, domain, uptime and keyword checks belong in a version-controlled file — not clicked into a dashboard one form at a time. Commit monitors.json, and StatusKit reconciles your live fleet to match it from CI, in one idempotent call.
monitors.json is the source of truth for the fleetEvery StatusKit account ships with a full REST API — the console is just one view of it. So your whole monitoring fleet can live in a repo: define each check in a file, commit it, and apply it from CI. Here is the entire fleet for a client, version-controlled and diffable:
# monitors.json — your whole fleet, version-controlled
{
"prune": true,
"monitors": [
{ "kind": "ssl", "target": "acme.com", "name": "Acme — SSL cert" },
{ "kind": "domain", "target": "acme.com", "name": "Acme — domain expiry" },
{ "kind": "http", "target": "https://acme.com", "name": "Acme — homepage", "public": true },
{ "kind": "keyword", "target": "https://acme.com|Cart", "name": "Acme — checkout alive" }
]
}
Identity is (kind, target) — the thing being watched — so you can rename a monitor freely and keep its uptime history. This is the difference between "we have a dashboard" and monitoring as code: a versioned, reviewable source of truth.
Write each SSL, domain, HTTP or keyword check into monitors.json in your repo.
Open a pull request. Your teammate reviews the monitoring change like any other diff.
On merge, CI POSTs the file to /api/monitors/sync. Live monitors now match the file.
The sync endpoint is idempotent: re-running an unchanged file writes nothing, editing a line updates that one monitor, and deleting a line removes it when you opt into prune:true. Here is a complete GitHub Action — copy it verbatim, only the secret is yours:
# .github/workflows/statuskit.yml
name: StatusKit sync
on:
push: { branches: [main], paths: [monitors.json] }
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Reconcile monitors
env: { STATUSKIT_KEY: ${{ secrets.STATUSKIT_KEY }} }
run: |
curl -sf -X POST "https://statuskit.app/api/monitors/sync" \
-H "Authorization: Bearer $STATUSKIT_KEY" \
-H "Content-Type: application/json" \
--data @monitors.json
Not on GitHub? It's a single authenticated HTTP call, so it runs the same from GitLab CI, CircleCI, a Makefile, or your laptop. Full details in the API reference.
If you run monitoring for dozens of clients, click-ops is where mistakes hide. Monitoring as code gives you one reviewable file per client, flat pricing with no per-seat tax, and a branded public status page for each — all driven from the same repo your team already works in. Start free with the SSL & domain checker, then put the fleet in version control.
Monitoring as code means your uptime, SSL, domain and keyword checks live in a version-controlled file in your repo — not clicked into a dashboard by hand. The file is the source of truth; a single idempotent API call reconciles your live monitors to match it. You get review, history, rollback and CI enforcement for monitoring, exactly like you already have for infrastructure.
A dashboard is click-ops: someone logs in, fills a form per monitor, and the current state lives only in that vendor's UI. There's no diff, no review, no audit trail, and configuration drifts as people leave. StatusKit gives you the dashboard too — but the same fleet is drivable from a monitors.json you commit, so a pull request becomes a reviewed, revertable monitoring change.
Yes. Keep a monitors.json in your repo and add a GitHub Action that POSTs it to /api/monitors/sync on every push. Merging a PR that edits the file updates your live monitors; reverting the PR reverts them. StatusKit ships a copy-pasteable starter workflow — see the API docs.
Any CI, and no CI at all. The sync endpoint is a single authenticated HTTP call — curl --data @monitors.json. It runs the same from GitHub Actions, GitLab CI, CircleCI, a Makefile, or your laptop. The only requirement is an api_key in the environment.
SSL certificate expiry, domain registration expiry, HTTP uptime, and keyword presence (is a specific word still on the page). Each check runs on a schedule from the edge and alerts you by email or webhook the moment it changes — and each can be published to a branded public status page.
Yes — it's idempotent. Re-running an unchanged file reports everything as unchanged and writes nothing. Every item is validated before anything is written, and the whole reconcile applies as one transaction, so a bad line fails the batch instead of leaving you half-configured. Deletion only happens when you opt in with prune:true; otherwise drift is reported, never destroyed.
Grab an API key from the console, drop a monitors.json in your repo, and wire the Action above. Your clients' monitoring becomes diffable, reviewable, and enforced on every push.