Skip to content

API Monitors

Base URL: https://api.okstatus.eu/api/v1/monitors — every request needs an Authorization: Bearer oks_live_... header, see Authentication.

GET /api/v1/monitors?page=1&per_page=50

Returns a paginated list scoped to your organization (per_page up to 100).

Response

{
"monitors": [
{
"id": "...",
"name": "...",
"url": "...",
"type": "http",
"interval": 60,
"status": "active",
"tags": ["prod"]
}
],
"total": 12,
"page": 1,
"perPage": 50,
"pages": 1
}
POST /api/v1/monitors
Content-Type: application/json
FieldTypeRequiredDescription
namestring✅Monitor name (1–100 chars)
urlstring✅The target: an http(s):// URL for http and llm, a host for ping, tcp and dns (example.com), a connection URL for databases — see each monitor type
typeenumhttp, tcp, ping, dns, grpc, llm, push, group, postgres, mysql, mongodb, smtp, imap or redis — defaults to http
intervalnumberSeconds between checks, min 30 — defaults to 60. Your plan’s floor still applies (300 s on Free, 60 s on Pro)
regionsstring[]Region codes, 1–5 of them — defaults to ["fr-dc3"]. See Regions
acceptedStatusCodesstring[]http: codes or ranges counted as up, e.g. ["200-299", "301"] — defaults to ["200-299"]
tagsstring[]Up to 5 tags of 30 characters. Stored in lowercase if your organization chose that in Settings → Tags
keywordstringhttp: text the response body must contain
followRedirectsbooleanhttp: follow 3xx redirects — defaults to true. With false, the redirect response itself is judged
httpMethodenumhttp: GET, POST, PUT, PATCH, DELETE, HEAD or OPTIONS
httpHeadersobjecthttp: request headers. Never returned: reading the monitor gives "***"
httpBodystringhttp: request body, with httpBodyEncoding = json, form, xml or text
ignoreTlsbooleanhttp: accept an invalid or self-signed certificate
portnumbertcp: port to connect to
dnsRecordTypeenumdns: A, AAAA, CNAME, MX, NS, TXT, SOA, CAA or SRV
dnsExpectedValuestringdns: value the answer must contain
dnsServerstringdns: resolver to query instead of the default one
retriesnumberConsecutive failed checks tolerated before the monitor is down (0–5) — defaults to 1
severity3xxenumhttp: a redirect that is not accepted counts as degraded (default) or down
latencyThresholdMsintegerResponse time (50–60000 ms) above which the monitor turns degraded and alerts, after max(2, retries + 1) slow checks in a row; null turns it off. See Response time alerts
latencyPublicbooleanfalse keeps slowness off public status pages (default true)
latencyAnomalybooleanAlert when the response time leaves its learned usual range (Max and Enterprise, 7 days of learning; refused with 403 below Max). See Response time alerts
sloTargetnumberSLO objective in percent over 30 rolling days (50 to 99.999, e.g. 99.9); null removes it. Max and Enterprise, refused with 403 below. See SLOs and error budget
keywordInvertbooleanhttp: the monitor is down when keyword is found
jsonPath, jsonOperator, jsonExpectedValuehttp: assertion on a JSON response (==, !=, >, <, >=, <=, contains). Not combinable with keyword
basicAuthUser / basicAuthPassstringBasic auth, and the credential pair of database, SMTP, IMAP and Redis monitors. Stored encrypted
authConfigobjectNon-Basic authentication — see below
dbQuerystringpostgres, mysql, mongodb: query run on each check
gracePeriodnumberpush: seconds without a ping before the monitor is down. The response carries the pushUrl to call
childMonitorIdsstring[]group: the monitors it aggregates
llmProvider, llmApiKey, llmConfigllm: see the interactive reference

Returns 201 with { "data": Monitor }.

A monitor is always created running and unmuted: pause or mute it with a PATCH.

authConfig carries one method, discriminated by type (full reference: Authentication):

{ "type": "bearer", "token": "…" }
{ "type": "apikey", "in": "header", "name": "X-API-Key", "value": "…" }
{ "type": "apikey", "in": "query", "name": "api_key", "value": "…" }
{ "type": "cookie", "cookie": "session=…; csrf=…" }
{ "type": "oauth2", "tokenUrl": "https://login.example.com/token", "clientId": "…", "clientSecret": "…", "scope": "…", "audience": "…", "authStyle": "basic" }
{ "type": "mtls", "cert": "-----BEGIN CERTIFICATE-----…", "key": "-----BEGIN PRIVATE KEY-----…", "ca": "…" }

Reading a monitor back returns the method and its non-secret settings, with each secret replaced by "***". Sending that mask back on PATCH keeps the stored value — which is what lets you round-trip a monitor through GET then PATCH without wiping its credentials. "authConfig": null clears the authentication.

GET /api/v1/monitors/:id
PATCH /api/v1/monitors/:id
DELETE /api/v1/monitors/:id

PATCH accepts the fields of create except type (all optional — only the fields you send change), plus:

FieldTypeDescription
statusenum"paused" stops the checks, "active" resumes them
isMutedbooleantrue stops the alerts while the checks keep running

To remove a value, send null: "keyword": null, "dnsExpectedValue": null, "port": null, "authConfig": null, "basicAuthUser": null. "tags": [] removes every tag.

Terminal window
curl -X PATCH https://api.okstatus.eu/api/v1/monitors/$ID \
-H "Authorization: Bearer $OKSTATUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "paused", "tags": ["prod", "payments"], "keyword": null }'

DELETE returns { "data": { "deleted": true } }.

GET /api/v1/monitors/:id/alert-channels
PUT /api/v1/monitors/:id/alert-channels

GET returns the ids of the channels attached to the monitor:

{ "data": { "channelIds": ["3f6e2b1a-...", "9c1d4e7f-..."] } }

PUT replaces that set — an empty list detaches every channel:

{ "channelIds": ["3f6e2b1a-..."] }

The ids are those of GET /api/v1/alert-channels. An id that is not one of your organization’s channels is refused with 404 NOT_FOUND, and nothing is changed. A channel that stays attached keeps its per-monitor settings (which kinds of alert it receives).

regions takes public region codes (see Regions and intervals), and on plans with private agents:

  • "private" — any of your private agents runs the check;
  • "private:<agent id>" — that agent only.
GET /api/v1/private-agents

lists your agents, each with the region value to use:

{
"data": [
{
"id": "5a0c…",
"name": "dc-paris",
"site": "Paris",
"region": "private:5a0c…",
"status": "up",
"suspended": false,
"version": "1.0.0",
"hostname": "probe-1",
"platform": "linux/amd64",
"lastHeartbeatAt": "2026-10-10T07:00:00.000Z"
}
],
"meta": { "eligible": true, "limit": 5, "latestVersion": "1.0.0" }
}

The list is read-only: an agent is enrolled from the dashboard, because enrolling hands out a credential. Enrollment tokens are never returned.

GET /api/v1/monitors/:id/checks?page=1&per_page=50
GET /api/v1/monitors/:id/uptime?range=24h
GET /api/v1/slos?status=at_risk
GET /api/v1/monitors/:id/slo?target=99.9

GET /slos lists every SLO of the organization, monitors and groups, worst first: kind (monitor or group), id, name, target, budgetMinutes, consumedMinutes, remainingMinutes, remainingPercent, availability30d, incidents (outages in the window), status (ok, at_risk, exhausted) and exhaustsAt (when the budget runs out at the last 7 days’ pace, or null). status filters the list.

GET /monitors/:id/slo returns the same figures for one monitor, plus series (the budget left over the last 30 days). target previews an objective on a monitor that has none. Both answer 403 below Max. See SLOs and error budget.

404 NOT_FOUND if the monitor doesn’t exist in your org. When a create or an update is refused, the error carries the reason — for example:

CodeMeaning
VALIDATION_ERRORA field is invalid; message names it
PLAN_LIMIT_REACHEDYour plan’s number of monitors is reached
PLAN_INTERVAL_TOO_LOWThe interval is below your plan’s minimum
PLAN_REGION_NOT_ALLOWEDA region is not included in your plan
PLAN_REGIONS_PER_MONITORToo many regions for one monitor on your plan
INVALID_URLThe target is a private or reserved address
UPSTREAM_ERRORThe monitoring engine failed without giving a reason

See Authentication for the shared error format and rate limits.

PlanMax monitorsMin intervalRegions per monitor
Free5300s2
Pro2060s3
Max8030s5
Enterprise500 (more on request)30s5

Limits are enforced on create: an organization already above a lowered limit keeps what it has, it just can’t add more.