Management API
v1A 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.
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.
{ "error": "invalid cron expression" }| Status | Meaning |
|---|---|
400 | A field failed validation: bad cron expression, unknown timezone, a number out of range, malformed JSON. |
401 | Missing, malformed, or revoked API key. Response carries WWW-Authenticate: Bearer. |
403 | The account is at its plan's monitor limit, or metricRules was sent on a Free account. |
404 | No 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.
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.
curl -fsS https://illari.dev/api/v1/monitors \
-H "Authorization: Bearer illari_YOUR_KEY"{
"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
| Field | Type | Notes |
|---|---|---|
name | string | Required. Non-empty. |
command | string | null | Optional. ≤ 500 chars. Free text, never executed. |
cronExpression | string | null | Optional. 5-field cron or a macro (@daily). Null for a grace-only monitor. |
timezone | string | Optional. IANA name. Default "UTC". |
gracePeriodSeconds | integer | Optional. 0–86400. Default 300. |
maxRuntimeSeconds | integer | null | Optional. 1–604800. Hung-run detection. Null = off. |
metricRules | MetricRule[] | Optional. Pro only. See the model below. |
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 }
]
}'{
"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
| Name | Type | Notes |
|---|---|---|
id | string (uuid) | The monitor id. |
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, ornullto wake now).
Changing cronExpression or timezone recomputes nextExpectedAt. Returns { "data": Monitor }.
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 }'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.
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
| Name | Type | Notes |
|---|---|---|
limit | integer | 1–200. Default 50. |
before | string (ISO 8601) | Return check-ins received strictly before this time. See Pagination. |
{
"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
| Field | Type | Notes |
|---|---|---|
id | string (uuid) | Read-only. |
accountId | string (uuid) | Read-only. |
name | string | Non-empty. |
command | string | null | ≤ 500 chars. Shown in alerts. Never executed. |
pingKey | string | Read-only. The credential in https://illari.dev/ping/<pingKey>. |
badgeKey | string | Read-only. For the public status badge SVG. |
cronExpression | string | null | Null for a grace-only monitor. |
timezone | string | IANA name. Default "UTC". |
gracePeriodSeconds | integer | 0–86400. Default 300. |
maxRuntimeSeconds | integer | null | 1–604800, or null when hung-run detection is off. |
metricRules | MetricRule[] | Default []. Pro only. |
status | string | Read-only. One of pending up late down. |
paused | boolean | Default false. |
snoozedUntil | string | null | ISO 8601. Null when not snoozed. |
lastPingAt | string | null | Read-only. ISO 8601. |
nextExpectedAt | string | null | Read-only. ISO 8601. Recomputed on schedule changes. |
lastAlertSentAt, lastNotifiedAt | string | null | Read-only. Incident and flap-guard bookkeeping. |
createdAt | string | Read-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
| Field | Type | Notes |
|---|---|---|
kind | string | "threshold". Optional; assumed when absent. |
metric | string | A name the job reports on a ping. Starts with a letter; letters, digits, dot, dash after; 40 chars max. |
op | string | One of lt lte gt gte eq ne. |
value | number | The threshold. |
Anomaly — a move off the recent baseline
| Field | Type | Notes |
|---|---|---|
kind | string | "anomaly". Required. |
metric | string | Same pattern as above. |
direction | string | One of up down both. Needs ~8 prior runs of the metric to establish a baseline. |
Ping
| Field | Type | Notes |
|---|---|---|
id, monitorId | string (uuid) | |
receivedAt | string | ISO 8601. |
sourceIp | string | null | Where the ping came from. |
kind | string | One of success start fail. |
exitCode | integer | null | From /ping/<key>/<code>. |
durationMs | integer | null | Wall-clock from the matching start ping. |
body | string | null | Captured request body, truncated to ~10 KB. |
metrics | object | null | Numeric key/value pairs sent with the ping. |
Changelog
- 2026-08-31 —
metricRulesgains anomaly rules ({ "kind": "anomaly", … }). Existing threshold rules are unchanged;kindis optional on them. - 2026-08-31 —
v1launch:/monitorsCRUD,/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.