← Docs

Management API

v1

A REST API for provisioning and managing monitors from scripts, CI, or a coding agent. Your jobs still only call the ping URL; this API is for setup and automation. There is an OpenAPI 3.1 spec at /openapi.json for generating clients or importing into an HTTP tool.

Overview

Base URL: https://illari.dev/api/v1. All requests and responses are JSON.

  • A single resource is returned as { "data": { … } }; a collection as { "data": [ … ] }. List endpoints that paginate add a sibling cursor field.
  • Timestamps are ISO 8601 in UTC (2026-08-31T07:00:00.000Z). IDs are UUIDs.
  • Send a JSON body with Content-Type: application/json. Unknown fields are ignored.

What you can do: list, create, retrieve, update (including pause and snooze), and delete monitors, and read a monitor's check-in history. Alert channels are not manageable through the API yet.

Authentication

Create a key under Settings → API keys. The key (illari_ followed by 32 hex characters) is shown once. Keys are account-scoped, full-access, and can be revoked at any time from the same screen.

Send it as a bearer token on every request. A request with no key, a malformed key, or a revoked key gets 401.

authenticated request
curl -fsS https://illari.dev/api/v1/monitors \
  -H "Authorization: Bearer illari_YOUR_KEY"

Errors

Every error response has the shape { "error": "message" } with a 4xx status. The message is a short human-readable string, safe to log.

example error (HTTP 400)
{ "error": "invalid cron expression" }
StatusMeaning
400A field failed validation: bad cron expression, unknown timezone, a number out of range, malformed JSON.
401Missing, malformed, or revoked API key. Response carries WWW-Authenticate: Bearer.
403The account is at its plan's monitor limit, or metricRules was sent on a Free account.
404No monitor with that id is visible to this key.

Pagination

Only GET /monitors/<id>/pings paginates. It uses a keyset cursor: pass ?limit= (1–200, default 50) and read nextBefore from the response. To get the next page, send that value back as ?before=. When nextBefore is null, you have reached the end.

second page
curl -fsS -G https://illari.dev/api/v1/monitors/<id>/pings \
  -H "Authorization: Bearer illari_YOUR_KEY" \
  --data-urlencode "limit=100" \
  --data-urlencode "before=2026-08-30T02:00:00.000Z"

Rate limits

The Management API has no published rate limit today. Keep it to a few requests per second and it will be fine. The ping endpoint (not part of this API) has its own flood guard of 60 requests per minute per monitor.

Endpoints

List monitors

GET /monitors

Every monitor on the account, newest first.

request
curl -fsS https://illari.dev/api/v1/monitors \
  -H "Authorization: Bearer illari_YOUR_KEY"
response — 200
{
  "data": [
    {
      "id": "b4dfaf3d-f934-4029-96b0-3a8ec7d73aff",
      "name": "nightly-etl",
      "cronExpression": "0 2 * * *",
      "timezone": "America/Chicago",
      "status": "up",
      "pingKey": "48c28871cf371128221df895ca3f9cfa",
      "nextExpectedAt": "2026-09-01T07:00:00.000Z",
      "createdAt": "2026-08-29T19:59:06.407Z"
    }
  ]
}

Create a monitor

POST /monitors

Creates a monitor and returns 201 with the full object, including the generated pingKey.

Body

FieldTypeNotes
namestringRequired. Non-empty.
commandstring | nullOptional. ≤ 500 chars. Free text, never executed.
cronExpressionstring | nullOptional. 5-field cron or a macro (@daily). Null for a grace-only monitor.
timezonestringOptional. IANA name. Default "UTC".
gracePeriodSecondsintegerOptional. 0–86400. Default 300.
maxRuntimeSecondsinteger | nullOptional. 1–604800. Hung-run detection. Null = off.
metricRulesMetricRule[]Optional. Pro only. See the model below.
request
curl -fsS -X POST https://illari.dev/api/v1/monitors \
  -H "Authorization: Bearer illari_YOUR_KEY" \
  -H "content-type: application/json" \
  -d '{
    "name": "nightly-etl",
    "cronExpression": "0 2 * * *",
    "timezone": "America/Chicago",
    "gracePeriodSeconds": 600,
    "metricRules": [
      { "kind": "threshold", "metric": "rows", "op": "lt", "value": 1 }
    ]
  }'
response — 201
{
  "data": {
    "id": "377aee8b-cf90-4cc4-9a8a-f29d6ae21a3b",
    "name": "nightly-etl",
    "command": null,
    "pingKey": "48c28871cf371128221df895ca3f9cfa",
    "badgeKey": "80b66c60e12ef7feb259c87a",
    "cronExpression": "0 2 * * *",
    "timezone": "America/Chicago",
    "gracePeriodSeconds": 600,
    "maxRuntimeSeconds": null,
    "metricRules": [
      { "kind": "threshold", "metric": "rows", "op": "lt", "value": 1 }
    ],
    "status": "pending",
    "paused": false,
    "snoozedUntil": null,
    "lastPingAt": null,
    "nextExpectedAt": "2026-09-01T07:00:00.000Z",
    "createdAt": "2026-08-31T19:36:00.018Z"
  }
}

Retrieve a monitor

GET /monitors/{id}

Path parameters

NameTypeNotes
idstring (uuid)The monitor id.
request
curl -fsS https://illari.dev/api/v1/monitors/<id> \
  -H "Authorization: Bearer illari_YOUR_KEY"

Returns { "data": Monitor }, or 404 if the key cannot see that monitor.

Update a monitor

PATCH /monitors/{id}

Partial update: only the keys present in the body change. Accepts every POST body field, plus:

  • paused (boolean). Resuming resets the schedule clock, so paused time never counts as late.
  • snoozedUntil (future ISO 8601 string, or null to wake now).

Changing cronExpression or timezone recomputes nextExpectedAt. Returns { "data": Monitor }.

request — pause
curl -fsS -X PATCH https://illari.dev/api/v1/monitors/<id> \
  -H "Authorization: Bearer illari_YOUR_KEY" \
  -H "content-type: application/json" \
  -d '{ "paused": true }'
request — add a baseline-anomaly rule
curl -fsS -X PATCH https://illari.dev/api/v1/monitors/<id> \
  -H "Authorization: Bearer illari_YOUR_KEY" \
  -H "content-type: application/json" \
  -d '{
    "metricRules": [
      { "kind": "anomaly", "metric": "cost_usd", "direction": "up" }
    ]
  }'

Delete a monitor

DELETE /monitors/{id}

Deletes the monitor and its check-in history. Returns 204 with no body. The ping URL then returns 404.

request
curl -fsS -X DELETE https://illari.dev/api/v1/monitors/<id> \
  -H "Authorization: Bearer illari_YOUR_KEY"

List a monitor's check-ins

GET /monitors/{id}/pings

Check-ins for one monitor, newest first.

Query parameters

NameTypeNotes
limitinteger1–200. Default 50.
beforestring (ISO 8601)Return check-ins received strictly before this time. See Pagination.
response — 200
{
  "data": [
    {
      "id": "9f1c3a2e-…",
      "monitorId": "377aee8b-…",
      "receivedAt": "2026-08-31T07:02:11.000Z",
      "sourceIp": "203.0.113.7",
      "kind": "success",
      "exitCode": 0,
      "durationMs": 41230,
      "body": null,
      "metrics": { "rows": 4123 }
    }
  ],
  "nextBefore": "2026-08-31T07:02:11.000Z"
}

Data models

Monitor

FieldTypeNotes
idstring (uuid)Read-only.
accountIdstring (uuid)Read-only.
namestringNon-empty.
commandstring | null≤ 500 chars. Shown in alerts. Never executed.
pingKeystringRead-only. The credential in https://illari.dev/ping/<pingKey>.
badgeKeystringRead-only. For the public status badge SVG.
cronExpressionstring | nullNull for a grace-only monitor.
timezonestringIANA name. Default "UTC".
gracePeriodSecondsinteger0–86400. Default 300.
maxRuntimeSecondsinteger | null1–604800, or null when hung-run detection is off.
metricRulesMetricRule[]Default []. Pro only.
statusstringRead-only. One of pending up late down.
pausedbooleanDefault false.
snoozedUntilstring | nullISO 8601. Null when not snoozed.
lastPingAtstring | nullRead-only. ISO 8601.
nextExpectedAtstring | nullRead-only. ISO 8601. Recomputed on schedule changes.
lastAlertSentAt, lastNotifiedAtstring | nullRead-only. Incident and flap-guard bookkeeping.
createdAtstringRead-only. ISO 8601.

MetricRule

A monitor carries an array of rules (Pro), checked against the numbers a completion ping reports. Two kinds:

Threshold — a fixed condition

FieldTypeNotes
kindstring"threshold". Optional; assumed when absent.
metricstringA name the job reports on a ping. Starts with a letter; letters, digits, dot, dash after; 40 chars max.
opstringOne of lt lte gt gte eq ne.
valuenumberThe threshold.

Anomaly — a move off the recent baseline

FieldTypeNotes
kindstring"anomaly". Required.
metricstringSame pattern as above.
directionstringOne of up down both. Needs ~8 prior runs of the metric to establish a baseline.

Ping

FieldTypeNotes
id, monitorIdstring (uuid)
receivedAtstringISO 8601.
sourceIpstring | nullWhere the ping came from.
kindstringOne of success start fail.
exitCodeinteger | nullFrom /ping/<key>/<code>.
durationMsinteger | nullWall-clock from the matching start ping.
bodystring | nullCaptured request body, truncated to ~10 KB.
metricsobject | nullNumeric key/value pairs sent with the ping.

Changelog

  • 2026-08-31metricRules gains anomaly rules ({ "kind": "anomaly", … }). Existing threshold rules are unchanged; kind is optional on them.
  • 2026-08-31v1 launch: /monitors CRUD, /monitors/<id>/pings, bearer-key auth.

A Terraform provider is planned on top of this API and the OpenAPI spec.

Back to the docs, or [email protected] for anything not covered.