Skip to main content

Uptimia API v2 (2.0.0)

Download OpenAPI specification:Download

The Uptimia REST API lets you do everything you can do in the web app — manage monitors, contacts, status pages, maintenance windows, reports and teams, and read incidents, logs and uptime statistics — over HTTPS, returning JSON.

This is API v2, the current version. The v1 API remains available but is legacy; new integrations should use v2.

Getting started

Uptimia is a website uptime and performance monitoring tool. With the API you can access the features you normally use in your browser via simple HTTPS calls. The API supports the standard GET, POST, PATCH and DELETE methods.

Send requests to the host where your account lives:

  • https://www.uptimia.com/api/v2/ for accounts created at www.uptimia.com
  • https://app.uptimia.com/api/v2/ for accounts created at app.uptimia.com (AppSumo)

An API key works only on the host that issued it. A key from app.uptimia.com sent to www.uptimia.com, or the other way round, returns 401 invalid_api_key.

Every call needs an API key — see Authentication below — then browse the available endpoints in the reference that follows.

Authentication

The Uptimia API uses Bearer authentication. Include your API key in an Authorization header on every request:

Authorization: Bearer YOUR_API_KEY

How to create an API key

  1. Log in to your Uptimia account and open Settings → API Keys.
  2. Click Create API key and give it a name (for your own reference).
  3. Copy the key that is shown — for security you won't be able to see it again.
  4. Use the key in the Authorization header of your requests.

Keep your API key secret. Don't share it or commit it to source control. If you think a key may be compromised, delete it and create a new one.

How to use an API key

Pass the key as a Bearer token. For example, with cURL:

curl "https://www.uptimia.com/api/v2/uptime" \
  -H "Authorization: Bearer YOUR_API_KEY"

For an app.uptimia.com account, use https://app.uptimia.com/api/v2/uptime.

When the API key is invalid

Failed authentication returns 401 Unauthorized with the same error envelope as every other API error (status / code / message).

A request with no Authorization header at all is rejected by the endpoint itself:

{
  "status": "error",
  "code": "unauthorized",
  "message": "Authentication required"
}

A request that does carry an Authorization header, but whose key is unknown, revoked, malformed (anything other than Bearer YOUR_API_KEY), belongs to a deleted account, was minted for a team seat that no longer exists, or was issued on the other host (www.uptimia.com vs app.uptimia.com), is rejected before the endpoint runs:

{
  "status": "error",
  "code": "invalid_api_key",
  "message": "API key invalid",
  "error_code": "invalid_api_key"
}

error_code repeats code for clients written against older versions of these docs. Read code, and treat any 401 as "not authenticated".

Alert recipients

Every monitor carries a contacts array naming who gets alerted. Each entry is a reference, not an address:

{ "id": 41930, "is_team": 0, "is_user": 0, "is_operator": 1, "is_individual_contact": 0 }

The flag decides which kind of thing id refers to, and each kind lives in its own table with its own id sequence:

Flag set id refers to Resolve it with Who is actually alerted
is_team a team GET /api/v2/teams the contacts of every member of that team
is_user the account owner GET /api/v2/users the contacts the owner owns (operator_id 0)
is_operator a team-member seat GET /api/v2/users/{id} every contact that seat owns
is_individual_contact one contact GET /api/v2/contacts/{id} that one contact

Ids are unique per kind, not across kinds. A team and a contact can both have id 41930 and mean completely different things. Always read the flags before resolving an id — never guess the endpoint.

One entry can mean several addresses

Only is_individual_contact names a single address. The other three name a seat or group, which is expanded when the alert is sent. A monitor showing just one is_operator entry may well page a dozen addresses — every contact belonging to that seat, including ones added after the monitor was configured.

So a short contacts array does not mean few recipients. To see the addresses a monitor resolves to, use:

GET /api/v2/contacts/selected/{monitorId}/{type}

It returns your whole address book with an is_selected flag on each contact, already accounting for team, owner and seat expansion, plus an operator_id telling you which seat owns each contact.

Contact verification

Alerts go only to verified e-mail addresses and phone numbers. There is no setting to turn this off. A new e-mail, SMS or phone-call contact, or one whose address or number changes, starts unverified (is_confirmed 0, verified false) and gets a verification message at once: an e-mail with a confirmation link, or an SMS with a 6-digit code and a link. Verification SMS are free. Integrations need no verification.

Until the link is used or the code is entered, every alert to the contact is recorded as skipped / contact_unconfirmed in its delivery record, and an escalation step counts it as not reached.

Call What it does
POST /api/v2/contacts/{id}/send-verification send the message again (also at /request-confirmation)
POST /api/v2/contacts/{id}/verify enter the SMS code (also at /confirm)
POST /api/v2/contacts/{id}/test send a test alert to a verified contact
GET /api/v2/contacts/verification-summary unverified contacts that active monitors alert

Your own login address is verified without a message once your account e-mail is verified. A link works for 7 days, and one reminder goes out after 24 hours.

API v1. /api/v1/contacts keeps its paths and response shapes. A contact created or changed through v1 follows the same rule: it starts unverified, the verification message goes out, and it receives no alert until it is verified. v1 responses do not carry the verification fields; read them from GET /api/v2/contacts/{id}.

Event subscriptions

Instead of polling incidents, subscribe a URL to an event and Uptimia POSTs to it the moment the event happens. This is the mechanism behind the Uptimia app in Zapier, and it is open to any tool that can receive an HTTPS request — Make, n8n, Pipedream, or your own service.

Events

Event Fires when Extra keys
monitor.down a check is confirmed down (after its alert delay) —
monitor.up the check passes again —
expiry.warning an SSL certificate or a domain is nearing expiry kind: ssl or domain
incident.acknowledged someone acknowledges the incident acknowledged_by

monitor.down respects the monitor's alert delay ("alert after N seconds down"), the same as your contacts: an outage that recovers before the delay sends neither monitor.down nor monitor.up. An already-expired certificate or domain is a monitor.down, not an expiry.warning.

Managing subscriptions

POST   /api/v2/hooks                 create a subscription
GET    /api/v2/hooks                 list your subscriptions
DELETE /api/v2/hooks/{id}            remove one
GET    /api/v2/hooks/events?event=monitor.down&limit=3
                                     recent real events, in the delivery shape (for samples)

POST /api/v2/hooks takes a JSON body with event and target_url, and optionally monitor_type and/or monitor_id to narrow the subscription to one monitor family or one monitor:

{
  "event": "monitor.down",
  "target_url": "https://example.com/uptimia/down",
  "monitor_type": "uptime",
  "monitor_id": 4471
}

It answers 201 Created with the subscription, including its secret — returned once, on creation, and never again. Store it: every delivery is signed with it. Creating a subscription that already exists (same event, target URL and filters) answers 409 Conflict with the existing subscription's id, so a client that retries a create never ends up with two. If that existing subscription was disabled (see below), it is replaced instead: the create answers 201 Created with a new id and secret.

The target URL must be https and publicly reachable; private, loopback and otherwise reserved addresses are refused. A Zapier target must be on hooks.zapier.com.

Deliveries

Every delivery is an HTTP POST with a JSON body and three headers:

Header Value
X-Uptimia-Event the event name, e.g. monitor.down
X-Uptimia-Delivery the id of this queued delivery — retries of it carry the same id
X-Uptimia-Signature sha256=<hex> — HMAC-SHA256 of the raw request body, keyed with the subscription's secret

The body carries the same keys for every event: event_id (stable per event — a retried delivery reuses it, so deduplicate on this), event, occurred_at, then the monitor (id, monitor_type, monitor_name, monitor_unique_id, monitor_url, monitor_notes, cp_url — the monitor's page in the control panel), the incident (monitor_status, severity, incident_start_time, incident_end_time, incident_duration_seconds, error_reason), the one-line message, kind and acknowledged_by. kind is ssl or domain on expiry.warning and empty otherwise (the days remaining are in message and error_reason, e.g. "will expire in 6 days"); acknowledged_by is set on incident.acknowledged and empty otherwise. When several monitors on one escalation policy fail together you receive one event per monitor, never a bundle. No event carries an acknowledge link.

Responses, retries and removal

  • Any 2xx counts as delivered.
  • 410 Gone tells Uptimia the endpoint is finished with the subscription: it is deleted and nothing more is sent. A 404 from hooks.zapier.com — what Zapier answers once a Zap is turned off — is treated the same way.
  • Any other failure (a timeout, a 5xx, a refused connection) is retried five times with backoff — up to six attempts per delivery, about 15 minutes in all.
  • After 25 consecutive failed deliveries (events whose every attempt failed; a single successful delivery resets the count) the subscription is disabled: its disabled_at is set, it stops receiving events, and it stays listed in GET /api/v2/hooks so you can see why the events stopped. Re-create it (the same POST /api/v2/hooks) to resume: the disabled subscription is replaced by a new one with a new secret.

Verifying the signature

Compute HMAC-SHA256 over the raw request body (before any JSON parsing) with the subscription's secret, and compare it to the header in constant time.

PHP:

$rawBody  = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
if (!hash_equals($expected, $_SERVER['HTTP_X_UPTIMIA_SIGNATURE'] ?? '')) {
    http_response_code(401);
    exit;
}

Node:

const crypto = require('crypto');
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const given = req.headers['x-uptimia-signature'] || '';
const ok = expected.length === given.length
        && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given));

Answer 2xx only after the signature checks out; an unsigned or mis-signed request should be rejected and never acted on.

Authentication

Exchanging account credentials for an API key (mobile / native sign-in).

Exchange credentials for an API key (mobile/native sign-in)

Verifies an account's email and password and returns a Bearer API key the native app stores securely and sends on every later /api/v2 request.

Lifetime and refresh. The key never expires and there is no refresh token — it is the same kind of key the control panel's API keys screen issues, so once stored it keeps working until it is revoked or the account's (or that seat's) password changes: a password change or reset revokes every key this endpoint minted for that identity, except the key the change itself was made with. There is nothing to renew and no rotation schedule to follow: call this endpoint once per device, keep the key, and only call it again after a revocation or a re-install. Every successful call mints a new key rather than returning an existing one, so an app that re-authenticates on each launch accumulates one key per launch in the account's API keys list. The response carries the new key's id as api_key_id. To revoke the key on sign-out, call DELETE /api/v2/auth/token with it as the Bearer (works for every team-member role); an owner or admin can also revoke any key with DELETE /api/v2/api-keys/{id}. Either takes effect on the next request. The account owner is emailed each time a key is created, including by this endpoint.

Two-factor. If the account (or, for a team member, that seat) has two-factor authentication enabled, a call without code responds 401 2fa_required with method saying where the code comes from. method: "email": that call emailed a six-digit one-time code; the app re-sends the same email and password together with the code and the challenge. method: "totp" (authenticator app): nothing is sent, the user reads the six-digit code from their authenticator app (a one-time recovery code is accepted too); a code may be sent on the very first call. A challenge allows five verification attempts; after that it is spent and a resend will not revive it. Wrong, replayed or spent codes answer 401 invalid_2fa_code. For authenticator-app accounts, ten wrong codes in a row lock code entry for 15 minutes (429 2fa_locked), and 503 totp_unavailable means the server cannot check app codes at the moment.

Scope of the key. Signing in as a team member mints a key stamped with that seat, so it carries the seat's role and group scope rather than full owner authority; operator_id in the response tells the app which it got.

The returned api_key is the FULL secret and is revealed only once — persist it in secure device storage, because every later read masks it. This endpoint is public: send no Authorization header on it (a stale Bearer is rejected by the auth layer before this handler runs). It is rate limited to 20 attempts per 15 minutes per client IP, and the account itself locks out after 5 consecutive failures.

Authorizations:
bearerAuth
Request Body schema: application/json
email
required
string

Account email address. Surrounding whitespace is trimmed. A team member signs in with their own address.

password
required
string <password>

Account password, sent verbatim (not trimmed)

code
string

Two-factor code, required only when the account has 2FA enabled. Email method: the six digits from the email the first call sends, on the second call. Authenticator-app method: the six digits from the app (or a one-time recovery code, xxxxx-xxxxx), on any call. Send the email and password again alongside it.

challenge
string

Opaque handle returned with the 401 2fa_required response. Send it back unchanged together with code: the code is verified against the session that emailed it, which is not the session this call mints.

device_name
string <= 100 characters

Optional label stored on the minted key and shown in the API keys list. Longer values are silently truncated to 100 characters; an empty or omitted value stores Mobile app.

Responses

Request samples

Content type
application/json
{
  • "email": "[email protected]",
  • "password": "pa$$word",
  • "code": "482915",
  • "challenge": "c1f0…",
  • "device_name": "iPhone 15"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Revoke the API key this request is signed with (mobile sign-out)

Deletes the API key sent as Authorization: Bearer <api_key> on this very request, so a signed-out device leaves no working credential behind. It needs no key id and no special permission: every team-member role may call it, because it can only delete the caller's own key. The key stops working immediately; later calls with it answer 401 invalid_api_key. A control-panel session (cookie, no Bearer) has no key to revoke and gets 400 api_key_required.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Uptime Monitors

HTTP/website uptime monitoring — create, read, update, delete and view stats.

List all uptime monitors

Returns a paginated list of all uptime monitors for the authenticated account. Supports filtering by monitor status.

Authorizations:
bearerAuth
query Parameters
limit
integer
Example: limit=25

Maximum number of monitors to return (0 = no limit)

offset
integer
Example: offset=0

Number of monitors to skip

show_is_up
boolean
Default: true

Include monitors that are up

show_is_critical
boolean
Default: true

Include monitors with critical incidents

show_is_trouble
boolean
Default: true

Include monitors with trouble incidents

show_is_suspended
boolean
Default: true

Include suspended monitors

show_is_paused
boolean
Default: true

Include paused monitors

show_is_maintenance
boolean
Default: true

Include monitors in maintenance

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new uptime monitor

Creates a new uptime monitor with the specified configuration. The domain field is required.

Authorizations:
bearerAuth
Request Body schema: application/json
domain
required
string

URL or hostname to monitor

unique_id
string

Custom unique identifier used in public status page URLs.

project_name
string

Monitor display name

monit_type
integer

Monitor type: 1=HTTP, 2=HTTPS, 3=TCP, 4=PING, 5=DNS, 6=UDP, 7=SMTP, 8=POP3, 9=IMAP

port
string

Port number (auto-detected if empty)

username
string

HTTP Basic Auth username

password
string

HTTP Basic Auth password

string_send
string

String to send for TCP/UDP protocol checks

string_expect
string

Expected string in TCP/UDP response

encrypted
integer

Use SSL/TLS for TCP connections (0=no, 1=yes)

monitoring_interval_slider
integer [ 0 .. 65 ]

How often to check, in MINUTES (0-60; 0 = every 30 seconds). Values 61-65 are period codes for longer cadences: 61=2h, 62=3h, 63=6h, 64=12h, 65=24h. A value below your plan's fastest cadence is raised to that floor.

report_down_slider
integer [ 0 .. 60 ]

How long an outage must persist before it is reported, in MINUTES (0-60). 0 reports as soon as the outage is confirmed.

probes
string

Monitoring locations: "all" for all locations, or comma-separated probe IDs

contacts
required
Array of integers

Contact IDs to notify on incidents

groups
Array of integers

Group IDs to assign the monitor to

object

Error types to report on

Array of objects

Keywords to check for in response body

Array of objects

Custom HTTP headers to send

payload
string

Raw POST/PUT request body

request_type
string
Enum: "GET" "POST" "PUT" "DELETE" "HEAD" "POSTRAW"

HTTP method for the check

follow_redirects
integer

Follow HTTP redirects (0=no, 1=yes)

max_timeout
integer

Maximum timeout in seconds

report_up
integer

Send notification when monitor recovers (0=no, 1=yes)

branding_id
integer

Branding template ID for notifications

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Responses

Request samples

Content type
application/json
{
  • "domain": "https://example.com",
  • "unique_id": "string",
  • "project_name": "My Website",
  • "monit_type": 2,
  • "port": "443",
  • "username": "string",
  • "password": "string",
  • "string_send": "string",
  • "string_expect": "string",
  • "encrypted": 0,
  • "monitoring_interval_slider": 5,
  • "report_down_slider": 1,
  • "probes": "all",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "error_types": {
    },
  • "keywords": [
    ],
  • "custom_headers": [
    ],
  • "payload": "string",
  • "request_type": "GET",
  • "follow_redirects": 1,
  • "max_timeout": 30,
  • "report_up": 0,
  • "branding_id": 0,
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single uptime monitor

Returns full details of a specific uptime monitor including configuration, status, and assigned contacts.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete an uptime monitor

Permanently deletes an uptime monitor and its associated reporting configuration. Incident and log data may be retained.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing uptime monitor

Updates an existing uptime monitor. Only include fields you want to change. Omitted fields retain their current values.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Request Body schema: application/json
is_paused
boolean

Pause (true) or resume (false) the monitor. When present, only the pause/resume action is performed and other fields are ignored.

unique_id
string

Custom unique identifier used in public status page URLs.

domain
string

URL or hostname to monitor

project_name
string

Monitor display name

monit_type
integer

Monitor type: 1=HTTP, 2=HTTPS, 3=TCP, 4=PING, 5=DNS, 6=UDP, 7=SMTP, 8=POP3, 9=IMAP

port
string

Port number

username
string

HTTP Basic Auth username

password
string

New HTTP Basic Auth password. Omitting it — or sending an empty string, which is what a GET response round-trips — keeps the stored secret. To remove the password, send clear_password: true.

clear_password
boolean

Set true to remove the stored HTTP Basic Auth password. Ignored when a non-empty password is sent in the same request (that rotates instead).

string_send
string

String to send for TCP/UDP checks

string_expect
string

Expected string in response

encrypted
integer

Use SSL/TLS for TCP connections (0=no, 1=yes)

monitoring_interval_slider
integer [ 0 .. 65 ]

How often to check, in MINUTES (0-60; 0 = every 30 seconds). Values 61-65 are period codes: 61=2h, 62=3h, 63=6h, 64=12h, 65=24h.

report_down_slider
integer [ 0 .. 60 ]

How long an outage must persist before it is reported, in MINUTES (0-60). 0 reports as soon as the outage is confirmed.

probes
string

Monitoring locations: "all" or comma-separated probe IDs

contacts
Array of integers

Contact IDs to notify

groups
Array of integers

Group IDs

error_types
object

Error types to report on

Array of objects

Keywords to check in the response body. Replaces the whole list; [] clears it.

custom_headers
Array of objects

Custom HTTP headers

payload
string

Raw POST/PUT request body

request_type
string
Enum: "GET" "POST" "PUT" "DELETE" "HEAD" "POSTRAW"

HTTP method

follow_redirects
integer

Follow HTTP redirects (0=no, 1=yes)

max_timeout
integer

Maximum timeout in seconds

report_up
integer

Send notification when monitor recovers (0=no, 1=yes)

branding_id
integer

Branding template ID

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Responses

Request samples

Content type
application/json
{
  • "is_paused": true,
  • "unique_id": "string",
  • "domain": "string",
  • "project_name": "string",
  • "monit_type": 0,
  • "port": "string",
  • "username": "string",
  • "password": "string",
  • "clear_password": true,
  • "string_send": "string",
  • "string_expect": "string",
  • "encrypted": 0,
  • "monitoring_interval_slider": 65,
  • "report_down_slider": 60,
  • "probes": "string",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "error_types": { },
  • "keywords": [
    ],
  • "custom_headers": [
    ],
  • "payload": "string",
  • "request_type": "GET",
  • "follow_redirects": 0,
  • "max_timeout": 0,
  • "report_up": 0,
  • "branding_id": 0,
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for an uptime monitor

Returns a list of incidents for the specified monitor within the given date range. Defaults to the last 30 days. date_start is raised to the account plan's history retention floor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of incidents to return

offset
integer

Number of incidents to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single incident

Returns details of a specific incident for the given uptime monitor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete an incident

Permanently deletes a specific incident and its associated status page threads. The incident must belong to the monitor in the path; otherwise 404 incident_not_found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

List monitoring logs across all monitors

Returns a paginated list of monitoring check logs across all uptime monitors for the authenticated account. Supports date range filtering and pagination. date_start is raised to the account plan's history retention floor, and an omitted date_start starts at that floor.

Authorizations:
bearerAuth
query Parameters
limit
integer
Example: limit=50

Maximum number of log entries to return (default 50)

offset
integer
Example: offset=0

Number of log entries to skip

date_start
integer

Start date as Unix timestamp

date_end
integer

End date as Unix timestamp

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

List monitoring logs

Returns monitoring check logs for the specified monitor, newest first. Defaults to the last 14 days and a page size of 20; use limit/offset to page through the whole window. date_start is raised to the account plan's history retention floor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
limit
integer
Example: limit=20

Page size (default 20)

offset
integer

Number of log entries to skip

date_start
integer

Start date as Unix timestamp to filter the log range (defaults to 14 days ago, raised to the plan retention floor)

date_end
integer

End date as Unix timestamp to filter the log range

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single monitoring log entry

Returns full details of a specific monitoring check log.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

logId
required
integer\d+
Example: 1756000000

Log entry ID — post-cutover this is the check's unix-second time, the same value the list endpoint returns as id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get timeline segments for an uptime monitor

Returns timeline segments showing uptime, downtime, maintenance, and unknown periods for the given date range. date_start is raised to the account plan's history retention floor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 7 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get availability percentages

Calculates uptime and downtime percentages for the specified monitor within the given date range. Defaults to the last 24 hours. date_start is raised to the account plan's history retention floor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 24 hours ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get response time history

Returns response time chart data for the specified monitor. Includes timing breakdown (DNS, connect, send, wait, receive) for HTTP/HTTPS monitors. Data is cached for 60 seconds. date_start is raised to the account plan's history retention floor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 24 hours ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

SSL Monitors

SSL/TLS certificate expiry and validity monitoring.

List all SSL monitors

Returns a paginated list of all SSL monitors for the authenticated account. Supports filtering by monitor status.

Authorizations:
bearerAuth
query Parameters
limit
integer
Example: limit=25

Maximum number of monitors to return (0 = no limit)

offset
integer
Example: offset=0

Number of monitors to skip

show_is_up
boolean
Default: true

Include monitors that are up

show_is_critical
boolean
Default: true

Include monitors with critical incidents

show_is_trouble
boolean
Default: true

Include monitors with trouble incidents

show_is_suspended
boolean
Default: true

Include suspended monitors

show_is_paused
boolean
Default: true

Include paused monitors

show_is_maintenance
boolean
Default: true

Include monitors in maintenance

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new SSL monitor

Creates a new SSL certificate monitor for the specified URL.

Authorizations:
bearerAuth
Request Body schema: application/json
url
required
string

URL to monitor SSL certificate for

region
integer

Monitoring region ID (defaults to 1).

project_name
string

Monitor display name

monitoring_interval_slider
integer

Check frequency in minutes (0-60; 0 = every 30 seconds) or a period code 61-65 (2h, 3h, 6h, 12h, 24h). -1 selects the 10-second cadence where enabled.

report_down_slider
integer

Minutes to wait before reporting an outage (0-60; 0 = report as soon as the outage is confirmed)

change_error_level_time
integer

Seconds before changing error level. Preferred field — sent in seconds by the editor.

change_error_level_time_slider
integer

Legacy slider value for the change error level time (1-10). Only used by the bulk path when change_error_level_time is omitted.

expire_alert_days
integer

Days before certificate expiry to alert

probes
string

Monitoring locations: "all" for all locations, or comma-separated probe IDs

contacts
Array of integers

Contact IDs to notify on incidents

groups
Array of integers

Group IDs to assign the monitor to

report_up
integer

Send notification when monitor recovers (0=no, 1=yes)

branding_id
integer

Branding template ID for notifications

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Responses

Request samples

Content type
application/json
{
  • "region": 1,
  • "project_name": "My Website SSL",
  • "monitoring_interval_slider": 5,
  • "report_down_slider": 1,
  • "change_error_level_time": 3600,
  • "change_error_level_time_slider": 5,
  • "expire_alert_days": 7,
  • "probes": "all",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "report_up": 0,
  • "branding_id": 0,
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single SSL monitor

Returns full details of a specific SSL monitor including configuration, status, certificate info, and assigned contacts.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete an SSL monitor

Permanently deletes an SSL monitor and its associated reporting configuration. Incident and log data may be retained.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing SSL monitor

Updates an existing SSL monitor. Only include fields you want to change. Omitted fields retain their current values.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Request Body schema: application/json
is_paused
boolean

Pause (true) or resume (false) the monitor. When present, only the pause/resume action is performed and other fields are ignored.

url
string

URL to monitor SSL certificate for

region
integer

Monitoring region ID (defaults to 1).

project_name
string

Monitor display name

monitoring_interval_slider
integer

Check frequency in minutes (0-60; 0 = every 30 seconds) or a period code 61-65 (2h, 3h, 6h, 12h, 24h)

report_down_slider
integer

Minutes to wait before reporting an outage (0-60)

change_error_level_time
integer

Seconds before changing error level. Preferred field — sent in seconds by the editor.

change_error_level_time_slider
integer

Legacy slider value for the change error level time (1-10). Only used by the bulk path when change_error_level_time is omitted.

expire_alert_days
integer

Days before certificate expiry to alert

probes
string

Monitoring locations: "all" or comma-separated probe IDs

contacts
Array of integers

Contact IDs to notify

groups
Array of integers

Group IDs

report_up
integer

Send notification when monitor recovers (0=no, 1=yes)

branding_id
integer

Branding template ID

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Responses

Request samples

Content type
application/json
{
  • "is_paused": true,
  • "url": "string",
  • "region": 1,
  • "project_name": "string",
  • "monitoring_interval_slider": 0,
  • "report_down_slider": 0,
  • "change_error_level_time": 3600,
  • "change_error_level_time_slider": 0,
  • "expire_alert_days": 0,
  • "probes": "string",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "report_up": 0,
  • "branding_id": 0,
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for an SSL monitor

Returns a list of incidents for the specified SSL monitor within the given date range. Defaults to the last 30 days.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of incidents to return

offset
integer

Number of incidents to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single SSL incident

Returns full details of a specific incident for the given SSL monitor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete an SSL incident

Permanently deletes a specific SSL incident and its associated status page threads. The incident must belong to the monitor in the path; otherwise 404 incident_not_found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

List SSL monitoring logs

Returns recent monitoring check logs for the specified SSL monitor. Shows the last 90 days of data, limited to 20 entries.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
limit
integer

Maximum number of log entries to return

offset
integer

Number of log entries to skip

date_start
integer

Start date as Unix timestamp to filter the log range

date_end
integer

End date as Unix timestamp to filter the log range

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single SSL monitoring log entry

Returns full details of a specific SSL monitoring check log.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

logId
required
integer\d+
Example: 1756000000

Log entry ID — post-cutover this is the check's unix-second time, the same value the list endpoint returns as id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get timeline segments for an SSL monitor

Returns up, down, maintenance and unknown timeline segments for the SSL monitor over the requested date range, suitable for rendering an availability timeline strip.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 7 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get SSL response time history

Returns response time and downtime chart data for the specified SSL monitor. Data is cached for 60 seconds.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 24 hours ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Domain Monitors

Domain registration / WHOIS expiry monitoring.

List all domain monitors

Returns a paginated list of all domain monitors for the authenticated account. Supports filtering by monitor status.

Authorizations:
bearerAuth
query Parameters
limit
integer
Example: limit=25

Maximum number of monitors to return (0 = no limit)

offset
integer
Example: offset=0

Number of monitors to skip

show_is_up
boolean
Default: true

Include monitors that are up

show_is_critical
boolean
Default: true

Include monitors with critical incidents

show_is_trouble
boolean
Default: true

Include monitors with trouble incidents

show_is_suspended
boolean
Default: true

Include suspended monitors

show_is_paused
boolean
Default: true

Include paused monitors

show_is_maintenance
boolean
Default: true

Include monitors in maintenance

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new domain monitor

Creates a new domain expiration monitor. Validates domain zone against supported TLD whitelist.

Authorizations:
bearerAuth
Request Body schema: application/json
url
required
string

Domain name to monitor (e.g. example.com)

project_name
required
string

Monitor display name

monitoring_interval_slider
integer

WHOIS check frequency, 71-79 (71 = every day … 79 = every 9 days)

monitoring_interval
integer

WHOIS check frequency in seconds, 86400-2592000 (1 to 30 days). Alternative to monitoring_interval_slider

report_down_slider
integer

Minutes to wait before reporting a failed check, 0-60 (0 = report as soon as the check fails)

expire_alert_days
integer

Days before domain expiry to alert (1-90, default 7)

expiry_date
string

Manual expiry date in YYYY-MM-DD format. Required for a manual zone (and for a third-level name in a zone that sells them): without it the create is refused with expiry_date_required. Ignored for other zones.

contacts
Array of integers

Contact IDs to notify on incidents

groups
Array of integers

Group IDs to assign the monitor to

report_up
integer

Send notification when monitor recovers (0=no, 1=yes)

branding_id
integer

Branding template ID for notifications

confirmations_required
integer

How many backup checks must agree before an outage is confirmed (1-3, default 3)

escalation_policy_id
integer

Escalation policy to alert through (0 = alert every recipient at once)

notes
string

Free-text operator note (plain text, up to 500 characters)

bulk_data
string

Bulk import: newline-separated list of domains

Responses

Request samples

Content type
application/json
{
  • "url": "example.com",
  • "project_name": "My Domain",
  • "monitoring_interval_slider": 77,
  • "monitoring_interval": 604800,
  • "report_down_slider": 0,
  • "expire_alert_days": 7,
  • "expiry_date": "2027-01-15",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "report_up": 0,
  • "branding_id": 0,
  • "confirmations_required": 3,
  • "escalation_policy_id": 0,
  • "notes": "",
  • "bulk_data": ""
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Look up a domain zone

Resolves a domain name (or a bare TLD) to its zone and reports whether the zone is monitored and whether its expiry date has to be supplied by hand. A manual zone has no queryable WHOIS server, so a monitor in it must be created with an expiry_date. The monitor editor calls this while the user types, to decide whether to show the expiry-date field.

Authorizations:
bearerAuth
query Parameters
url
string
Example: url=example.de

Domain name or URL to resolve (e.g. "example.de" or "https://example.de/path")

tld
string
Example: tld=example.de

Alias for url — accepted so a caller that already has the bare TLD can pass it directly

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single domain monitor

Returns full details of a specific domain monitor including WHOIS data, expiration info, registrar, and nameservers.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a domain monitor

Permanently deletes a domain monitor and its associated reporting configuration. Incident and log data may be retained.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing domain monitor

Updates an existing domain monitor. Only include fields you want to change. Omitted fields retain their current values.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Request Body schema: application/json
is_paused
boolean

Pause (true) or resume (false) the monitor. When present, only the pause/resume action is performed and other fields are ignored.

url
string

Domain name to monitor

project_name
string

Monitor display name

monitoring_interval_slider
integer

WHOIS check frequency, 71-79 (71 = every day … 79 = every 9 days)

monitoring_interval
integer

WHOIS check frequency in seconds, 86400-2592000 (1 to 30 days). Alternative to monitoring_interval_slider

report_down_slider
integer

Minutes to wait before reporting a failed check, 0-60

expire_alert_days
integer

Days before domain expiry to alert (1-90)

expiry_date
string

Manual expiry date in YYYY-MM-DD format (only for manual zones)

contacts
Array of integers

Contact IDs to notify

groups
Array of integers

Group IDs

report_up
integer

Send notification when monitor recovers (0=no, 1=yes)

branding_id
integer

Branding template ID

confirmations_required
integer

How many backup checks must agree before an outage is confirmed (1-3)

escalation_policy_id
integer

Escalation policy to alert through (0 = alert every recipient at once)

notes
string

Free-text operator note (plain text, up to 500 characters)

Responses

Request samples

Content type
application/json
{
  • "is_paused": true,
  • "url": "string",
  • "project_name": "string",
  • "monitoring_interval_slider": 0,
  • "monitoring_interval": 0,
  • "report_down_slider": 0,
  • "expire_alert_days": 0,
  • "expiry_date": "2027-01-15",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "report_up": 0,
  • "branding_id": 0,
  • "confirmations_required": 0,
  • "escalation_policy_id": 0,
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for a domain monitor

Returns a list of domain expiration incidents within the given date range. Defaults to the last 30 days. Domain-specific error codes: domain_expires_soon, domain_expires_very_soon, domain_expired.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of incidents to return

offset
integer

Number of incidents to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single domain incident

Returns details of a specific domain expiration incident.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a domain incident

Permanently deletes a specific domain expiration incident and its associated status page threads. The incident must belong to the monitor in the path; otherwise 404 incident_not_found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

List domain WHOIS check logs

Returns recent WHOIS monitoring check logs for the specified domain monitor. Shows the last 90 days of data, limited to 20 entries.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
limit
integer

Maximum number of log entries to return

offset
integer

Number of log entries to skip

date_start
integer

Start date as Unix timestamp to filter the log range

date_end
integer

End date as Unix timestamp to filter the log range

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single domain monitoring log entry

Returns full details of a specific domain WHOIS check log.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

logId
required
integer\d+

Log entry ID

Responses

Get timeline segments for a domain monitor

Returns up, down, maintenance and unknown timeline segments for the domain monitor over the requested date range, suitable for rendering an availability timeline strip.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 7 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Get domain WHOIS response time history

Returns WHOIS response time and downtime chart data for the specified domain monitor. Data is cached for 60 seconds.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 24 hours ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Speed Monitors

Full-page-load performance monitoring (the type key is "fpl").

List all speed monitors

Returns a paginated list of all speed monitors for the authenticated account. Supports filtering by monitor status.

Authorizations:
bearerAuth
query Parameters
limit
integer
Example: limit=25

Maximum number of monitors to return (0 = no limit)

offset
integer
Example: offset=0

Number of monitors to skip

show_is_up
boolean
Default: true

Include monitors that are up

show_is_critical
boolean
Default: true

Include monitors with critical incidents

show_is_trouble
boolean
Default: true

Include monitors with trouble incidents

show_is_suspended
boolean
Default: true

Include suspended monitors

show_is_paused
boolean
Default: true

Include paused monitors

show_is_maintenance
boolean
Default: true

Include monitors in maintenance

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new speed monitor

Creates a new speed/page-load monitor for the specified URL. Speed and Transaction monitors share ONE "Advanced" plan pool, so creation is refused with 403 plan_exceeded once that pool is full — the check runs before anything is written. Three fields must be supplied: url, project_name and contacts; every other field falls back to its create default. An explicit probes list must name at least 6 locations, and location_profile records which saved Location Profile that list came from without itself changing where the monitor runs.

Authorizations:
bearerAuth
Request Body schema: application/json
url
required
string

URL to monitor page speed for. Required — an absent or empty value is refused with invalid_url before anything else runs.

project_name
required
string

Monitor display name. Required on create: it has no usable default, so an absent or empty value is always refused with no_project_name once url is present. It must also be unique within the account (already_exists).

monitoring_interval_slider
integer

Monitoring interval slider value: 0-60 (minutes; 0 = every 30 seconds) or a period code 61-65 (2h, 3h, 6h, 12h, 24h). Out of range is refused with monitoring_interval_invalid. Defaults to 5.

report_down_slider
integer

Report-down delay slider value: 0-60 minutes to wait before an outage is reported (0 = report as soon as it is confirmed). Out of range is refused with report_down_invalid. Defaults to 1.

probes
string

Monitoring locations: "all" for every location, or a comma-separated list of probe ids. An explicit list must name at least 6 probes, otherwise too_few_locations. Defaults to "all".

contacts
required
Array of integers

Alert recipient ids. Required in practice: on create an omitted (or empty) list is refused with no_contacts_provided, because a monitor that can alert nobody is not worth running. Bare ids are normalized to individual contacts; every id must belong to the account.

groups
Array of integers

Monitor-group ids to assign the monitor to. Every id must belong to the account (invalid_groups otherwise). A scoped operator's new monitor is auto-kept in one of their scope groups.

is_alert_speed_drops
integer

Enable speed drop alerts (0=no, 1=yes)

alert_speed_threshold
integer

Speed alert threshold in seconds (1-30)

alert_speed_time
integer

Speed alert time window in minutes (20-60)

is_alert_vitals
integer

Master toggle for web-vitals budget alerts (0=no, 1=yes). Stored as 1 only while at least one budget below is > 0.

alert_lcp_ms
integer

LCP budget in ms (0 = recorded but not alerting; else 100-60000)

alert_fcp_ms
integer

FCP budget in ms (0 = recorded but not alerting; else 100-60000)

alert_ttfb_ms
integer

TTFB budget in ms (0 = recorded but not alerting; else 50-30000)

alert_cls_x1000
integer

CLS budget ×1000 (0 = recorded but not alerting; else 10-10000; 100 = CLS 0.10)

is_alert_dead_elements
integer

Alert when a page element keeps failing (0=no, 1=yes); detection itself always runs

dead_element_checks
integer

Consecutive failing checks before the dead-element alert fires (1-10)

dead_element_watch_types
string

Comma-separated element types to alert on, from: image,script,css,other

dead_element_ignore
string

Ignore globs, one per line — matching elements are recorded but never alert

report_up
integer

Send notification when monitor recovers (0=no, 1=yes)

branding_id
integer

Branding template ID for notifications. 0 (the default) uses the default theme; an id not owned by the account is refused with invalid_branding, and a non-numeric value with the same code.

confirmations_required
integer
Enum: 1 2 3

How many probes must independently observe the failure before it is acted on. Clamped into 1-3 (and clamped again by the manager), so an out-of-range value is silently corrected rather than refused. Defaults to 3 on create.

escalation_policy_id
integer

Escalation policy that routes this monitor's alerts. 0 (the default) alerts every recipient at once; a value above 0 must reference a policy owned by the account or the request is refused with invalid_escalation_policy.

notes
string

Free-text operator note stored on the monitor. Trimmed and truncated to 500 characters; a non-string value stores an empty string. Shown on the incident page and included in alert emails and webhook payloads.

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Responses

Request samples

Content type
application/json
{
  • "project_name": "My Website Speed",
  • "monitoring_interval_slider": 5,
  • "report_down_slider": 1,
  • "probes": "all",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "is_alert_speed_drops": 0,
  • "alert_speed_threshold": 5,
  • "alert_speed_time": 30,
  • "is_alert_vitals": 0,
  • "alert_lcp_ms": 2500,
  • "alert_fcp_ms": 0,
  • "alert_ttfb_ms": 800,
  • "alert_cls_x1000": 100,
  • "is_alert_dead_elements": 0,
  • "dead_element_checks": 3,
  • "dead_element_watch_types": "image,script,css",
  • "dead_element_ignore": "*/pixel/*.gif",
  • "report_up": 0,
  • "branding_id": 0,
  • "confirmations_required": 3,
  • "escalation_policy_id": 0,
  • "notes": "Checkout page — owned by the storefront team.",
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single speed monitor

Returns full details of a specific speed monitor including configuration, status, speed alert settings, and assigned contacts.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a speed monitor

Permanently deletes a speed monitor and its associated reporting configuration. Incident and log data may be retained.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing speed monitor

Updates an existing speed monitor. Only include fields you want to change — omitted fields retain their stored values. Two groups are touch-gated: the five web-vitals keys are only written when at least ONE of them is present (and the missing siblings are then backfilled from the stored config), and the four dead-element keys only when is_alert_dead_elements is present. Sending is_paused short-circuits the whole request: the pause/resume is applied and every other field in the same body is ignored.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Request Body schema: application/json
is_paused
boolean

Pause (true) or resume (false) the monitor. When present and non-null, ONLY the pause/resume action is performed — every other field in the same body is silently ignored and the response is just {data:{id}}. An explicit null is not a pause instruction and falls through to the normal update.

url
string

URL to monitor page speed for.

project_name
string

Monitor display name. It must stay unique within the account, otherwise the request is refused with already_exists.

monitoring_interval_slider
integer

Monitoring interval slider value: 0-60 (minutes; 0 = every 30 seconds) or a period code 61-65 (2h, 3h, 6h, 12h, 24h). Out of range is refused with monitoring_interval_invalid. Omit it to preserve the stored interval in seconds.

report_down_slider
integer

Report-down delay slider value: 0-60 minutes to wait before an outage is reported (0 = report as soon as it is confirmed). Out of range is refused with report_down_invalid.

probes
string

Monitoring locations: "all", or a comma-separated list of probe ids. An explicit list must name at least 6 probes, otherwise too_few_locations. Omitted, the stored selection is preserved rather than widened back to "all".

contacts
Array of integers

Alert recipient ids. Omitting the key leaves the stored recipients alone (the manager receives a "no_changes" sentinel); sending an empty list is refused with no_contacts_provided, because a monitor that can alert nobody is not worth running.

groups
Array of integers

Monitor-group ids. Every id must belong to the account (invalid_groups otherwise). A scoped operator's list is rewritten so the monitor always stays in at least one of their scope groups.

is_alert_speed_drops
integer

Enable speed-drop alerts (0=no, 1=yes). The threshold/window ranges below are only enforced while this is 1.

alert_speed_threshold
integer

Speed alert threshold in seconds (1-30); alert_speed_threshold_invalid otherwise.

alert_speed_time
integer

Speed alert evaluation window in minutes (20-60); alert_speed_time_invalid otherwise. The window must also fit at least 10 checks at the configured interval, or not_enough_checks_for_speed_alert.

is_alert_vitals
integer

Master toggle for web-vitals budget alerts (0=no, 1=yes). Part of the touch-gated vitals group: send any one of the five vitals keys and all five are written, the ones you omit backfilled from the stored config.

alert_lcp_ms
integer

LCP budget in ms. 0 records the metric without alerting; any other value must be 100-60000 or the request is refused with invalid_vitals_budget.

alert_fcp_ms
integer

FCP budget in ms. 0 records the metric without alerting; any other value must be 100-60000 (invalid_vitals_budget).

alert_ttfb_ms
integer

TTFB budget in ms. 0 records the metric without alerting; any other value must be 50-30000 (invalid_vitals_budget).

alert_cls_x1000
integer

CLS budget multiplied by 1000 (100 = a CLS of 0.10). 0 records the metric without alerting; any other value must be 10-10000 (invalid_vitals_budget).

is_alert_dead_elements
integer

Alert when a page element keeps failing (0=no, 1=yes); detection itself always runs. This key is the gate for the whole dead-element group — the three fields below are only written when it is present.

dead_element_checks
integer

Consecutive failing checks before the dead-element alert fires (1-10); invalid_dead_element_checks otherwise. Only read when is_alert_dead_elements is also present.

dead_element_watch_types
string

Comma-separated element types to alert on, from image, script, css and other. Only read when is_alert_dead_elements is also present.

dead_element_ignore
string

Ignore globs, one per line — matching elements are recorded but never alert. Only read when is_alert_dead_elements is also present.

report_up
integer

Send notification when monitor recovers (0=no, 1=yes).

branding_id
integer

Branding template used for this monitor's alert emails and reports. 0 uses the default theme; an id not owned by the account (or a non-numeric value) is refused with invalid_branding.

confirmations_required
integer
Enum: 1 2 3

How many probes must independently observe the failure before it is acted on. Clamped into 1-3 rather than refused. Omitted, the stored value is preserved.

escalation_policy_id
integer

Escalation policy that routes this monitor's alerts. 0 detaches (alert every recipient at once); a value above 0 must reference a policy owned by the account or the request is refused with invalid_escalation_policy. Absent preserves the stored binding; an explicit null detaches.

notes
string

Free-text operator note. Trimmed and truncated to 500 characters; a non-string value stores an empty string.

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Responses

Request samples

Content type
application/json
{
  • "is_paused": false,
  • "project_name": "My Website Speed",
  • "monitoring_interval_slider": 5,
  • "report_down_slider": 1,
  • "probes": "all",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "is_alert_speed_drops": 0,
  • "alert_speed_threshold": 5,
  • "alert_speed_time": 30,
  • "is_alert_vitals": 0,
  • "alert_lcp_ms": 2500,
  • "alert_fcp_ms": 0,
  • "alert_ttfb_ms": 800,
  • "alert_cls_x1000": 100,
  • "is_alert_dead_elements": 0,
  • "dead_element_checks": 3,
  • "dead_element_watch_types": "image,script,css",
  • "dead_element_ignore": "*/pixel/*.gif",
  • "report_up": 0,
  • "branding_id": 0,
  • "confirmations_required": 3,
  • "escalation_policy_id": 0,
  • "notes": "Checkout page — owned by the storefront team.",
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for a speed monitor

Returns a list of incidents for the specified speed monitor within the given date range. Defaults to the last 30 days.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of incidents to return

offset
integer

Number of incidents to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single speed incident

Returns the full detail of a specific incident for the given speed monitor, including the parsed error list, the probe servers that detected the incident, the captured response headers/body, traceroute and screenshot.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a speed incident

Permanently deletes a specific speed incident and its associated status page threads. The incident must belong to the monitor in the path; otherwise 404 incident_not_found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

List speed monitoring logs

Returns monitoring check logs for the specified speed monitor, newest first. Defaults to the last 14 days and a page size of 10; use limit/offset to page through the window. date_start is raised to the account plan's history retention floor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 14 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Page size (default 10, capped at 500)

offset
integer

Number of log entries to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single speed monitoring log entry

Returns full details of a specific speed monitoring check log. The row is addressed by its unix-second time, which is the same value GET /api/v2/speed/{id}/logs returns as each entry's id. Timestamps render in the account timezone.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

logId
required
integer\d+
Example: 1756000000

Log entry ID — the check's unix-second time, the same value the list endpoint returns as id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get timeline segments for a speed monitor

Returns up, down, trouble, maintenance, paused and unknown timeline segments for the speed monitor over the requested date range, suitable for rendering an availability timeline strip. date_start is raised to the account plan's history retention floor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 7 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get speed load time chart data

Returns load time and downtime chart data for the specified speed monitor, including per-point probe location. Data is cached for 60 seconds.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 24 hours ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get speed monitor averages

Returns aggregated average metrics for the specified speed monitor within the given date range: load time, requests, size, own domain time, and number of hosts.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get web-vitals & breakdown chart data

Consolidated per-check history for the speed detail page: median-bucketed series for full page load, lab web vitals (TTFB/FCP/LCP/CLS), own-vs-third-party time, requests, hosts and per-type transfer sizes; plus range summary, the latest check per location, the configured budgets, and the locations present in the range. Vitals are lab values measured in the same Chrome run as the load time; checks from probes that do not record vitals yet are excluded from the vitals series (never zero-filled).

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start as Unix timestamp (defaults to 24 hours ago)

date_end
integer

End as Unix timestamp (defaults to now)

location
string
Example: location=all

Probe server ID to filter to, or 'all' (default) for the cross-location median

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get dead/broken elements

Returns the dead-element report for the monitored page: every failing asset seen in the range with its type, sighting streaks, status and probe locations, plus a bucketed sightings series, the ignore-list hit count and the monitor alert config.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "report": {
    }
}

Get PageSpeed/Lighthouse scores

Returns the latest Lighthouse/PageSpeed analysis for the monitored page, including score, host count, resource count, page size, and detailed insights.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get component breakdown

Returns the time (seconds), average size, and request count broken down by component type (script, HTML, CSS, image, text, redirect) for the specified date range.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Transaction Monitors

Multi-step browser transaction monitoring.

List all transaction monitors

Returns a list of all transaction monitors for the authenticated account. Supports filtering by monitor status.

Authorizations:
bearerAuth
query Parameters
show_is_up
boolean
Default: true

Include monitors that are up

show_is_critical
boolean
Default: true

Include monitors with critical incidents

show_is_trouble
boolean
Default: true

Include monitors with trouble incidents

show_is_suspended
boolean
Default: true

Include suspended monitors

show_is_paused
boolean
Default: true

Include paused monitors

show_is_maintenance
boolean
Default: true

Include monitors in maintenance

limit
integer
Example: limit=25

Maximum number of monitors to return (0 = no limit)

offset
integer
Example: offset=0

Number of monitors to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new transaction monitor

Creates a new transaction monitor with its step definitions — the user journey a probe replays on every check. Speed and Transaction share ONE "Advanced" plan pool, so creation is refused with 403 plan_exceeded once that pool is full; the check runs before anything is written. At least one step is required, and the FIRST step (the one numbered 1) must carry a usable URL in element_value_1 — that value is what the blacklist and URL validation are run against.

Authorizations:
bearerAuth
Request Body schema: application/json
project_name
required
string

Monitor display name. Required — an empty value is refused with no_project_name, and a name another transaction monitor on the account already uses with already_exists.

monitoring_interval_slider
integer

Monitoring interval slider value in minutes. Defaults to 5. Unlike the speed family this is NOT range-validated at the API edge, and the resolved interval is then floored at 600 seconds — a transaction monitor cannot run more often than every 10 minutes, so anything shorter is snapped up rather than refused.

report_down_slider
integer

Report-down delay slider value — minutes to wait before an outage is reported; 0 alerts as soon as the failure is confirmed. Defaults to 1. Not range-validated at the API edge.

contacts
required
Array of integers

Alert recipient ids. Required in practice: on create an omitted (or empty) list is refused with no_contacts_provided, because a monitor that can alert nobody is not worth running. Bare ids are normalized to individual contacts; every id must belong to the account.

groups
Array of integers

Monitor-group ids. Every id must belong to the account (invalid_groups otherwise). A scoped operator's new monitor is auto-kept in one of their scope groups, inside the editor rather than at the API edge.

report_up
integer

Send a notification when the monitor recovers (0=no, 1=yes). Defaults to 1 on create — the opposite of the speed family, which defaults to 0.

branding_id
integer

Branding template used for this monitor's alert emails and reports. 0 (the default) uses the default theme; an id not owned by the account, or a non-numeric value, is refused with invalid_branding.

string or Array of integers

Vantage selection: the literal string "all" (the default) or a list of probe ids. Transaction does NOT enforce the six-location minimum the uptime/ssl/speed families apply, so a shorter explicit list is accepted here.

confirmations_required
integer
Enum: 1 2 3

How many probes must independently observe the failure before it is acted on. Clamped into 1-3 (and clamped again by the save path), so an out-of-range value is silently corrected rather than refused. Defaults to 3 on create.

escalation_policy_id
integer

Escalation policy that routes this monitor's alerts. 0 (the default) alerts every recipient at once; a value above 0 must reference a policy owned by the account or the request is refused with invalid_escalation_policy.

notes
string

Free-text operator note stored on the monitor. Trimmed and truncated to 500 characters; a non-string value stores an empty string. Shown on the incident page and included in alert emails and webhook payloads.

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

required
Array of objects

The journey to replay, at least one step. Each entry is keyed by its own number, and the FIRST entry in the array must be the one numbered 1 carrying the opening URL — the validator reads that step's element_value_1 and refuses the request with invalid_url when it is empty or blacklisted. Send the steps in order.

Responses

Request samples

Content type
application/json
{
  • "project_name": "Checkout journey",
  • "monitoring_interval_slider": 10,
  • "report_down_slider": 1,
  • "contacts": [
    ],
  • "groups": [
    ],
  • "report_up": 1,
  • "branding_id": 0,
  • "probes": "all",
  • "confirmations_required": 3,
  • "escalation_policy_id": 0,
  • "notes": "Runs against the staging card processor.",
  • "location_profile": "builtin:europe",
  • "steps": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single transaction monitor

Returns full details of a specific transaction monitor: configuration, alert recipients, group memberships, the applied Location Profile and the ordered step definitions. This is the editor's load path, so the stored selectors are cleaned for display — a legacy ":(N)" token is rewritten to ":nth-child(N)" and ":(0)" is dropped — which means a selector read here can differ from the exact bytes stored.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a transaction monitor

Permanently deletes a transaction monitor and its associated steps and reporting configuration.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update a transaction monitor

Updates an existing transaction monitor. Only include fields you want to change — omitted fields, and the whole step list, retain their stored values. steps is a FULL REPLACE when present: the step table is rewritten from what you send, so a partial list deletes the steps you left out. Pause/resume rides along instead of short-circuiting: is_paused is lifted out of the payload and applied AFTER the rest of the update succeeds, so a rejected save leaves the paused state untouched; sending is_paused alone answers with the bare id.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Request Body schema: application/json
is_paused
boolean

true pauses the monitor, false resumes it. Applied only after the rest of the update has been saved, so a validation failure never commits the pause. An explicit null is not a pause instruction. When it is the ONLY key in the body the response is just {data:{id}}; the write is read back, and a pause that did not land answers 400 monitor_not_updated.

project_name
string

Monitor display name. Must stay non-empty (no_project_name) and unique within the account (already_exists).

monitoring_interval_slider
integer

Monitoring interval slider value in minutes. Not range-validated at the API edge, and the resolved interval is floored at 600 seconds — a transaction monitor cannot run more often than every 10 minutes. Omit it to preserve the stored interval in seconds.

report_down_slider
integer

Report-down delay slider value — minutes to wait before an outage is reported; 0 alerts as soon as the failure is confirmed. Omit it to preserve the stored delay in seconds.

contacts
Array of integers

Alert recipient ids. Omitting the key preserves the stored recipients — the editor rewrites the join tables unconditionally, so this family re-sends the current list rather than passing a sentinel. Sending an empty list is refused with no_contacts_provided.

groups
Array of integers

Monitor-group ids. Every id must belong to the account (invalid_groups otherwise). Omitting the key preserves the stored memberships. A scoped operator's list is rewritten inside the editor so the monitor always stays in at least one of their scope groups.

report_up
integer

Send a notification when the monitor recovers (0=no, 1=yes).

branding_id
integer

Branding template used for this monitor's alert emails and reports. 0 uses the default theme; an id not owned by the account, or a non-numeric value, is refused with invalid_branding.

string or Array of integers

Vantage selection: "all" or a list of probe ids. Omitted, the stored selection is preserved rather than widened back to "all". Transaction does NOT enforce the six-location minimum the uptime/ssl/speed families apply.

confirmations_required
integer
Enum: 1 2 3

How many probes must independently observe the failure before it is acted on. Clamped into 1-3 rather than refused. Omitted, the stored value is preserved.

escalation_policy_id
integer

Escalation policy that routes this monitor's alerts. 0 detaches (alert every recipient at once); a value above 0 must reference a policy owned by the account or the request is refused with invalid_escalation_policy. Absent preserves the stored binding; an explicit null detaches.

notes
string

Free-text operator note. Trimmed and truncated to 500 characters; a non-string value stores an empty string.

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Array of objects

FULL REPLACE of the journey — send every step you want to keep, in order. Omit the key entirely to preserve the stored steps. The first entry must be the one numbered 1 carrying the opening URL, which is what invalid_url is judged against.

Responses

Request samples

Content type
application/json
{
  • "is_paused": false,
  • "project_name": "Checkout journey",
  • "monitoring_interval_slider": 10,
  • "report_down_slider": 1,
  • "contacts": [
    ],
  • "groups": [
    ],
  • "report_up": 1,
  • "branding_id": 0,
  • "probes": "all",
  • "confirmations_required": 3,
  • "escalation_policy_id": 0,
  • "notes": "Runs against the staging card processor.",
  • "location_profile": "builtin:europe",
  • "steps": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for a transaction monitor

Returns a list of incidents for the specified transaction monitor within the given date range. Defaults to the last 30 days.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of incidents to return

offset
integer

Number of incidents to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get incident detail with step breakdown

Returns details of a specific transaction incident, including a per-step breakdown with durations, action names and screenshot URLs. The incident must belong to the monitor in the path. The step breakdown is only assembled while the run is within the one-week step-retention window and its log rows still exist; outside that the steps array comes back empty while the rest of the incident is still reported. Timestamps render in the account timezone.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a transaction incident

Permanently deletes one CLOSED incident of the specified monitor. The currently open incident cannot be deleted.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

List monitoring logs for a transaction monitor

Returns recent monitoring check logs for the specified transaction monitor within the given date range, limited to 20 entries. Defaults to the last 14 days when no range is supplied.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 14 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of log entries to return

offset
integer

Number of log entries to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single transaction monitoring log entry

Returns full details of a specific transaction monitoring check log — the run summary, not the per-step breakdown (use GET /api/v2/transaction/{id}/last-run or the incident detail endpoint for steps). A transaction result is keyed by monitor + unix-second time, and that time is both the {logId} you address here and the id the list endpoint returns, so the two round-trip. Timestamps render in the account timezone.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

logId
required
integer\d+
Example: 1756000000

Log entry ID — the run's unix-second time, the same value the list endpoint returns as id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get the last run of a transaction monitor

Returns the most recent transaction run with its overall status, total duration and per-step breakdown (step number, action name, attribute, duration, status and a screenshot URL when one was captured). data is null when the monitor has never run, and also when the run exists but its per-step log rows or the monitor's step definitions could not be read — the two cases are indistinguishable from the response. Unlike the incident breakdown, only the LAST step of a failed run is marked error; every earlier step is labelled success because it was logged, not because it was verified.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get timeline segments for a transaction monitor

Returns up, down, trouble, maintenance, paused and unknown timeline segments for the transaction monitor over the requested date range, suitable for rendering an availability timeline strip. Unlike the speed family this endpoint does NOT clamp date_start to the plan's history retention floor, so an older window is answered as asked.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 7 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get stacked step chart data

Returns step-by-step timing data for building a stacked chart of transaction execution durations. In addition to the fixed fields, the response contains one dynamic series per step ("step_1", "step_2", ... up to "step_N" where N is max_steps); each step_N is an array of that step's duration in seconds for each data point (0 when the step did not run). Returns an empty object when there is no data in the range.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 24 hours ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get availability percentages for a transaction monitor

Calculates uptime and downtime percentages for the specified transaction monitor within the given date range. Defaults to the last 24 hours.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 24 hours ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get step definitions for a transaction monitor

Returns just the configured step definitions for the specified transaction monitor — the same steps array GET /api/v2/transaction/{id} embeds, without the rest of the record. Like that endpoint it is an editor load path, so a legacy ":(N)" selector token is rewritten to ":nth-child(N)" and ":(0)" is dropped, which means a selector read here can differ from the exact bytes stored. An empty array when the monitor has no steps.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Queue an immediate test run for a transaction monitor

Schedules the specified transaction monitor for an immediate check by setting its next check time to now. This is an asynchronous operation: the test is queued for a probe to pick up and does NOT run synchronously, so live step results and screenshots are not returned here. The response always reports a "queued" status, echoes the monitor ID, and lists the monitor's steps with a placeholder "queued" status (duration "0ms", no screenshot). Poll GET /api/v2/transaction/{id}/last-run afterwards to retrieve the actual run results.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Run tests for all transaction monitors

Queues every non-suspended transaction monitor on the account for an immediate check by setting its next check time to now. Asynchronous, like the per-monitor variant: nothing runs synchronously and no results are returned — poll GET /api/v2/transaction/{id}/last-run for each monitor afterwards. Suspended monitors are skipped and are not counted. The endpoint reads no request body.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Security Monitors

Malware, software version, TLS, security header and email authentication checks of your sites.

List domain verifications

Returns the account's domain ownership verifications with the DNS record and file each one expects.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Start a domain verification

Creates a pending verification for the domain and returns its token, the TXT record to publish and the file to serve. Prove ownership with either one, then call POST /api/v2/security/verifications/{id}/check. A verification covers the domain and all its subdomains. When the account already has a verification for the domain, that one is returned (200) with its existing token.

Authorizations:
bearerAuth
Request Body schema: application/json
domain
required
string

Domain or host to verify. A pasted URL is reduced to its host; internationalised names are stored in their ASCII (punycode) form.

Responses

Request samples

Content type
application/json
{
  • "domain": "example.com"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Check a domain verification now

Looks for the TXT record, then fetches the verification file (https first, then http; redirects only within the same host), and stores the result. Either proof verifies the domain. A failed check leaves a pending verification pending; on a verified domain it counts toward the 3 failed checks in a row that mark it lost.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Verification ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    },
  • "checked": {
    }
}

Delete a domain verification

Removes the verification. Monitors on the domain lose the owner-only checks.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Verification ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

List all security monitors

Returns a paginated list of all security monitors for the authenticated account. Supports filtering by monitor status.

Authorizations:
bearerAuth
query Parameters
limit
integer
Example: limit=25

Maximum number of monitors to return (0 = no limit)

offset
integer
Example: offset=0

Number of monitors to skip

show_is_up
boolean
Default: true

Include monitors that are up

show_is_critical
boolean
Default: true

Include monitors with critical incidents

show_is_trouble
boolean
Default: true

Include monitors with trouble incidents

show_is_suspended
boolean
Default: true

Include suspended monitors

show_is_paused
boolean
Default: true

Include paused monitors

show_is_maintenance
boolean
Default: true

Include monitors in maintenance

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new security monitor

Creates a new security monitor for the specified URL. Each scan checks the URL with Google Web Risk and runs the enabled check groups (see security_checks).

Authorizations:
bearerAuth
Request Body schema: application/json
url
required
string

URL to monitor for malware and security issues

project_name
string

Monitor display name

monitoring_interval_slider
integer

Monitoring interval slider value (determines check frequency, minimum 3600s)

report_down_slider
integer

Report down delay slider value

contacts
Array of integers

Contact IDs to notify on incidents

groups
Array of integers

Group IDs to assign the monitor to

report_up
integer

Send notification when monitor recovers (0=no, 1=yes)

branding_id
integer

Branding template ID for notifications

security_checks
Array of strings
Items Enum: "software" "headers" "tls" "email" "page" "dns" "mail" "mta_sts"

Check groups to run besides the malware check, which always runs (malware in the list is ignored, and so is the retired key certs). Default: all eight. Any other key is rejected with invalid_security_checks.

security_alert_level
string
Enum: "critical" "high"

Lowest finding severity that opens an incident and alerts. Default critical.

Responses

Request samples

Content type
application/json
{
  • "project_name": "My Website Security",
  • "monitoring_interval_slider": 5,
  • "report_down_slider": 1,
  • "contacts": [
    ],
  • "groups": [
    ],
  • "report_up": 1,
  • "branding_id": 0,
  • "security_checks": [
    ],
  • "security_alert_level": "critical"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single security monitor

Returns full details of a specific security monitor including configuration, status, and assigned contacts.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a security monitor

Permanently deletes a security monitor and its associated reporting configuration. Incident and log data may be retained.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing security monitor

Updates an existing security monitor. Only include fields you want to change. Omitted fields retain their current values.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Request Body schema: application/json
is_paused
boolean

Pause (true) or resume (false) the monitor. May be sent alone or together with configuration fields — both are then applied, and the pause only after the rest of the payload has validated.

url
string

URL to monitor for malware and security issues

project_name
string

Monitor display name

monitoring_interval_slider
integer

Monitoring interval slider value

report_down_slider
integer

Report down delay slider value

contacts
Array of integers

Contact IDs to notify

groups
Array of integers

Group IDs

report_up
integer

Send notification when monitor recovers (0=no, 1=yes)

branding_id
integer

Branding template ID

security_checks
Array of strings
Items Enum: "software" "headers" "tls" "email" "page" "dns" "mail" "mta_sts"

Check groups to run besides the malware check (malware and the retired key certs are ignored). Replaces the stored list; omit to keep it. Any other key is rejected with invalid_security_checks.

security_alert_level
string
Enum: "critical" "high"

Lowest finding severity that opens an incident and alerts; omit to keep it.

Responses

Request samples

Content type
application/json
{
  • "is_paused": true,
  • "url": "string",
  • "project_name": "string",
  • "monitoring_interval_slider": 0,
  • "report_down_slider": 0,
  • "contacts": [
    ],
  • "groups": [
    ],
  • "report_up": 0,
  • "branding_id": 0,
  • "security_checks": [
    ],
  • "security_alert_level": "critical"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for a security monitor

Returns a list of security incidents for the specified security monitor within the given date range. The incident code is the highest-ranked open finding code, e.g. MALWARE, SOCIAL_ENGINEERING, UNWANTED_SOFTWARE, EOL_SOFTWARE or TLS_LEGACY. Defaults to the last 30 days.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of incidents to return

offset
integer

Number of incidents to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single security incident

Returns the full detail of a specific security incident for the given security monitor. The malware check is one server-side Google Web Risk lookup, so the shared incident keys that describe a probe fan-out and its HTTP exchange (servers, response headers/body, traceroute, screenshot) are always empty for this family.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a security incident

Permanently deletes a specific CLOSED security incident and its associated status page threads. The incident must belong to the monitor in the path; otherwise 404 incident_not_found. The monitor's currently open incident cannot be deleted (409).

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

List security scan logs

Returns security scan check logs for the specified monitor, newest first. Defaults to the last 90 days; use limit/offset to page through the window. date_start is raised to the account plan's history retention floor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 90 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of log entries to return

offset
integer

Number of log entries to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single security scan log entry

Returns full details of a specific security scan check log.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

logId
required
integer\d+

Log entry ID

Responses

Mark a finding as expected

Closes an open finding and keeps it out of counts and alerts on this monitor until undone. The same code and subject stays accepted across scans; another subject is a new finding, and a report at a higher severity brings it back. Malware findings cannot be accepted.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

findingId
required
integer\d+

Open finding ID

Responses

Response samples

Content type
application/json
{
  • "status": "success",
  • "data": { }
}

Undo a finding marked as expected

Removes the acceptance and reopens the finding it closed. For new script sources and new certificate issuers the next scan reports the value again.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

acceptedId
required
integer\d+

ID from accepted_findings

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Check now

Asks for a full scan on the next scan tick, usually within a minute: the Google Web Risk lookup, every switched-on check group and, when the monitor qualifies for them, the owner-only groups, whatever their usual once-a-day cadence or a Web Risk retry wait. It does NOT scan synchronously: poll GET /api/v2/virus/{id} and read manual_check.running, checks_state and findings. Groups that do not fit one tick continue in the next ones; running stays true until they have all run. The regular scan schedule does not move. Results go through the usual alerting: a fixed issue closes its incident and a new finding alerts. While a request is still running, another one answers 202 with that request and changes nothing, so a double click is harmless. Rate-limited to once per 5 minutes per monitor and 20 per hour per ACCOUNT. Refused outright for monitors the scanner skips anyway.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

Security monitor id.

Responses

Response samples

Content type
application/json
{
  • "status": "success",
  • "data": {
    }
}

Get timeline segments for a security monitor

Returns up, down, maintenance and unknown timeline segments for the security monitor over the requested date range, suitable for rendering an availability timeline strip.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 7 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

RUM Monitors

Real User Monitoring — passive, in-browser performance beacon.

List all RUM monitors

Returns a paginated list of all RUM monitors for the authenticated account. Supports filtering by monitor status.

Authorizations:
bearerAuth
query Parameters
limit
integer
Example: limit=25

Maximum number of monitors to return (0 = no limit)

offset
integer
Example: offset=0

Number of monitors to skip

show_is_up
boolean
Default: true

Include monitors that are up

show_is_critical
boolean
Default: true

Include monitors with critical incidents

show_is_trouble
boolean
Default: true

Include monitors with trouble incidents

show_is_suspended
boolean
Default: true

Include suspended monitors

show_is_paused
boolean
Default: true

Include paused monitors

show_is_maintenance
boolean
Default: true

Include monitors in maintenance

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new RUM monitor

Creates a new Real User Monitoring site with the specified configuration.

Authorizations:
bearerAuth
Request Body schema: application/json
url
required
string

URL of the website to monitor

project_name
required
string

Monitor display name

apdex_score
integer

Apdex threshold in seconds (1-20, default 4)

is_alert_traffic_stops
integer

Enable traffic stop alerts (0=no, 1=yes)

alert_traffic_stops_minutes
integer

Minutes without traffic before alerting

is_alert_speed_drops
integer

Enable speed drop alerts (0=no, 1=yes)

alert_speed_drops_percent
integer

Speed drop percentage threshold

alert_speed_drops_time
integer

Minutes of sustained speed drop before alerting

is_alert_traffic_drops
integer

Enable traffic drop alerts (0=no, 1=yes)

alert_traffic_drops_percent
integer

Traffic drop percentage threshold

alert_traffic_drops_time
integer

Minutes of sustained traffic drop before alerting

is_alert_js_errors
integer

Enable JS error alerts (0=no, 1=yes)

alert_js_errors_percent
integer

JS error percentage threshold

alert_js_errors_time
integer

Minutes of sustained JS errors before alerting

contacts
Array of integers

Contact IDs to notify on incidents

integer or Array of integers

Group assignment: a single group ID or an array of group IDs.

branding_id
integer

Branding template ID

Responses

Request samples

Content type
application/json
{
  • "project_name": "My Website",
  • "apdex_score": 4,
  • "is_alert_traffic_stops": 0,
  • "alert_traffic_stops_minutes": 30,
  • "is_alert_speed_drops": 0,
  • "alert_speed_drops_percent": 50,
  • "alert_speed_drops_time": 30,
  • "is_alert_traffic_drops": 0,
  • "alert_traffic_drops_percent": 50,
  • "alert_traffic_drops_time": 30,
  • "is_alert_js_errors": 0,
  • "alert_js_errors_percent": 10,
  • "alert_js_errors_time": 30,
  • "contacts": [
    ],
  • "groups": 0,
  • "branding_id": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single RUM monitor

Returns full details of a specific RUM monitor including configuration, tracking code, alert settings, and assigned contacts.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a RUM monitor

Permanently deletes a RUM monitor and its associated configuration. Incident and log data may be retained.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing RUM monitor

Updates an existing RUM monitor. Only include fields you want to change. Omitted fields retain their current values.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Request Body schema: application/json
url
string

URL of the website to monitor

project_name
string

Monitor display name

apdex_score
integer

Apdex threshold in seconds (1-20)

is_alert_traffic_stops
integer

Enable traffic stop alerts (0=no, 1=yes)

alert_traffic_stops_minutes
integer

Minutes without traffic before alerting

is_alert_speed_drops
integer

Enable speed drop alerts (0=no, 1=yes)

alert_speed_drops_percent
integer

Speed drop percentage threshold

alert_speed_drops_time
integer

Minutes of sustained speed drop before alerting

is_alert_traffic_drops
integer

Enable traffic drop alerts (0=no, 1=yes)

alert_traffic_drops_percent
integer

Traffic drop percentage threshold

alert_traffic_drops_time
integer

Minutes of sustained traffic drop before alerting

is_alert_js_errors
integer

Enable JS error alerts (0=no, 1=yes)

alert_js_errors_percent
integer

JS error percentage threshold

alert_js_errors_time
integer

Minutes of sustained JS errors before alerting

contacts
Array of integers

Contact IDs to notify

is_paused
boolean

Pause (true) or resume (false) the monitor. When present, only the pause/resume action is performed and other fields are ignored.

integer or Array of integers

Group assignment: a single group ID or an array of group IDs.

branding_id
integer

Branding template ID

Responses

Request samples

Content type
application/json
{
  • "url": "string",
  • "project_name": "string",
  • "apdex_score": 0,
  • "is_alert_traffic_stops": 0,
  • "alert_traffic_stops_minutes": 0,
  • "is_alert_speed_drops": 0,
  • "alert_speed_drops_percent": 0,
  • "alert_speed_drops_time": 0,
  • "is_alert_traffic_drops": 0,
  • "alert_traffic_drops_percent": 0,
  • "alert_traffic_drops_time": 0,
  • "is_alert_js_errors": 0,
  • "alert_js_errors_percent": 0,
  • "alert_js_errors_time": 0,
  • "contacts": [
    ],
  • "is_paused": true,
  • "groups": 0,
  • "branding_id": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for a RUM monitor

Returns a list of incidents for the specified RUM monitor within the given date range. Defaults to the last 30 days. Incidents that overlap the range (including ongoing incidents that started before it) are included, and the result set is paginated with the limit/offset parameters.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of incidents to return

offset
integer

Number of incidents to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get a single RUM incident

Returns full details of a specific RUM incident.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Delete a RUM incident

Permanently deletes a specific RUM incident and its associated status page threads. The incident must belong to the monitor in the path; otherwise 404 incident_not_found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

incidentId
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Verify tracking script installation

Checks whether the RUM tracking script has been correctly installed on the monitored website by fetching the page and searching for the script hash.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get RUM summary analytics

Returns summary analytics for a RUM monitor: average load time, pageviews, JS errors, and user satisfaction breakdown.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
string <date>

Start date (YYYY-MM-DD), defaults to 30 days ago

date_end
string <date>

End date (YYYY-MM-DD), defaults to today

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get per-page performance breakdown

Returns per-page performance data including pageviews and average load time for each tracked URL.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
string <date>

Start date (YYYY-MM-DD), defaults to 30 days ago

date_end
string <date>

End date (YYYY-MM-DD), defaults to today

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Get JavaScript error analytics

Returns JavaScript error data including totals, error breakdown by name and by script.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
string <date>

Start date (YYYY-MM-DD), defaults to 30 days ago

date_end
string <date>

End date (YYYY-MM-DD), defaults to today

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get geographic distribution

Returns visitor distribution by country with load counts and average load times.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
string <date>

Start date (YYYY-MM-DD), defaults to 30 days ago

date_end
string <date>

End date (YYYY-MM-DD), defaults to today

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Get browser distribution

Returns visitor distribution by browser with share percentage and load counts.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
string <date>

Start date (YYYY-MM-DD), defaults to 30 days ago

date_end
string <date>

End date (YYYY-MM-DD), defaults to today

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Get device type distribution

Returns visitor distribution by device type (Desktop, Mobile, Tablet) with share percentage and load counts.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
string <date>

Start date (YYYY-MM-DD), defaults to 30 days ago

date_end
string <date>

End date (YYYY-MM-DD), defaults to today

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Get operating system distribution

Returns visitor distribution by operating system with share percentage and load counts.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
string <date>

Start date (YYYY-MM-DD), defaults to 30 days ago

date_end
string <date>

End date (YYYY-MM-DD), defaults to today

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Get tracking JavaScript snippet

Returns the JavaScript tracking code snippet that should be embedded in the monitored website to collect Real User Monitoring data.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

List alert logs for a RUM monitor

Returns recent alert/incident logs for the specified RUM monitor. RUM monitors collect client-side data, so logs reflect alert events rather than server-side checks.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 30 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

limit
integer

Maximum number of log entries to return

offset
integer

Number of log entries to skip

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get timeline segments for a RUM monitor

Returns up, down, maintenance and unknown timeline segments for the RUM monitor over the requested date range, suitable for rendering an availability timeline strip.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Monitor ID

query Parameters
date_start
integer

Start date as Unix timestamp (defaults to 7 days ago)

date_end
integer

End date as Unix timestamp (defaults to now)

Responses

API Monitors

Multi-step HTTP/REST API chains with per-step assertions and variables.

List all API monitors

Returns every API monitor of the authenticated account, sorted by name ascending, with the derived status decorations the monitor list renders from: is_up (0 while a critical or trouble state is open), is_paused, is_maintenance and steps_count. The list is not paginated — metadata.total is simply the number of rows in data. A monitor-group-scoped operator only ever sees monitors inside their scope groups, so total is what that actor may see rather than the account total. The list row deliberately omits the variables blob and the last_run payload: only GET /{id} returns those, and even there secret values are masked.

Authorizations:
bearerAuth
query Parameters
search
string
Example: search=checkout

Case-insensitive substring match on the monitor name. LIKE wildcards (% and _) inside the term are escaped and matched literally.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create an API monitor

Creates a multi-step API monitor. The plan pool is checked first (403 plan_exceeded), then ownership of the escalation policy, groups, branding template and contacts (400), then the manager validates the name, the variables, the whole step chain and the probe selection before writing the list row and the steps in one transaction — so a 422 leaves nothing behind. Steps are re-numbered 1..N on save, so a client-sent step number is ignored. Omitting contacts entirely seeds every contact on the account; sending an explicitly empty list is refused one gate earlier, as a 400 invalid_contacts rather than a 422. The check cadence can be given as monitoring_interval_slider, monitoring_interval or report_interval (that precedence); whichever is used the result is clamped to the account plan floor and never goes below 60 seconds, because the sweep runs per minute.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Monitor name, trimmed. Required, at most 190 characters, and unique within the account.

required
Array of objects

The ordered HTTP chain: at least 1 step and at most 15. Numbers are re-sequenced 1..N on save.

Array of objects

Monitor-level variables available to every step as {{name}}. At most 30.

string or Array of integers

Probe selection. "all" (the default), null, "" or [] mean every capable probe; an explicit array of location IDs must carry at least 6 distinct entries.

contacts
Array of integers

Alert recipients: bare contact IDs, or {id, is_team, is_user, is_operator, is_individual_contact} objects. Every ID must belong to the account. Omit the key (or send null) to auto-seed every contact on the account; an explicitly empty list is rejected with 400 invalid_contacts ("No contacts provided") before anything is written.

groups
Array of integers

Monitor group IDs (a single bare integer is also accepted); every ID must belong to the account. For a group-scoped editor the list is rewritten so the new monitor always lands inside their scope.

branding_id
integer

Branding template used for alert emails and status pages. 0 (default) = the default theme; a non-zero ID must belong to the account.

escalation_policy_id
integer

Escalation policy that governs alert routing. 0 (default) = notify all recipients at once; a non-zero ID must belong to the account.

notes
string

Free-text operator note (plain text), trimmed and capped at 500 characters. Shown on the incident page and included in alert emails and webhook payloads.

confirmations_required
integer

How many independent probe confirmations must agree before a failure opens an incident. Clamped to 1-3; defaults to 3.

report_up
integer

Send the recovery (UP) alert. 0 disables it; any other value — and an absent key — means 1.

report_down
integer

Delay in SECONDS between the confirmed failure and the DOWN alert. Negative values are floored to 0. Default 0 (alert immediately). Ignored when report_down_slider is present.

report_down_slider
integer

The same delay expressed in MINUTES (what the editor slider sends); converted to seconds and taking precedence over report_down.

monitoring_interval_slider
integer

Check cadence as the shared editor slider code (1 = 60s, 5 = 300s, 61 = 2h, 65 = 24h, 71+ = whole days), clamped to the account plan floor. Highest-precedence interval key.

monitoring_interval
integer

Check cadence in raw seconds, clamped up to the account plan floor. Used when monitoring_interval_slider is absent.

report_interval
integer

Check cadence in seconds under the name GET returns it as, so a GET → edit → PUT round-trip works. Lowest-precedence interval key; the resolved value is floored to 60 seconds and defaults to 300.

(string or null) or (integer or null)

Canonical ref of the Location Profile to record against this monitor: a built-in's synthetic id ("builtin:", e.g. "builtin:europe") or an owned profile's numeric id, as a string or an int. null, "" and any ref that is neither a known built-in nor a profile owned by this account are all stored as NO binding rather than rejected. This is purely a binding record for the editor's Locations tab — it does not itself rewrite probes, so send probes as well to change where the monitor runs.

Responses

Request samples

Content type
application/json
{
  • "name": "Checkout API",
  • "steps": [
    ],
  • "variables": [
    ],
  • "probes": "all",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "branding_id": 0,
  • "escalation_policy_id": 0,
  • "notes": "",
  • "confirmations_required": 3,
  • "report_up": 1,
  • "report_down": 0,
  • "report_down_slider": 0,
  • "monitoring_interval_slider": 5,
  • "monitoring_interval": 300,
  • "report_interval": 300,
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get an API monitor

Returns the full editable detail of one monitor: every list-row field plus the decoded step chain, the variable list, the last run blob, the probe/location selection, the alert contacts, the group memberships and the applied Location Profile. This is the round-trip shape — what you read here can be edited and sent straight back to PATCH /{id}. Secrets are write-only: a variable marked secret comes back with value "" and has_value true, and any literal occurrence of a secret value inside a step URL, header or body is rewritten to its {{name}} placeholder before it leaves the API. An out-of-scope monitor is indistinguishable from a non-existent one, so a group-scoped actor cannot probe for foreign IDs.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update an API monitor

Alias of PATCH /{id}, kept for client compatibility — the route declares both verbs and they resolve to the same handler, so the request contract, the response and the error set are identical and the semantics are a partial update either way. Omitted keys keep their stored values, sending steps or variables replaces that list wholesale, and a secret variable sent with an empty value keeps the stored secret. Sending is_paused short-circuits everything else and only pauses or resumes the monitor.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

Request Body schema: application/json
is_paused
boolean

Pause (truthy) or resume (falsy) the monitor. Present with any value other than a literal null this SHORT-CIRCUITS the whole update: no other field in the body is read, no validation runs, and the response is just {data:{id}}. Send it on its own.

name
string

New monitor name. Same rules as create — non-empty, at most 190 characters, unique within the account excluding this monitor. Absent keeps the stored name.

Array of objects

Full replacement of the step chain: the stored steps are deleted and re-inserted, re-numbered 1..N. Same per-step contract and limits as create (1-15 steps). Absent leaves the stored chain alone — but sending variables WITHOUT steps re-validates the stored chain against the new variable set, so removing a variable that a step still references fails with undefined_variable instead of silently breaking the monitor. Replacing the chain marks the definition changed, which clears the in-flight pull lease and drops any outstanding confirmation round.

Array of objects

Full replacement of the variable list, at most 30. Masked round-trip: an incoming variable whose value is "" and whose name matches a STORED SECRET keeps the stored value, whatever the incoming secret flag — so an untouched secret can be re-saved, and un-secreted, without retyping it.

string or Array of integers

Replacement probe selection: "all", or at least 6 distinct location IDs. Absent keeps the stored selection. Changing it marks the definition changed.

contacts
Array of integers

Replacement recipient list: bare contact IDs, or {id, is_team, is_user, is_operator, is_individual_contact} objects. Every ID must belong to the account. A null value, the "no_changes" sentinel and an absent key all leave the stored list untouched; an explicitly empty array is NOT a way to clear the recipients — it is rejected with 400 invalid_contacts ("No contacts provided"), because a monitor with no recipients alerts nobody.

groups
Array of integers

Replacement group membership. An empty array DELETES all memberships; "no_changes" or an absent key leaves them alone. A group-scoped editor's write is confined to their scope groups, and owner-assigned memberships outside that scope are preserved.

branding_id
integer

Branding template ID; 0 = default theme, a non-zero ID must belong to the account. Absent keeps the stored value.

escalation_policy_id
integer

Escalation policy ID; 0 = notify all recipients at once, a non-zero ID must belong to the account. Absent keeps the stored value.

notes
string

Free-text operator note, trimmed and capped at 500 characters. An absent key preserves the stored value; an explicit empty string clears it.

confirmations_required
integer

Independent probe confirmations before an incident opens, clamped 1-3. Absent keeps the stored value.

report_up
integer

Send the recovery alert (0 = off, anything else = on). Absent keeps the stored value.

report_down
integer

DOWN-alert delay in SECONDS, floored at 0. Absent keeps the stored value.

report_down_slider
integer

DOWN-alert delay in MINUTES (the editor slider); converted to seconds and taking precedence over report_down.

monitoring_interval_slider
integer

Check cadence as the shared editor slider code, clamped to the account plan floor. Highest-precedence interval key.

monitoring_interval
integer

Check cadence in raw seconds, clamped to the account plan floor. Used when the slider key is absent.

report_interval
integer

Check cadence in seconds under the read-side name, so a GET → edit → PUT round-trip is honoured. Lowest precedence; the resolved value is floored to 60 seconds, and with no interval key at all the stored cadence is kept.

(string or null) or (integer or null)

Canonical ref of the applied Location Profile: a built-in's synthetic id ("builtin:") or an owned profile's numeric id. Only written when the key is explicitly present, so a rename or a single-field PATCH never clobbers an existing binding; sending null or an unrecognised ref clears the binding instead of erroring.

Responses

Request samples

Content type
application/json
{
  • "is_paused": true,
  • "name": "Checkout API",
  • "steps": [
    ],
  • "variables": [
    ],
  • "probes": "all",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "branding_id": 0,
  • "escalation_policy_id": 0,
  • "notes": "",
  • "confirmations_required": 3,
  • "report_up": 1,
  • "report_down": 0,
  • "report_down_slider": 0,
  • "monitoring_interval_slider": 5,
  • "monitoring_interval": 300,
  • "report_interval": 300,
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete an API monitor

Permanently deletes the monitor and cascades: the step chain, the legacy result rows, the reporting rows, every incident, the maintenance and pause audit rows, the Location Profile binding, the group memberships, the pull-queue and confirmation rows, and the ClickHouse per-run and per-step history. There is no soft delete and no undo — pause the monitor instead if you only want to stop checks. A monitor outside the caller's group scope answers 404 exactly like a non-existent one.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update an API monitor

True partial update: only the keys you send are written, everything else keeps its stored value. steps and variables are whole-list replacements rather than merges, and a secret variable sent with an empty value keeps the stored secret, so a GET → edit → PATCH round-trip never wipes credentials. Sending is_paused short-circuits the whole update — no other field is read, no validation runs, and the response is just {data:{id}}. Changing steps, variables or probes marks the definition changed, which clears the in-flight pull lease and drops any outstanding confirmation round.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

Request Body schema: application/json
is_paused
boolean

Pause (truthy) or resume (falsy) the monitor. Present with any value other than a literal null this SHORT-CIRCUITS the whole update: no other field in the body is read, no validation runs, and the response is just {data:{id}}. Send it on its own.

name
string

New monitor name. Same rules as create — non-empty, at most 190 characters, unique within the account excluding this monitor. Absent keeps the stored name.

Array of objects

Full replacement of the step chain: the stored steps are deleted and re-inserted, re-numbered 1..N. Same per-step contract and limits as create (1-15 steps). Absent leaves the stored chain alone — but sending variables WITHOUT steps re-validates the stored chain against the new variable set, so removing a variable that a step still references fails with undefined_variable instead of silently breaking the monitor. Replacing the chain marks the definition changed, which clears the in-flight pull lease and drops any outstanding confirmation round.

Array of objects

Full replacement of the variable list, at most 30. Masked round-trip: an incoming variable whose value is "" and whose name matches a STORED SECRET keeps the stored value, whatever the incoming secret flag — so an untouched secret can be re-saved, and un-secreted, without retyping it.

string or Array of integers

Replacement probe selection: "all", or at least 6 distinct location IDs. Absent keeps the stored selection. Changing it marks the definition changed.

contacts
Array of integers

Replacement recipient list: bare contact IDs, or {id, is_team, is_user, is_operator, is_individual_contact} objects. Every ID must belong to the account. A null value, the "no_changes" sentinel and an absent key all leave the stored list untouched; an explicitly empty array is NOT a way to clear the recipients — it is rejected with 400 invalid_contacts ("No contacts provided"), because a monitor with no recipients alerts nobody.

groups
Array of integers

Replacement group membership. An empty array DELETES all memberships; "no_changes" or an absent key leaves them alone. A group-scoped editor's write is confined to their scope groups, and owner-assigned memberships outside that scope are preserved.

branding_id
integer

Branding template ID; 0 = default theme, a non-zero ID must belong to the account. Absent keeps the stored value.

escalation_policy_id
integer

Escalation policy ID; 0 = notify all recipients at once, a non-zero ID must belong to the account. Absent keeps the stored value.

notes
string

Free-text operator note, trimmed and capped at 500 characters. An absent key preserves the stored value; an explicit empty string clears it.

confirmations_required
integer

Independent probe confirmations before an incident opens, clamped 1-3. Absent keeps the stored value.

report_up
integer

Send the recovery alert (0 = off, anything else = on). Absent keeps the stored value.

report_down
integer

DOWN-alert delay in SECONDS, floored at 0. Absent keeps the stored value.

report_down_slider
integer

DOWN-alert delay in MINUTES (the editor slider); converted to seconds and taking precedence over report_down.

monitoring_interval_slider
integer

Check cadence as the shared editor slider code, clamped to the account plan floor. Highest-precedence interval key.

monitoring_interval
integer

Check cadence in raw seconds, clamped to the account plan floor. Used when the slider key is absent.

report_interval
integer

Check cadence in seconds under the read-side name, so a GET → edit → PUT round-trip is honoured. Lowest precedence; the resolved value is floored to 60 seconds, and with no interval key at all the stored cadence is kept.

(string or null) or (integer or null)

Canonical ref of the applied Location Profile: a built-in's synthetic id ("builtin:") or an owned profile's numeric id. Only written when the key is explicitly present, so a rename or a single-field PATCH never clobbers an existing binding; sending null or an unrecognised ref clears the binding instead of erroring.

Responses

Request samples

Content type
application/json
{
  • "is_paused": true,
  • "name": "Checkout API",
  • "steps": [
    ],
  • "variables": [
    ],
  • "probes": "all",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "branding_id": 0,
  • "escalation_policy_id": 0,
  • "notes": "",
  • "confirmations_required": 3,
  • "report_up": 1,
  • "report_down": 0,
  • "report_down_slider": 0,
  • "monitoring_interval_slider": 5,
  • "monitoring_interval": 300,
  • "report_interval": 300,
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Incidents for an API monitor

Newest-first incident history for one monitor, formatted into the shared Incidents-card shape used by every monitor family: pre-formatted display strings rather than raw timestamps. The window is a half-open overlap — an incident is in range when it started before date_end AND was still open after date_start — so a long outage spanning the window is included rather than dropped. metadata.total is the real count for the window and ignores limit/offset, so it can be used to drive paging.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

query Parameters
limit
integer
Default: 50
Example: limit=50

Page size, clamped to 1-200

offset
integer
Default: 0
Example: offset=0

Row offset into the newest-first list; negatives are floored to 0

date_start
integer
Default: 0

Window lower bound as a Unix timestamp; 0 (the default) means unbounded

date_end
integer
Default: 0

Window upper bound as a Unix timestamp; 0 (the default) means unbounded

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Per-run check log

Newest-first page of the append-only run log: one row per run of the step chain with its timestamp, total duration, pass/fail, the failing step + error, the pass count and the probe. Kept per plan retention, like every other monitor family's check history. The row's time is the run's identity — pass it to GET /{id}/logs/{time} for the per-step breakdown. The window is half-open: date_start is inclusive, date_end exclusive. The log lives in ClickHouse and degrades to an empty page with total 0 during a ClickHouse outage rather than returning an error, so an unexpectedly empty page is not proof that nothing ran.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

query Parameters
limit
integer
Default: 20
Example: limit=20

Page size, clamped to 1-100

offset
integer
Default: 0
Example: offset=0

Row offset; negatives are floored to 0

date_start
integer
Default: 0

Inclusive lower bound on the run time as a Unix timestamp (time >= date_start); 0 = unbounded

date_end
integer
Default: 0

Exclusive upper bound on the run time as a Unix timestamp (time < date_end); 0 = unbounded

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

One run in full

The summary of a single run plus every step of the chain as it was recorded: pass/fail/optional-failed/not-run, HTTP status, total and phase timings (DNS, connect, TLS, wait, receive), response size, the assertion tally and any error. time is the exact Unix second returned by GET /{id}/logs — there is no nearest-match, an unmatched timestamp is a 404. Step names, methods and paths come from the monitor's CURRENT definition, because the per-step storage keeps only the step number: a step renamed since the run shows today's name, and a step deleted since is labelled by its number alone.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

time
required
integer\d+
Example: 1756100400

Unix timestamp of the run, exactly as returned in the log row's time field

Responses

Response samples

Content type
application/json
{
  • "data": {
    },
  • "metadata": {
    }
}

Delete an API monitor incident

Deletes one CLOSED incident record of this monitor. The monitor's currently open incident is refused with 409 incident_open, because deleting it would leave the monitor pointing at a row that no longer exists — resolve or wait for the recovery first. The incident must belong to this monitor: an ID from another monitor answers 404 incident_not_found rather than deleting anything.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

incidentId
required
integer\d+
Example: 90211

Incident ID, as returned in error_id by GET /{id}/incidents

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Detail-page summary

One payload for the detail page: the decorated monitor and its steps, availability derived from incident downtime overlapping the window, the in-window incidents, run counts, per-step average/p95/share/delta, the bucketed stacked series and the last run. Pass an explicit from/to window in Unix seconds, or a rolling days window — days is only consulted when neither bound is given. The window is capped at 92 days and never ends later than now, and the series bucket width adapts (hourly up to 7 days, then 3h/6h/12h, daily beyond 30 days) so the series stays at 180 buckets or fewer. Availability comes from MariaDB incident rows, while the run statistics come from ClickHouse: during a ClickHouse outage runs_total, runs_failed, avg_run_ms, p95_run_ms, per_step and hourly degrade to 0 and empty arrays instead of erroring, so a zeroed run section next to a healthy availability figure means "stats unavailable", not "nothing ran".

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

query Parameters
from
integer
Example: from=1755500000

Explicit window start as a Unix timestamp. Consulted only when from or to is greater than 0, and replaced by (to − 7 days) when it is not strictly earlier than the resolved to.

to
integer
Example: to=1756100000

Explicit window end as a Unix timestamp, clamped to no later than now

days
integer
Default: 7
Example: days=7

Rolling-window length in days, used ONLY when neither from nor to is greater than 0. Minimum 1; the resulting window is still capped at 92 days.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Run a builder test (unsaved editor state)

Runs an UNSAVED step chain synchronously on a monitoring probe and returns the full per-step result: timings, HTTP codes, redacted response headers and body snippets, and the outcome of every assertion and extraction. Nothing is persisted and no incident can be opened by it. The call blocks for as long as the chain takes, up to the executor budget. Two gates apply before anything runs: the account plan must include API monitoring, and the account may run at most 10 tests per sliding minute. There is no stored monitor to merge secrets from, so a secret variable must carry its real value here; every secret with a non-empty value is passed to the probe as a redaction target so it never appears in an echoed URL, header, body snippet or error text.

Authorizations:
bearerAuth
Request Body schema: application/json
required
Array of objects

The chain to execute, in exactly the wire shape create and update accept. Validated with the same rules and the same error codes as a save — 1 to 15 steps, at most 20 headers, 15 asserts and 10 extracts per step, a body of at most 65536 bytes, a timeout of 1-60 seconds, a wait of 0-30000 ms, and {{placeholder}} names that are defined before the step that uses them — but with no name check and no plan pool check. A non-array value is treated as an empty chain and fails with steps_required.

Array of objects

Variables available to every step as {{name}}, at most 30, with identifier-shaped names and values of at most 4096 CR/LF-free characters. Used verbatim: a secret must carry its real value because there is no stored monitor to fill it from.

probe
integer

Force a single probe location ID to run the test. Absent or falsy lets the transport walk its default candidate list, i.e. the whole capable fleet.

run_to
integer

"Run to step N" — stop the chain after that step number; later steps come back with ran false. Clamped to 0-15; 0 (the default) runs the whole chain.

Responses

Request samples

Content type
application/json
{
  • "steps": [
    ],
  • "variables": [
    ],
  • "probe": 12,
  • "run_to": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Run a builder test against a saved monitor

The same synchronous builder test as POST /test, but against a SAVED monitor: masked secrets are filled in from storage, the monitor's own probe selection supplies the candidate list, and the result is persisted as the monitor's last run, marked as builder-sourced so the receiver never reasons an incident from a hand-triggered test. It does NOT advance last_check and never opens or closes an incident. The steps you send are executed as sent — the stored chain is not a fallback, so an absent or empty steps array fails with steps_required. The plan gate and the 10-per-minute rate limit are both applied BEFORE the ownership lookup, so a request for a foreign monitor ID still burns a rate-limit token.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Monitor ID

Request Body schema: application/json
required
Array of objects

The chain to execute, in exactly the wire shape create and update accept. Validated with the same rules and the same error codes as a save — 1 to 15 steps, at most 20 headers, 15 asserts and 10 extracts per step, a body of at most 65536 bytes, a timeout of 1-60 seconds, a wait of 0-30000 ms, and {{placeholder}} names that are defined before the step that uses them — but with no name check and no plan pool check. A non-array value is treated as an empty chain and fails with steps_required.

Array of objects

Variables available to every step as {{name}}, at most 30. Validated first, then merged against the monitor's STORED variables: an incoming variable whose value is "" and whose stored twin is a secret takes the stored secret value, so the editor can re-run a test without retyping credentials, while a non-empty incoming value always wins. Every secret with a resolved non-empty value is passed to the probe as a redaction target.

probe
integer

Force a single probe location ID. Absent, the candidate list is the monitor's own saved locations; when that is empty too (an "all probes" selection) the transport's default candidate list is used.

run_to
integer

Stop the chain after this step number; clamped to 0-15, 0 (the default) runs the whole chain.

Responses

Request samples

Content type
application/json
{
  • "steps": [
    ],
  • "variables": [
    ],
  • "probe": 12,
  • "run_to": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

DNS Monitors

Authoritative nameserver health and DNS record change monitoring for a zone.

List all DNS monitors

Returns every DNS monitor on the authenticated account, ordered by name ascending. There is no pagination — metadata.total is simply the number of rows in data. Each row is decorated: the JSON columns are decoded, the derived flags (is_up, is_paused, snooze_active, records_watched, locations) are added, and the sweep-engine internals (probes, vantage cursor, pull lease, last transcript, nameserver statistics, baseline) are stripped — fetch one monitor's summary for those. A scoped operator sees only the monitors in their monitor groups.

Authorizations:
bearerAuth
query Parameters
search
string
Example: search=example.com

Case-insensitive substring filter matched against BOTH the monitor name and the zone. LIKE wildcards (%, _, ) in the term are escaped, so they match literally. Omit for no filter.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a DNS monitor

Creates a DNS monitor for one zone and queues its baseline sweep for the next per-minute cron tick, so the first results land within a minute. The sweep interval is fixed at 300 seconds and is not configurable. dynamic_names is ignored here — a new monitor always starts with an empty dynamic list, and records are marked dynamic later from a change episode. Creation is refused with 403 plan_exceeded once the account is at its DNS pool allowance.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Monitor display name. Trimmed; 1-255 characters, otherwise the request is refused with name_invalid. Required.

zone
required
string

The DNS zone to watch, as a naked domain. It is normalized before storage: lowercased, with any scheme, path, query, port, leading "www." and trailing dot stripped, and IDN converted to punycode. It must then match a hostname of at most 253 characters with a 2-63 letter TLD; anything that parses as an IPv4 or IPv6 literal is refused with zone_invalid. Required.

watch_names
Array of strings

Relative record names swept for A, AAAA and CNAME. Entries are lowercased, the trailing dot is trimmed and duplicates are removed. A name ending in the zone is reduced to its relative form: www.example.com on the zone example.com is stored as www, and the zone itself as "@". The apex marker "@" always comes first. At most 20 names counting "@", so 19 besides it, of at most 253 characters each and 63 per label. A wildcard is refused with 422 watch_names_wildcard; any other invalid name, an empty entry, an entry that is not a string or integer, or a value that is not an array with watch_names_invalid; more than 20 names with watch_names_max. Defaults to ["@", "www"].

object

Per record-group alerting. Any group you omit is filled in with its default (enabled, and severity critical for addresses / mail / ns, trouble for policy), and an unrecognised severity falls back to that default — this field can never fail validation. A disabled group still records its changes, but at info severity, so they show on the detail page and never page anyone.

verify_sweeps
integer
Enum: 1 3 5

Consecutive clean sweeps required before a change episode auto-closes as restored. Must be 1, 3 or 5 (verify_sweeps_invalid otherwise); each step is one 5-minute sweep, so 3 means roughly 15 minutes of agreement. Defaults to 3.

serial_drift_seconds
integer
Enum: 1800 7200 21600

How long SOA serials may disagree between the zone's authoritative nameservers before a serial-drift health episode opens, in seconds. Must be 1800 (30 min), 7200 (2 h) or 21600 (6 h) — serial_drift_invalid otherwise. Defaults to 1800; raise it for zones whose provider replicates slowly.

confirmations_required
integer
Enum: 1 2 3

Outage-confirmation depth for the pull model: how many vantages must independently observe the same finding before it is acted on. Must be 1, 2 or 3 (confirmations_invalid otherwise) and is clamped into that range on write. Defaults to 3; lowering it trades false-positive protection for faster alerts.

snooze
integer
Enum: 0 14400 86400 604800

A snooze DURATION in seconds, not a timestamp — the monitor stores snooze_until = now + this value, and 0 clears an active snooze. Must be 0, 14400 (4 h), 86400 (24 h) or 604800 (7 d), otherwise snooze_invalid. Defaults to 0.

(string or null) or (Array of integers or null)

Vantage selection. The literal string "all" (and an absent key, null or an empty array) sweeps from the whole DNS-capable fleet. An explicit list of checkpoint ids must name at least 6 DNS-capable vantages, otherwise the request is refused with too_few_locations — a smaller pool cannot carry the confirmation quorum. Ids outside the DNS fleet are stored as submitted (a shared Location Profile may carry them) and skipped at sweep time.

report_up
integer

Whether recovery ("restored") notifications are sent. Any non-zero value stores 1. Defaults to 1 on create.

escalation_policy_id
integer

Escalation policy that routes this monitor's alerts. 0 (the default) alerts every recipient at once; a value above 0 must reference a policy owned by the account or the request is refused with invalid_escalation_policy.

branding_id
integer

Branding template applied to this monitor's alert emails and reports. 0 (the default) uses the default theme; non-numeric junk, or an id not owned by the account, is refused with invalid_branding.

notes
string

Free-text operator note stored on the monitor. Trimmed and truncated to 500 characters; a non-string value stores an empty string. Written only when the key is present, so an omitted note is never clobbered.

(Array of integers or objects or null) or (string or null)

Alert recipients: bare contact ids, or objects naming what each id refers to. Every id must belong to the account. The literal string "all" selects every account contact and "no_changes" leaves the stored bindings alone. On create, omitting the key (or sending null) seeds every account contact; sending the key with an empty value is refused, because a monitor that can alert nobody is not worth running.

Array of integers or integer

Monitor-group ids this monitor belongs to; a single bare integer is accepted too. Every id must belong to the account. A scoped operator's submitted list is rewritten so the monitor always stays in at least one of their scope groups — it can never be created or edited into invisibility — while owner-assigned memberships outside that scope are preserved.

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Responses

Request samples

Content type
application/json
{
  • "name": "example.com zone",
  • "zone": "example.com",
  • "watch_names": [
    ],
  • "group_settings": {
    },
  • "verify_sweeps": 3,
  • "serial_drift_seconds": 1800,
  • "confirmations_required": 3,
  • "snooze": 0,
  • "probes": "all",
  • "report_up": 1,
  • "escalation_policy_id": 0,
  • "branding_id": 0,
  • "notes": "Zone is managed by the platform team.",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a DNS monitor

Returns one DNS monitor with its alert recipients, monitor-group memberships and the Location Profile its vantage selection was applied from — everything the editor needs to prefill. This is the configuration read; for the baseline, episodes, watch matrix and last sweep, use GET /api/v2/dns/{id}/summary instead. A monitor outside a scoped operator's groups answers exactly like a missing one.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Replace a DNS monitor (alias of PATCH)

An alias of PATCH /api/v2/dns/{id}, kept for client compatibility: the route declares both methods and they resolve to the same handler, so PUT here is NOT a full replacement — the semantics are partial exactly as for PATCH. Partial update: every omitted field keeps its stored value. is_paused may travel alone or alongside a configuration edit, and the pause is applied only after the whole request validates, so a 422 means nothing was written. A watch-config change (zone, watch_names, group_settings, dynamic_names) pulls the next sweep forward to within a minute and invalidates any in-flight pull lease; a ZONE change additionally wipes the baseline, discovered nameservers, last transcript, nameserver statistics, serial-drift timer and delegation timestamp so the next sweep re-baselines from scratch. Config edits also reconcile open episodes: episodes whose watch key is no longer watched (or all of them, on a zone change) close silently, survivors take the NEW group severity, and the incident and counters are recomputed. Two narrower response shapes exist: sending only is_paused answers with the bare {id}, and so does a write whose read-back came back empty.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

Request Body schema: application/json
name
string

Monitor display name. Trimmed; 1-255 characters, otherwise the request is refused with name_invalid. Omit to keep the stored name.

zone
string

The DNS zone to watch, as a naked domain. It is normalized before storage: lowercased, with any scheme, path, query, port, leading "www." and trailing dot stripped, and IDN converted to punycode. It must then match a hostname of at most 253 characters with a 2-63 letter TLD; anything that parses as an IPv4 or IPv6 literal is refused with zone_invalid. Omit to keep the stored zone. CHANGING IT IS DESTRUCTIVE: the baseline, the discovered nameservers, the last sweep transcript, the 24 h nameserver statistics, the serial-drift timer and the delegation-check timestamp are all reset, and every open episode is closed silently, because all of it described the old zone.

watch_names
Array of strings

Relative record names swept for A, AAAA and CNAME. Entries are lowercased, the trailing dot is trimmed and duplicates are removed. A name ending in the zone is reduced to its relative form: www.example.com on the zone example.com is stored as www, and the zone itself as "@". The apex marker "@" always comes first. At most 20 names counting "@", so 19 besides it, of at most 253 characters each and 63 per label. A wildcard is refused with 422 watch_names_wildcard; any other invalid name, an empty entry, an entry that is not a string or integer, or a value that is not an array with watch_names_invalid; more than 20 names with watch_names_max. Omit to keep the stored list. Removing a name takes its dynamic marking with it and silently closes any episode on its keys.

object

Per record-group alerting. Any group you omit is filled in with its default (enabled, and severity critical for addresses / mail / ns, trouble for policy), and an unrecognised severity falls back to that default — this field can never fail validation. A disabled group still records its changes, but at info severity, so they show on the detail page and never page anyone.

dynamic_names
Array of strings

Watch keys ("name|TYPE") whose VALUES are allowed to rotate: presence and record type are still compared, the answer itself is not. Entries that are not in the current watch matrix are dropped. Normally managed through POST /api/v2/dns/{id}/changes/{changeId}/dynamic rather than here, and omitting the key preserves the stored list. Ignored entirely on create, where the list always starts empty.

verify_sweeps
integer
Enum: 1 3 5

Consecutive clean sweeps required before a change episode auto-closes as restored. Must be 1, 3 or 5 (verify_sweeps_invalid otherwise); each step is one 5-minute sweep, so 3 means roughly 15 minutes of agreement. Omit to keep the stored value.

serial_drift_seconds
integer
Enum: 1800 7200 21600

How long SOA serials may disagree between the zone's authoritative nameservers before a serial-drift health episode opens, in seconds. Must be 1800 (30 min), 7200 (2 h) or 21600 (6 h) — serial_drift_invalid otherwise. Omit to keep the stored value.

confirmations_required
integer
Enum: 1 2 3

Outage-confirmation depth for the pull model: how many vantages must independently observe the same finding before it is acted on. Must be 1, 2 or 3 (confirmations_invalid otherwise) and is clamped into that range on write. Omit to keep the stored value.

snooze
integer
Enum: 0 14400 86400 604800

A snooze DURATION in seconds, not a timestamp — the monitor stores snooze_until = now + this value, and 0 clears an active snooze. Must be 0, 14400 (4 h), 86400 (24 h) or 604800 (7 d), otherwise snooze_invalid. Written only when the key is present, so an omitted key leaves an active snooze running.

(string or null) or (Array of integers or null)

Vantage selection. The literal string "all" (and an absent key, null or an empty array) sweeps from the whole DNS-capable fleet. An explicit list of checkpoint ids must name at least 6 DNS-capable vantages, otherwise the request is refused with too_few_locations — a smaller pool cannot carry the confirmation quorum. Ids outside the DNS fleet are stored as submitted (a shared Location Profile may carry them) and skipped at sweep time.

report_up
integer

Whether recovery ("restored") notifications are sent. Any non-zero value stores 1. Omit to keep the stored value.

escalation_policy_id
integer

Escalation policy that routes this monitor's alerts. 0 (the default) alerts every recipient at once; a value above 0 must reference a policy owned by the account or the request is refused with invalid_escalation_policy.

branding_id
integer

Branding template applied to this monitor's alert emails and reports. 0 (the default) uses the default theme; non-numeric junk, or an id not owned by the account, is refused with invalid_branding.

notes
string

Free-text operator note stored on the monitor. Trimmed and truncated to 500 characters; a non-string value stores an empty string. Written only when the key is present, so an omitted note is never clobbered.

(Array of integers or objects or null) or (string or null)

Alert recipients: bare contact ids, or objects naming what each id refers to. Every id must belong to the account. The literal string "all" selects every account contact and "no_changes" leaves the stored bindings alone. Omitting the key, or sending null or "no_changes", keeps the stored list and skips the ownership check entirely. An empty array reaches the guard and is refused with invalid_contacts, so a monitor can never be left with nobody to alert.

Array of integers or integer

Monitor-group ids this monitor belongs to; a single bare integer is accepted too. Every id must belong to the account. A scoped operator's submitted list is rewritten so the monitor always stays in at least one of their scope groups — it can never be created or edited into invisibility — while owner-assigned memberships outside that scope are preserved.

(boolean or null) or (integer or null)

Pause (truthy) or resume (falsy, including an explicit null) the monitor. It may travel alone or alongside a configuration edit; either way the pause is applied only after the whole request has validated, so a 422 means nothing was written. Sent on its own the response is the bare {id}.

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Responses

Request samples

Content type
application/json
{
  • "name": "example.com zone",
  • "zone": "example.com",
  • "watch_names": [
    ],
  • "group_settings": {
    },
  • "dynamic_names": [
    ],
  • "verify_sweeps": 3,
  • "serial_drift_seconds": 1800,
  • "confirmations_required": 3,
  • "snooze": 0,
  • "probes": "all",
  • "report_up": 1,
  • "escalation_policy_id": 0,
  • "branding_id": 0,
  • "notes": "Zone is managed by the platform team.",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "is_paused": true,
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a DNS monitor

Permanently deletes the monitor and cascades synchronously — change episodes, recipient bindings, incidents, maintenance windows and pauses, group memberships, the pending pull-queue rows, and the ClickHouse sweep history all go with it. An account-activity entry is recorded. There is no undo and no soft-delete tombstone: nothing here is recoverable afterwards.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update a DNS monitor

Partial update: every omitted field keeps its stored value. is_paused may travel alone or alongside a configuration edit, and the pause is applied only after the whole request validates, so a 422 means nothing was written. A watch-config change (zone, watch_names, group_settings, dynamic_names) pulls the next sweep forward to within a minute and invalidates any in-flight pull lease; a ZONE change additionally wipes the baseline, discovered nameservers, last transcript, nameserver statistics, serial-drift timer and delegation timestamp so the next sweep re-baselines from scratch. Config edits also reconcile open episodes: episodes whose watch key is no longer watched (or all of them, on a zone change) close silently, survivors take the NEW group severity, and the incident and counters are recomputed. Two narrower response shapes exist: sending only is_paused answers with the bare {id}, and so does a write whose read-back came back empty.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

Request Body schema: application/json
name
string

Monitor display name. Trimmed; 1-255 characters, otherwise the request is refused with name_invalid. Omit to keep the stored name.

zone
string

The DNS zone to watch, as a naked domain. It is normalized before storage: lowercased, with any scheme, path, query, port, leading "www." and trailing dot stripped, and IDN converted to punycode. It must then match a hostname of at most 253 characters with a 2-63 letter TLD; anything that parses as an IPv4 or IPv6 literal is refused with zone_invalid. Omit to keep the stored zone. CHANGING IT IS DESTRUCTIVE: the baseline, the discovered nameservers, the last sweep transcript, the 24 h nameserver statistics, the serial-drift timer and the delegation-check timestamp are all reset, and every open episode is closed silently, because all of it described the old zone.

watch_names
Array of strings

Relative record names swept for A, AAAA and CNAME. Entries are lowercased, the trailing dot is trimmed and duplicates are removed. A name ending in the zone is reduced to its relative form: www.example.com on the zone example.com is stored as www, and the zone itself as "@". The apex marker "@" always comes first. At most 20 names counting "@", so 19 besides it, of at most 253 characters each and 63 per label. A wildcard is refused with 422 watch_names_wildcard; any other invalid name, an empty entry, an entry that is not a string or integer, or a value that is not an array with watch_names_invalid; more than 20 names with watch_names_max. Omit to keep the stored list. Removing a name takes its dynamic marking with it and silently closes any episode on its keys.

object

Per record-group alerting. Any group you omit is filled in with its default (enabled, and severity critical for addresses / mail / ns, trouble for policy), and an unrecognised severity falls back to that default — this field can never fail validation. A disabled group still records its changes, but at info severity, so they show on the detail page and never page anyone.

dynamic_names
Array of strings

Watch keys ("name|TYPE") whose VALUES are allowed to rotate: presence and record type are still compared, the answer itself is not. Entries that are not in the current watch matrix are dropped. Normally managed through POST /api/v2/dns/{id}/changes/{changeId}/dynamic rather than here, and omitting the key preserves the stored list. Ignored entirely on create, where the list always starts empty.

verify_sweeps
integer
Enum: 1 3 5

Consecutive clean sweeps required before a change episode auto-closes as restored. Must be 1, 3 or 5 (verify_sweeps_invalid otherwise); each step is one 5-minute sweep, so 3 means roughly 15 minutes of agreement. Omit to keep the stored value.

serial_drift_seconds
integer
Enum: 1800 7200 21600

How long SOA serials may disagree between the zone's authoritative nameservers before a serial-drift health episode opens, in seconds. Must be 1800 (30 min), 7200 (2 h) or 21600 (6 h) — serial_drift_invalid otherwise. Omit to keep the stored value.

confirmations_required
integer
Enum: 1 2 3

Outage-confirmation depth for the pull model: how many vantages must independently observe the same finding before it is acted on. Must be 1, 2 or 3 (confirmations_invalid otherwise) and is clamped into that range on write. Omit to keep the stored value.

snooze
integer
Enum: 0 14400 86400 604800

A snooze DURATION in seconds, not a timestamp — the monitor stores snooze_until = now + this value, and 0 clears an active snooze. Must be 0, 14400 (4 h), 86400 (24 h) or 604800 (7 d), otherwise snooze_invalid. Written only when the key is present, so an omitted key leaves an active snooze running.

(string or null) or (Array of integers or null)

Vantage selection. The literal string "all" (and an absent key, null or an empty array) sweeps from the whole DNS-capable fleet. An explicit list of checkpoint ids must name at least 6 DNS-capable vantages, otherwise the request is refused with too_few_locations — a smaller pool cannot carry the confirmation quorum. Ids outside the DNS fleet are stored as submitted (a shared Location Profile may carry them) and skipped at sweep time.

report_up
integer

Whether recovery ("restored") notifications are sent. Any non-zero value stores 1. Omit to keep the stored value.

escalation_policy_id
integer

Escalation policy that routes this monitor's alerts. 0 (the default) alerts every recipient at once; a value above 0 must reference a policy owned by the account or the request is refused with invalid_escalation_policy.

branding_id
integer

Branding template applied to this monitor's alert emails and reports. 0 (the default) uses the default theme; non-numeric junk, or an id not owned by the account, is refused with invalid_branding.

notes
string

Free-text operator note stored on the monitor. Trimmed and truncated to 500 characters; a non-string value stores an empty string. Written only when the key is present, so an omitted note is never clobbered.

(Array of integers or objects or null) or (string or null)

Alert recipients: bare contact ids, or objects naming what each id refers to. Every id must belong to the account. The literal string "all" selects every account contact and "no_changes" leaves the stored bindings alone. Omitting the key, or sending null or "no_changes", keeps the stored list and skips the ownership check entirely. An empty array reaches the guard and is refused with invalid_contacts, so a monitor can never be left with nobody to alert.

Array of integers or integer

Monitor-group ids this monitor belongs to; a single bare integer is accepted too. Every id must belong to the account. A scoped operator's submitted list is rewritten so the monitor always stays in at least one of their scope groups — it can never be created or edited into invisibility — while owner-assigned memberships outside that scope are preserved.

(boolean or null) or (integer or null)

Pause (truthy) or resume (falsy, including an explicit null) the monitor. It may travel alone or alongside a configuration edit; either way the pause is applied only after the whole request has validated, so a 422 means nothing was written. Sent on its own the response is the bare {id}.

(string or null) or (integer or null)

Records WHICH saved Location Profile the vantage selection came from, so the editor's Locations tab can show the applied profile. Either a built-in synthetic id ("builtin:") or the numeric id of a profile owned by the account; anything else clears the binding. Provenance only — the vantages themselves still come from probes. Written only when the key is present, so an unrelated update never clobbers it.

Responses

Request samples

Content type
application/json
{
  • "name": "example.com zone",
  • "zone": "example.com",
  • "watch_names": [
    ],
  • "group_settings": {
    },
  • "dynamic_names": [
    ],
  • "verify_sweeps": 3,
  • "serial_drift_seconds": 1800,
  • "confirmations_required": 3,
  • "snooze": 0,
  • "probes": "all",
  • "report_up": 1,
  • "escalation_policy_id": 0,
  • "branding_id": 0,
  • "notes": "Zone is managed by the platform team.",
  • "contacts": [
    ],
  • "groups": [
    ],
  • "is_paused": true,
  • "location_profile": "builtin:europe"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get the detail-page summary

The entire DNS detail page in one payload: the decorated monitor with its baseline, the newest change and health episodes, the last sweep's raw transcript, the rolling 24-hour per-nameserver roll-up, recent incidents, the effective watch matrix and the SOA serial state. The episode feed is capped at 200 rows but is unioned with the newest change episode per watch key however old, so a long-running change never loses its ack affordance. Incidents here are RAW rows with Unix timestamps — the incidents endpoint returns pre-formatted strings instead.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Queue a sweep now

Queues an on-demand sweep by making the monitor due immediately and clearing any in-flight pull lease, so the per-minute sweep cron picks it up on its next tick. It does NOT sweep synchronously — poll the logs or the summary for the result. Rate-limited to 10 requests per sliding minute per ACCOUNT, not per IP, because teams share NAT addresses; each recheck also drops any in-flight result, so hammering it prevents the monitor from ever completing a sweep. Refused outright for monitors the sweep engine skips anyway.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Acknowledge a change episode

Accepts a changed record as the new truth: the episode's after-values become the baseline for that watch key (recorded with source ack), the episode closes as acked with the acting operator and an optional note, and the monitor's counters and open incident are recomputed. When nothing alertable remains open, the incident closes through the recovery path: everyone who received the alert is told who accepted the change, and report_up is honoured. The request is refused while the value moved since it was shown or while a nameserver still serves another value; neither check applies to a dynamic record. Acknowledge only changes you intend to keep; use mark-dynamic instead when the record legitimately rotates. Health findings and already-closed episodes cannot be acknowledged.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

changeId
required
integer\d+
Example: 90211

Change-episode id, as returned in episodes[].id by the summary endpoint.

Request Body schema: application/json
note
string

Optional free-text reason recorded on the episode as ack_note. Trimmed and truncated to 500 characters; defaults to an empty string. The actor is NOT taken from the body — acked_by is the signed-in operator's email, read from the session.

after_digest
string

The episode's after_digest from the summary: the values the person was shown. Omit it to skip the moved-value check.

Responses

Request samples

Content type
application/json
{
  • "note": "DNS migration to the new provider, expected.",
  • "after_digest": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Accept several open record changes in one decision

Checks every listed change, then accepts them all or none. An id listed twice counts once. Each new answer becomes that record's baseline. When nothing alertable remains open the incident closes and everyone who received the warning is told who accepted it. 409 value_moved means a record changed again since it was shown; 409 servers_disagree means a nameserver still serves something else.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
required
Array of objects
note
string

Optional reason, at most 500 characters.

Responses

Request samples

Content type
application/json
{
  • "changes": [
    ],
  • "note": "string"
}

Mark a changed record as dynamic

"This record legitimately rotates." Adds the episode's watch key to the monitor's dynamic list — from then on only the record's presence and type are compared and its values are ignored — AND acknowledges the episode in the same call, with the fixed note "marked dynamic — values are allowed to rotate". Use it for round-robin CDN answers and similar churn that would otherwise page on every rotation. The key is re-validated against the current watch matrix, so a key that is no longer watched is dropped. Health findings and non-active episodes are refused.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

changeId
required
integer\d+
Example: 90211

Change-episode id, as returned in episodes[].id by the summary endpoint.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for a DNS monitor

Newest-first incident history for one DNS monitor — change and health alerts and their recoveries — pre-formatted for the shared Incidents card. Beware the timestamps: time_started and time_ended are human strings in the account timezone, not Unix integers; read GET /api/v2/dns/{id}/summary if you need raw incident rows. metadata.total is a real count over the same date window and is unaffected by limit and offset.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

query Parameters
limit
integer [ 1 .. 200 ]
Default: 50
Example: limit=50

Page size. Defaults to 50 and is clamped into 1-200, so an absurd value cannot pull the whole table and a negative one cannot yield an empty page.

offset
integer
Default: 0
Example: offset=0

Zero-based row offset into the newest-first list. Negatives are floored to 0.

date_start
integer
Default: 0
Example: date_start=0

Unix timestamp lower bound; 0 (the default) means unbounded. The window is half-open on overlap: an incident counts when it was still open after this moment (time_ended = 0 or time_ended > date_start), so a long outage that began earlier is still included.

date_end
integer
Default: 0
Example: date_end=0

Unix timestamp upper bound; 0 (the default) means unbounded. An incident counts when it started before this moment. Applies to the page and to metadata.total alike.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

List the per-sweep check log

Newest-first page of the append-only sweep log — one row per sweep, read from the check-history store and retained for the account's plan retention like every other family's check history. Note that duration is the SLOWEST nameserver's mean answer time for that sweep, not an average across servers, and that changes and health_issues are the episode counts as they stood at sweep time rather than now. Take time from here to open a single sweep in full.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

query Parameters
limit
integer [ 1 .. 100 ]
Default: 20
Example: limit=20

Page size. Defaults to 20 and is clamped into 1-100.

offset
integer
Default: 0
Example: offset=0

Zero-based row offset into the newest-first log. Negatives are floored to 0.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get one sweep in full

One sweep's counters plus the per-nameserver answers behind them: each authoritative server's reachability, mean answer time, SOA serial, AA bit and TCP/recursion probes, and every watched record exactly as THAT server answered it. servers and episodes are mutually exclusive and cells_source says which you are looking at — sweeps older than per-cell storage have no stored answers, so the episodes open at that moment are rebuilt instead, a view that can name what was wrong and never what was right. The {time} segment must be an exact time value from the logs listing.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

time
required
integer\d+
Example: 1756100300

Unix timestamp of the sweep, taken verbatim from a time value in GET /api/v2/dns/{id}/logs. It is matched exactly, not as a range.

Responses

Response samples

Content type
application/json
{
  • "data": {
    },
  • "metadata": {
    }
}

Delete a DNS incident

Deletes one CLOSED incident record belonging to this monitor. The currently open incident can never be deleted — that is guarded twice, once against the monitor's own open-incident pointer and once against the incident's missing end time — because removing it would strand the monitor in an alerting state with nothing to recover from. Deleting an incident does not touch the sweep log or the change episodes behind it.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4211

DNS monitor id.

incidentId
required
integer\d+
Example: 55120

Incident id, as returned in error_id by the incidents listing.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Heartbeat Monitors

Inbound ping (dead man's switch) monitoring for cron jobs and background tasks.

List all heartbeat monitors

Returns every heartbeat monitor on the account, ordered by name ascending, each decorated with the ping URL its job should call. Rows carry the whole monitor record but NOT the contacts/groups relations — fetch a single monitor for those. Monitor-group scoping is applied inside the read, so a scoped team member sees only the monitors in their scope groups and a member with an empty scope gets an empty list with total 0.

Authorizations:
bearerAuth
query Parameters
search
string
Example: search=invoice

Case-insensitive substring match on the monitor name (SQL LIKE %search%). An empty string is treated as no filter.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a heartbeat monitor

Creates an inbound (dead-man switch) monitor and mints its unique ping token — the literal hb_ followed by 32 hexadecimal characters. The monitor is written unarmed and arms itself on its first real ping, so nothing can alert until the job has checked in once; a manual test ping deliberately does not arm it. Omitting contacts entirely auto-seeds every account contact, while sending an empty contacts array is refused outright, so a monitor can never exist with nobody to alert. Creation is refused with 403 plan_exceeded once the account non-suspended heartbeat monitors reach the plan heartbeat allowance.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Monitor display name. Trimmed; must be non-empty and at most 255 characters (error code name_invalid).

watches
string
Enum: "cron" "worker" "queue" "backup" "iot" "other"

What the job is. Labelling only — it never changes the schedule maths. Defaults to cron (error code watches_invalid).

schedule_type
string
Enum: "interval" "cron"

interval expects a ping every interval_seconds after the last one (self-referential, so timezone is inert); cron expects a ping at each fire time of cron_expression, evaluated in the monitor timezone. Defaults to interval (error code schedule_type_invalid).

interval_seconds
integer

Expected seconds between pings, 30 to 7776000 (90 days); defaults to 300. Both schedule columns are always persisted, so a value sent in cron mode is still range-checked and stored as the dormant value (error code interval_invalid).

cron_expression
string

5-field cron expression. Required in cron mode; in interval mode it is optional but, when non-empty, still validated and stored as the dormant value. Macros (@hourly, @daily, @midnight, @weekly, @monthly, @yearly, @annually) and three-letter month/day names are accepted. Validation walks 3100 consecutive days from a fixed 2001-01-01 reference, so an expression that parses but can never match a real date (0 0 30 2 *) is rejected (error code cron_invalid).

timezone
integer

config/time_zone.php id (1-128) the cron schedule is evaluated in — the zone the customer cron daemon runs in, not where the account sits. 0, the default, inherits the account timezone (UTC when the account has none). Only consulted in cron mode. The shape is checked strictly: an integer or an all-digit string, never a cast of a non-numeric value (error code timezone_invalid).

grace_seconds
integer

How long after the expected ping time the sweep waits before opening a missed-ping incident, 0 to 2592000 (30 days); defaults to 120 (error code grace_invalid).

late_threshold_seconds
integer

Lower bound of the late-but-within-grace warning band, 0 to 2592000; defaults to 10. A ping later than expected by less than this is treated as on time. A value above grace_seconds is refused with late_threshold_exceeds_grace because it would leave the warning band empty and the late metric inert (error code late_threshold_invalid).

runtime_limit_seconds
integer

Maximum allowed job runtime — the gap between a /start ping and its matching success ping — up to 604800 (7 days). 0, the default, disables the check (error code runtime_limit_invalid).

fail_alerts
boolean

Whether an explicit /fail ping pages the recipients. Defaults to true when absent, and is parsed permissively, so the string "false" disables paging rather than enabling it.

report_up
integer

Whether the recovery notification is sent when the monitor pings again. Stored as 0 only when the value casts to integer 0; anything else, including absence, stores 1.

escalation_policy_id
integer

Escalation policy that routes this monitor alerts. 0, the default, alerts every recipient at once; a value above 0 must reference a policy owned by this account.

branding_id
integer

Branding theme applied to this monitor alert emails and reports. 0, the default, is the standard theme; a value above 0 must belong to this account.

notes
string

Free-text operator note shown on the incident page and included in alert emails and webhook payloads. Non-string input becomes an empty string; the value is trimmed and hard-truncated to 500 characters.

(Array of integers or objects) or string

Alert recipients: an array of bare contact ids, an array of typed recipient objects, or one of the sentinels "all" and "no_changes". OMITTING the key (or sending null, or the no_changes sentinel, which has no stored list to preserve on a create) auto-seeds every contact on the account so the new monitor always alerts somebody; sending a PRESENT but EMPTY array is refused with no_contacts_provided. Every id must belong to this account.

groups
Array of integers

Monitor-group ids this monitor joins; every id must belong to this account. An absent key assigns no groups. For a scoped team member the submitted list is rewritten so the new monitor always lands in at least one of their scope groups and can never be created invisible to its author; unrestricted actors keep the list byte for byte.

Responses

Request samples

Content type
application/json
{
  • "name": "Nightly invoice export",
  • "watches": "cron",
  • "schedule_type": "interval",
  • "interval_seconds": 300,
  • "cron_expression": "0 3 * * 1-5",
  • "timezone": 0,
  • "grace_seconds": 120,
  • "late_threshold_seconds": 10,
  • "runtime_limit_seconds": 0,
  • "fail_alerts": true,
  • "report_up": 1,
  • "escalation_policy_id": 0,
  • "branding_id": 0,
  • "notes": "Runs on cron-box-2; owner: billing team",
  • "contacts": [
    ],
  • "groups": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Validate a cron expression and preview its next runs

Validates a cron expression that has not been saved yet and previews its next three fire times, so the editor can show the customer what the schedule will do before they commit to it. Validation is stricter than a parse: the expression is also walked across 3100 consecutive days from a FIXED 2001-01-01 reference date to prove it can match a real calendar day at all, so a parseable-but-impossible expression such as 0 0 30 2 * is reported invalid. That satisfiability walk does not depend on the current date or on the timezone. The runs are previewed in the timezone the caller is about to save; 0 or an absent timezone previews them in the account timezone, and an unresolvable timezone id is silently clamped to that same account default rather than rejected.

Authorizations:
bearerAuth
Request Body schema: application/json
expression
string

The cron expression to test: five fields (minute hour day-of-month month day-of-week), or one of the macros @hourly, @daily, @midnight, @weekly, @monthly, @yearly and @annually. Three-letter month names (jan-dec) and day names (sun-sat) are accepted, as are the step, range and list forms; day-of-week 7 means Sunday. Trimmed and lowercased before use; an empty or absent value simply answers valid=false rather than erroring.

timezone
integer

config/time_zone.php id (1-128) to preview the runs in. 0 or absent uses the account timezone, which resolves to UTC when the account has none.

Responses

Request samples

Content type
application/json
{
  • "expression": "0 3 * * 1-5",
  • "timezone": 128
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a heartbeat monitor

Returns one heartbeat monitor as the fully decorated record — every stored column, the derived up/paused/maintenance flags, the alert recipients, the monitor-group memberships and the ping URL. This is the read the monitor editor prefills from. A monitor that does not exist, belongs to another account, or sits outside the acting member monitor-group scope answers the same 404 in all three cases, so ids cannot be probed.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update a heartbeat monitor

Partial update: omitted fields keep their stored values. The nine identity, schedule and threshold fields (name, watches, schedule_type, interval_seconds, cron_expression, timezone, grace_seconds, late_threshold_seconds, runtime_limit_seconds) are merged from the stored row before validation, so a payload that changes one of them is still validated against the rest of the saved configuration — raising late_threshold_seconds alone can therefore fail against the stored grace_seconds. The guard order is load-bearing: ownership first, then the payload parse, then every validation, and only then the pause write, so a request that ends in a 422 can never have silently paused the dead-man switch. Sending is_paused on its own returns { data: { id } } without re-reading the monitor; resuming grants one fresh schedule window so a stale pre-pause deadline cannot alert immediately. PUT is an alias of PATCH — both verbs resolve to the same handler and behave identically, so PUT is NOT a full replace; it is kept for client compatibility.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

Request Body schema: application/json
is_paused
boolean

Pause (true) or resume (false) the monitor. Parsed as a real boolean, so the string "false" RESUMES; a value that cannot be parsed is a 422. Resuming grants one fresh schedule window so a stale pre-pause deadline cannot alert immediately. When is_paused is the ONLY key in the body the pause is applied and the response is just { data: { id } } with no monitor re-read; sent alongside other fields it is applied only after every sibling field has validated, so a request that ends in a 422 can never have silently paused the dead-man switch.

name
string

Monitor display name; trimmed, 1 to 255 characters. Omitted means unchanged.

watches
string
Enum: "cron" "worker" "queue" "backup" "iot" "other"

What the job is. Labelling only. Omitted means unchanged.

schedule_type
string
Enum: "interval" "cron"

interval or cron. Changing it in either direction counts as a schedule change and recomputes the next expected ping for an armed monitor.

interval_seconds
integer

Expected seconds between pings, 30 to 7776000. A change recomputes expected_next_at for an armed monitor from the later of its last ping and now.

cron_expression
string

5-field cron expression (or one of the @hourly/@daily/@midnight/@weekly/@monthly/@yearly/@annually macros); validated whenever non-empty and mandatory in cron mode. A change recomputes expected_next_at for an armed monitor.

timezone
integer

config/time_zone.php id; 0 inherits the account timezone. Counts as a schedule change ONLY in cron mode — an interval schedule is self-referential, so recomputing there would push a dead job missed-ping incident out by a whole interval. In cron mode the next expected ping is recomputed immediately so an armed monitor does not keep the previous zone deadline. Same strict integer / all-digit-string shape rule as on create.

grace_seconds
integer

Seconds before a missed ping opens an incident, 0 to 2592000. Must be greater than or equal to late_threshold_seconds, compared against the MERGED values — so raising the threshold alone can fail against the stored grace.

late_threshold_seconds
integer

Lower bound of the in-grace late band, 0 to 2592000. Must not exceed grace_seconds.

runtime_limit_seconds
integer

Maximum permitted /start-to-success runtime in seconds, up to 604800. 0 turns the check off.

fail_alerts
boolean

Whether a /fail ping pages the recipients. Absent preserves the stored flag; the string "false" disables paging.

report_up
integer

Send the recovery notification. Stored as 0 only when the value casts to integer 0; absent preserves the stored flag.

escalation_policy_id
integer

Escalation policy to alert through; 0 alerts every recipient at once and a value above 0 must belong to this account. Absent preserves the stored binding.

branding_id
integer

Branding template; 0 is the standard theme and a value above 0 must belong to this account. Absent preserves the stored value.

notes
string

Operator note, trimmed and capped at 500 characters. Normalized only when the key is actually present; an absent key preserves the stored note.

(Array of integers or objects) or string

Replaces the alert recipients. Bare ids, typed recipient objects, or the sentinels "all" and "no_changes". An ABSENT key — or an explicit null — leaves the stored bindings untouched and skips the ownership check entirely.

groups
Array of integers

Replaces the monitor group memberships; every id must belong to this account. Absent leaves memberships unchanged. For a scoped team member the list is rewritten so their edit stays confined to their scope groups, while owner-assigned memberships outside that scope are preserved rather than orphaned.

Responses

Request samples

Content type
application/json
{
  • "is_paused": false,
  • "name": "Nightly invoice export",
  • "watches": "cron",
  • "schedule_type": "cron",
  • "interval_seconds": 300,
  • "cron_expression": "0 3 * * 1-5",
  • "timezone": 0,
  • "grace_seconds": 120,
  • "late_threshold_seconds": 10,
  • "runtime_limit_seconds": 0,
  • "fail_alerts": true,
  • "report_up": 1,
  • "escalation_policy_id": 0,
  • "branding_id": 0,
  • "notes": "Runs on cron-box-2; owner: billing team",
  • "contacts": [
    ],
  • "groups": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a heartbeat monitor

Permanently deletes the monitor and everything hanging off it: the monitor record, its recipient bindings, its incidents, its frozen ping/maintenance/pause rows, its monitor-group memberships and its ClickHouse ping history. The ping history purge is best-effort — a ClickHouse outage is logged and swallowed so it cannot block the erasure of the relational data. The deletion is irreversible and frees a slot in the plan heartbeat allowance.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update a heartbeat monitor

Partial update: omitted fields keep their stored values. The nine identity, schedule and threshold fields (name, watches, schedule_type, interval_seconds, cron_expression, timezone, grace_seconds, late_threshold_seconds, runtime_limit_seconds) are merged from the stored row before validation, so a payload that changes one of them is still validated against the rest of the saved configuration — raising late_threshold_seconds alone can therefore fail against the stored grace_seconds. The guard order is load-bearing: ownership first, then the payload parse, then every validation, and only then the pause write, so a request that ends in a 422 can never have silently paused the dead-man switch. Sending is_paused on its own returns { data: { id } } without re-reading the monitor; resuming grants one fresh schedule window so a stale pre-pause deadline cannot alert immediately. The same route serves PUT with identical semantics.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

Request Body schema: application/json
is_paused
boolean

Pause (true) or resume (false) the monitor. Parsed as a real boolean, so the string "false" RESUMES; a value that cannot be parsed is a 422. Resuming grants one fresh schedule window so a stale pre-pause deadline cannot alert immediately. When is_paused is the ONLY key in the body the pause is applied and the response is just { data: { id } } with no monitor re-read; sent alongside other fields it is applied only after every sibling field has validated, so a request that ends in a 422 can never have silently paused the dead-man switch.

name
string

Monitor display name; trimmed, 1 to 255 characters. Omitted means unchanged.

watches
string
Enum: "cron" "worker" "queue" "backup" "iot" "other"

What the job is. Labelling only. Omitted means unchanged.

schedule_type
string
Enum: "interval" "cron"

interval or cron. Changing it in either direction counts as a schedule change and recomputes the next expected ping for an armed monitor.

interval_seconds
integer

Expected seconds between pings, 30 to 7776000. A change recomputes expected_next_at for an armed monitor from the later of its last ping and now.

cron_expression
string

5-field cron expression (or one of the @hourly/@daily/@midnight/@weekly/@monthly/@yearly/@annually macros); validated whenever non-empty and mandatory in cron mode. A change recomputes expected_next_at for an armed monitor.

timezone
integer

config/time_zone.php id; 0 inherits the account timezone. Counts as a schedule change ONLY in cron mode — an interval schedule is self-referential, so recomputing there would push a dead job missed-ping incident out by a whole interval. In cron mode the next expected ping is recomputed immediately so an armed monitor does not keep the previous zone deadline. Same strict integer / all-digit-string shape rule as on create.

grace_seconds
integer

Seconds before a missed ping opens an incident, 0 to 2592000. Must be greater than or equal to late_threshold_seconds, compared against the MERGED values — so raising the threshold alone can fail against the stored grace.

late_threshold_seconds
integer

Lower bound of the in-grace late band, 0 to 2592000. Must not exceed grace_seconds.

runtime_limit_seconds
integer

Maximum permitted /start-to-success runtime in seconds, up to 604800. 0 turns the check off.

fail_alerts
boolean

Whether a /fail ping pages the recipients. Absent preserves the stored flag; the string "false" disables paging.

report_up
integer

Send the recovery notification. Stored as 0 only when the value casts to integer 0; absent preserves the stored flag.

escalation_policy_id
integer

Escalation policy to alert through; 0 alerts every recipient at once and a value above 0 must belong to this account. Absent preserves the stored binding.

branding_id
integer

Branding template; 0 is the standard theme and a value above 0 must belong to this account. Absent preserves the stored value.

notes
string

Operator note, trimmed and capped at 500 characters. Normalized only when the key is actually present; an absent key preserves the stored note.

(Array of integers or objects) or string

Replaces the alert recipients. Bare ids, typed recipient objects, or the sentinels "all" and "no_changes". An ABSENT key — or an explicit null — leaves the stored bindings untouched and skips the ownership check entirely.

groups
Array of integers

Replaces the monitor group memberships; every id must belong to this account. Absent leaves memberships unchanged. For a scoped team member the list is rewritten so their edit stays confined to their scope groups, while owner-assigned memberships outside that scope are preserved rather than orphaned.

Responses

Request samples

Content type
application/json
{
  • "is_paused": false,
  • "name": "Nightly invoice export",
  • "watches": "cron",
  • "schedule_type": "cron",
  • "interval_seconds": 300,
  • "cron_expression": "0 3 * * 1-5",
  • "timezone": 0,
  • "grace_seconds": 120,
  • "late_threshold_seconds": 10,
  • "runtime_limit_seconds": 0,
  • "fail_alerts": true,
  • "report_up": 1,
  • "escalation_policy_id": 0,
  • "branding_id": 0,
  • "notes": "Runs on cron-box-2; owner: billing team",
  • "contacts": [
    ],
  • "groups": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Regenerate the ping token

Mints a new ping token for the monitor and returns it with its ping URL. The old URL stops working the instant the write lands — the public ingest looks a monitor up by its token — so update the job before rotating, or the next ping will be lost and the monitor will alert. No request body is read.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

Responses

Response samples

Content type
application/json
{}

Send a test ping

Records a manual ping against the monitor so an integrator can confirm the plumbing without waiting for the real job. The signal type is fixed to manual and the user agent to a fixed dashboard label — nothing is read from the request body, and the caller IP is recorded as the source. A manual ping is deliberately non-arming: it shows up in the ping log and the live feed but never arms the monitor and never moves the next expected ping, so it cannot mask a job that has actually stopped running.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

List the ping log for a heartbeat monitor

Newest-first ping log for one monitor, read from the ClickHouse ping history and built for live-feed polling: pass back the newest id you hold as since_id to fetch only what is new. That filter is INCLUSIVE, so that a second ping landing in the same second is never lost — which means the newest row you already hold comes back again and an incremental poller MUST de-duplicate on id. A ClickHouse failure degrades to an empty rows array rather than a 5xx, so an empty page is not proof that no pings arrived.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

query Parameters
since_id
integer
Default: 0
Example: since_id=41270001756100000

Return only pings at or after the time part of this encoded ping id. Default 0 (no lower bound); negative values are floored to 0. De-duplicate on id — the boundary row is returned again.

limit
integer
Default: 50
Example: limit=50

Maximum rows to return. Default 50, clamped server-side to 1-200.

date_start
integer
Default: 0
Example: date_start=1755500000

Unix timestamp lower bound, inclusive. Default 0 = unbounded; negative values floored to 0.

date_end
integer
Default: 0
Example: date_end=1756100000

Unix timestamp upper bound, inclusive. Default 0 = unbounded; negative values floored to 0.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get the detail-page summary for a heartbeat monitor

Everything the monitor detail page needs in one payload: the stat-strip numbers, the 12-hour pulse strip, per-bucket received counts, the in-window incidents and the monitor itself. Give an explicit from/to window in unix seconds, or omit both and pass days for a rolling window; the window is clamped to now and capped at 92 days, and a longer request is silently trimmed to the most recent 92 days rather than rejected. Availability is derived from clipped incident downtime over the whole window and does NOT subtract maintenance. The late_pings key is ALWAYS an empty array here — this endpoint is polled every three seconds while a ping is overdue and skips the dedicated late-ping read — while the pings_late counter is unaffected.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

query Parameters
from
integer
Default: 0
Example: from=1755500000

Window start as a unix timestamp. Default 0. When both from and to are 0 or less the rolling days window is used instead. An out-of-order or non-positive from is replaced by seven days before the window end.

to
integer
Default: 0
Example: to=1756100000

Window end as a unix timestamp. Default 0. Clamped to now — a future value is pulled back to the current time.

days
integer
Default: 7
Example: days=7

Rolling window size in days, used ONLY when neither from nor to is given: the window becomes the last days*86400 seconds. Default 7; floored to a minimum of 1.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for a heartbeat monitor

Newest-first incident history for one monitor — missed pings, explicitly reported /fail runs and runtime overruns — in the formatted display shape shared by every monitor family per-monitor incident endpoint. Every time field here is a rendered STRING, not a timestamp. Window membership is half-open: an incident belongs to the window when it started before date_end AND was still open after date_start, so an incident that is still open always qualifies. metadata.total is the real uncapped count over the same window, independent of limit and offset, so it can drive pagination.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

query Parameters
limit
integer
Default: 50
Example: limit=50

Maximum incidents to return. Default 50, clamped server-side to 1-200.

offset
integer
Default: 0
Example: offset=0

Rows to skip, for pagination. Default 0; negative values are floored to 0.

date_start
integer
Default: 0
Example: date_start=1755500000

Unix timestamp: keep incidents that were still open after this instant. Default 0 = unbounded; negative values floored to 0.

date_end
integer
Default: 0
Example: date_end=1756100000

Unix timestamp: keep incidents that started strictly before this instant. Default 0 = unbounded; negative values floored to 0.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Delete a heartbeat incident

Permanently deletes one CLOSED incident record from the monitor history. The monitor currently open incident is refused with 409 incident_open so live alerting state cannot be erased out from under the missed-ping sweep — close it first by letting the job ping again. The lookup is bound to the monitor in the path, so an incident belonging to a different monitor answers 404 incident_not_found rather than being deleted.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4127

Monitor id

incidentId
required
integer\d+
Example: 90211

Incident id, as returned in error_id by GET /api/v2/heartbeat/{id}/incidents

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Blacklist Monitors

DNSBL reputation monitoring for your domain and its web / mail IPs.

List all blacklist monitors

Returns every blacklist monitor on the account, decorated exactly as the editor reads it but WITHOUT the contacts and groups keys — fetch a single monitor for those. The endpoint is unpaged: it reads no limit or offset, and metadata.total is simply the number of rows returned. Rows are ordered by name ascending, and an operator whose role is confined to monitor groups sees only the monitors inside that scope (an empty scope returns an empty list, not a 403).

Authorizations:
bearerAuth
query Parameters
search
string
Example: search=example.com

Case-insensitive substring filter applied to the monitor name and target. LIKE wildcards in the term are escaped, so "a_b" and "100%" match literally. Applied only when the key is present; there is no default.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a blacklist monitor

Creates a blacklist monitor and queues its baseline sweep immediately, so the first result lands within a minute rather than after a full sweep interval. Guards run in a fixed order — field validation, then the plan pool, then escalation policy, groups, branding and contact ownership, then the monitor-group scope rewrite — and nothing is written until all of them pass. The response is the whole created monitor read back through the same shape as GET /api/v2/blacklist/{id}, not a bare id. Note the recipient rule that catches integrators out: omitting contacts entirely binds every contact already on the account, but sending an empty list is an error.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Monitor display name. Trimmed, then required to be non-empty and at most 255 characters (name_invalid otherwise).

target
required
string

What to watch: a registrable domain or a public IPv4 address. It is normalized before it is stored (scheme, userinfo, port, path, query, fragment, a leading "www." and a trailing root dot are stripped; an IDN is lowered to punycode) and the normalized form is what later reads return. IPv6 literals are refused because no registry zone answers on IPv6, and an IP target must be publicly routable — private and reserved ranges, CGNAT 100.64/10, 192.0.0/24, TEST-NET-1/2/3, 198.18/15 and multicast 224/4 all give target_private.

extra_ips
Array of strings

Up to 5 dedicated sending IPv4 addresses swept alongside the target. Must be an array (extra_ips_invalid), at most 5 entries after de-duplication (extra_ips_too_many), each publicly routable IPv4 (extra_ips_invalid). On write the entries are trimmed and de-duplicated, any entry equal to the target is dropped, and the list is capped at 5. Omitting the field means an empty list.

sweep_interval
integer
Enum: 900 1800 3600

Seconds between sweeps. Only 900, 1800 and 3600 are accepted; anything else is sweep_interval_invalid. Defaults to 900 when omitted.

verify_checks
integer
Enum: 1 3 5

How many consecutive clean answers a listing needs before it counts as delisted. Only 1, 3 and 5 are accepted; anything else is verify_checks_invalid. Defaults to 3.

watch_web_ip
boolean

Whether a domain target checks its website IP (the A record) on the IP lists. Turn it off for a site behind a CDN or on shared hosting, whose IP is listed for other customers' traffic; the domain lists and the mail IP stay watched. Ignored for an IP target. Defaults to true.

object

Per-impact-tier configuration. At least one tier must stay enabled or the request is refused with tier_settings_all_disabled. Unrecognised input is normalized against the defaults (major enabled/critical, standard enabled/trouble, info enabled) and an unrecognised severity falls back to that tier default.

report_up
integer

Send the recovery (delisting) notification. 0 disables it; any other value, and omitting the field, means 1. There is deliberately no report_down field in this family — a listing is already a delayed signal, so DOWN alerts are queued due immediately and report_down is stored as 0.

escalation_policy_id
integer

Escalation policy the monitor alerts through; 0 (the default) alerts every recipient at once. A non-zero id must belong to the account or the request is refused with invalid_escalation_policy.

branding_id
integer

Branding template used for this monitor notification emails; 0 (the default) is the standard theme. A non-zero id must belong to the account, and a non-numeric value is refused with invalid_branding before the ownership comparison.

notes
string

Free-text operator note, plain text, trimmed and truncated to 500 characters. Shown on the incident page and included in alert emails and webhook payloads. Written only when the key is present.

(Array of integers or objects) or string

Alert recipients. Create-only semantics: an ABSENT or null key seeds the monitor with every contact already stored on the account, each bound as an individual contact, and the "no_changes" sentinel seeds the same way (a create has no stored list to preserve); an account that holds no contacts yet is seeded with nobody and the create still succeeds. A key that is present and EMPTY is refused instead — a monitor with no recipients alerts nobody. Every team, operator, user or contact referenced must belong to the account.

Array of integers or integer

Monitor-group ids this monitor belongs to; every id must belong to the account. Written only when the key is present. For an operator whose role is confined to monitor groups the submitted list is rewritten so the new monitor always lands in one of their scope groups and can never be created invisible to its author; an unrestricted actor keeps the submitted ids byte for byte.

Responses

Request samples

Content type
application/json
{
  • "name": "Corporate mail",
  • "target": "example.com",
  • "extra_ips": [
    ],
  • "sweep_interval": 900,
  • "verify_checks": 3,
  • "watch_web_ip": true,
  • "tier_settings": {
    },
  • "report_up": 1,
  • "escalation_policy_id": 0,
  • "branding_id": 0,
  • "notes": "Shared IP with the marketing mailer",
  • "contacts": [
    ],
  • "groups": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a blacklist monitor

Returns one blacklist monitor in the shape the editor prefills from: the decorated row plus its contact bindings and the ids of the monitor groups it belongs to. There is no metadata key on this response. A monitor that does not exist, belongs to another account, or falls outside the acting operator monitor-group scope all answer with the same 404.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update a blacklist monitor (alias of PATCH)

Alias of PATCH /api/v2/blacklist/{id}, kept for client compatibility — one route declares both verbs and they resolve to the same handler. Despite the PUT verb the semantics are PARTIAL, not replace: omitted fields keep their stored values and no field is reset to a create default. Every field is optional and an omitted field keeps its stored value. is_paused may be sent on its own for a bare pause/resume, which answers with just the monitor id, or combined with configuration fields — in that case the whole request is validated before the pause is applied, so a 422 leaves the monitor completely untouched. Changing the watch configuration (target, dedicated IPs or tiers) pulls the next sweep forward to now so the change takes effect within a minute; changing the target additionally clears the discovered web and mail addresses and silently force-closes the listing episodes that belonged to the old target, recomputing the counters and closing the open incident without a recovery alert when nothing alertable is left.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

Request Body schema: application/json
boolean or integer

Truthy pauses the monitor, falsy — including an explicit null — resumes it. Sent ALONE it short-circuits and answers {"data":{"id":…}} without touching anything else; sent alongside other fields it is applied only after every other guard has passed, so a 422 leaves the monitor completely untouched. Update-only: the create endpoint does not read it.

name
string

Monitor display name; trimmed, non-empty, at most 255 characters. Absent keeps the stored name.

target
string

Domain or public IPv4 address to watch, with the same normalization and public-address rule as on create. Absent keeps the stored target. Changing it clears the discovered web IP, MX host, mail IP and the last raw sweep — the IPv6 and full-RRset copies are left for the next sweep to overwrite — and force-closes every active listing episode silently (no recovery alert), because those episodes belonged to the old target.

extra_ips
Array of strings

Replaces the stored dedicated-IP list wholesale — it is not merged. Same rules as on create: an array of at most 5 publicly routable IPv4 addresses, de-duplicated, with any entry equal to the target dropped. Absent leaves the stored list unchanged.

sweep_interval
integer
Enum: 900 1800 3600

Seconds between sweeps — 900, 1800 or 3600. Absent leaves it unchanged.

verify_checks
integer
Enum: 1 3 5

Consecutive clean answers before a listing counts as delisted — 1, 3 or 5. Absent leaves it unchanged.

watch_web_ip
boolean

Whether a domain target checks its website IP on the IP lists. Turning it off closes any open website-IP listing without a delisting alert. Ignored for an IP target. Absent leaves it unchanged.

object

Replaces the stored tier configuration wholesale. At least one tier must stay enabled or the request is refused with tier_settings_all_disabled. Unrecognised input is normalized against the defaults (major enabled/critical, standard enabled/trouble, info enabled) and an unrecognised severity falls back to that tier default. Disabling a tier silently closes that tier active listing episodes; a surviving listing severity may only rank up, so an unrelated edit never quietly downgrades a critical listing, and PBL answers are always forced back to the informational tier.

report_up
integer

Send the recovery (delisting) notification: 0 disables it, any other value enables it. Absent leaves the stored value in place. There is no report_down field in this family.

escalation_policy_id
integer

Escalation policy to alert through; 0 alerts every recipient at once. A non-zero id must belong to the account. Absent leaves it unchanged.

branding_id
integer

Branding template id; 0 is the standard theme. A non-zero id must belong to the account and a non-numeric value is refused. Absent leaves it unchanged.

notes
string

Free-text operator note, trimmed and capped at 500 characters. Written only when the key is present, so an absent key preserves the stored note while an empty string clears it.

(Array of integers or objects) or string

Replaces the monitor alert recipients. Same entry shapes as on create, and "all" / "no_changes" are accepted sentinels. An absent key, or an explicit null, leaves the stored recipients alone — both the ownership guard and the write are skipped. Unlike create, an empty array here is rejected rather than auto-seeded.

Array of integers or integer

Replaces the monitor group memberships; every id must belong to the account. Absent leaves them unchanged. For an operator whose role is confined to monitor groups the list is rewritten so their edits stay inside their scope groups while owner-assigned memberships outside that scope are preserved rather than orphaned.

Responses

Request samples

Content type
application/json
{
  • "is_paused": true,
  • "name": "Corporate mail",
  • "target": "example.com",
  • "extra_ips": [
    ],
  • "sweep_interval": 1800,
  • "verify_checks": 3,
  • "watch_web_ip": false,
  • "tier_settings": {
    },
  • "report_up": 1,
  • "escalation_policy_id": 0,
  • "branding_id": 0,
  • "notes": "Shared IP with the marketing mailer",
  • "contacts": [
    ],
  • "groups": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a blacklist monitor

Permanently deletes the monitor and everything hanging off it: the monitor row, its listing episodes, contact bindings, incidents, maintenance and pause audit rows, group memberships and the per-sweep history in ClickHouse. The deletion is recorded in the account activity log. This answers 200 with a body, not 204, and there is no undo.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update a blacklist monitor

Partial update: every field is optional and an omitted field keeps its stored value. is_paused may be sent on its own for a bare pause/resume, which answers with just the monitor id, or combined with configuration fields — in that case the whole request is validated before the pause is applied, so a 422 leaves the monitor completely untouched. Changing the watch configuration (target, dedicated IPs or tiers) pulls the next sweep forward to now so the change takes effect within a minute; changing the target additionally clears the discovered web and mail addresses and silently force-closes the listing episodes that belonged to the old target, recomputing the counters and closing the open incident without a recovery alert when nothing alertable is left.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

Request Body schema: application/json
boolean or integer

Truthy pauses the monitor, falsy — including an explicit null — resumes it. Sent ALONE it short-circuits and answers {"data":{"id":…}} without touching anything else; sent alongside other fields it is applied only after every other guard has passed, so a 422 leaves the monitor completely untouched. Update-only: the create endpoint does not read it.

name
string

Monitor display name; trimmed, non-empty, at most 255 characters. Absent keeps the stored name.

target
string

Domain or public IPv4 address to watch, with the same normalization and public-address rule as on create. Absent keeps the stored target. Changing it clears the discovered web IP, MX host, mail IP and the last raw sweep — the IPv6 and full-RRset copies are left for the next sweep to overwrite — and force-closes every active listing episode silently (no recovery alert), because those episodes belonged to the old target.

extra_ips
Array of strings

Replaces the stored dedicated-IP list wholesale — it is not merged. Same rules as on create: an array of at most 5 publicly routable IPv4 addresses, de-duplicated, with any entry equal to the target dropped. Absent leaves the stored list unchanged.

sweep_interval
integer
Enum: 900 1800 3600

Seconds between sweeps — 900, 1800 or 3600. Absent leaves it unchanged.

verify_checks
integer
Enum: 1 3 5

Consecutive clean answers before a listing counts as delisted — 1, 3 or 5. Absent leaves it unchanged.

watch_web_ip
boolean

Whether a domain target checks its website IP on the IP lists. Turning it off closes any open website-IP listing without a delisting alert. Ignored for an IP target. Absent leaves it unchanged.

object

Replaces the stored tier configuration wholesale. At least one tier must stay enabled or the request is refused with tier_settings_all_disabled. Unrecognised input is normalized against the defaults (major enabled/critical, standard enabled/trouble, info enabled) and an unrecognised severity falls back to that tier default. Disabling a tier silently closes that tier active listing episodes; a surviving listing severity may only rank up, so an unrelated edit never quietly downgrades a critical listing, and PBL answers are always forced back to the informational tier.

report_up
integer

Send the recovery (delisting) notification: 0 disables it, any other value enables it. Absent leaves the stored value in place. There is no report_down field in this family.

escalation_policy_id
integer

Escalation policy to alert through; 0 alerts every recipient at once. A non-zero id must belong to the account. Absent leaves it unchanged.

branding_id
integer

Branding template id; 0 is the standard theme. A non-zero id must belong to the account and a non-numeric value is refused. Absent leaves it unchanged.

notes
string

Free-text operator note, trimmed and capped at 500 characters. Written only when the key is present, so an absent key preserves the stored note while an empty string clears it.

(Array of integers or objects) or string

Replaces the monitor alert recipients. Same entry shapes as on create, and "all" / "no_changes" are accepted sentinels. An absent key, or an explicit null, leaves the stored recipients alone — both the ownership guard and the write are skipped. Unlike create, an empty array here is rejected rather than auto-seeded.

Array of integers or integer

Replaces the monitor group memberships; every id must belong to the account. Absent leaves them unchanged. For an operator whose role is confined to monitor groups the list is rewritten so their edits stay inside their scope groups while owner-assigned memberships outside that scope are preserved rather than orphaned.

Responses

Request samples

Content type
application/json
{
  • "is_paused": true,
  • "name": "Corporate mail",
  • "target": "example.com",
  • "extra_ips": [
    ],
  • "sweep_interval": 1800,
  • "verify_checks": 3,
  • "watch_web_ip": false,
  • "tier_settings": {
    },
  • "report_up": 1,
  • "escalation_policy_id": 0,
  • "branding_id": 0,
  • "notes": "Shared IP with the marketing mailer",
  • "contacts": [
    ],
  • "groups": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Detail-page summary

Returns the whole detail page in one payload: the decorated monitor, its listing episodes, the last sweep decoded answers, the newest incidents, the registry of zones the enabled tiers cover and the watched-resource slots. The control panel re-fetches this every 30 seconds, so the resolved listing history is capped at the 200 newest while active episodes are never truncated — truncating an episode that has been open for months would paint a listed cell clean while the same payload counters said listed. The monitor object here carries dqs_configured but no contacts or groups; the incidents are raw rows rather than the formatted shape the incidents endpoint returns.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Re-check all lists now

Queues an on-demand sweep by pulling the monitor next_check forward to now; the per-minute sweep cron picks it up on its next tick, so results land within a minute rather than immediately in this response. The request body is ignored entirely. A monitor the sweep would skip — suspended by the plan pool, paused, or in maintenance — is refused with a 409 rather than being told a recheck was queued, and the endpoint is rate limited to 10 rechecks per minute per account because each one fans a full registry sweep out across the probe fleet.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

List incidents for a blacklist monitor

Newest-first incident history — listing alerts and their recoveries — formatted into the display shape the shared incidents card consumes, so every value is a string except error_id. Paging is clamped by the family rather than the caller: limit is forced into 1..200 and defaults to 50, so a huge limit cannot return everything and a negative one cannot produce an invalid query. The date window is half-open and overlap-based: an incident counts when it started before date_end AND was still open after date_start, and a zero bound means unbounded on that side.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

query Parameters
limit
integer [ 1 .. 200 ]
Default: 50
Example: limit=50

Page size. Read only when the key is present; clamped to 1..200 with a default of 50.

offset
integer
Default: 0
Example: offset=0

Rows to skip, floored at 0.

date_start
integer
Default: 0
Example: date_start=1756000000

Unix timestamp lower bound, floored at 0. An incident is in the window when it was still open after this instant — time_ended is 0 (ongoing) or greater than date_start. 0, the default, means unbounded.

date_end
integer
Default: 0
Example: date_end=1756200000

Unix timestamp upper bound, floored at 0. An incident is in the window when time_started is less than date_end. 0, the default, means unbounded.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Per-sweep check log

Newest-first page of the append-only per-sweep check log: one row per sweep with its timestamp, fan-out duration, queried-zone count and what it found. Paging is clamped by the family, not the caller — limit is forced into 1..100 and defaults to 20 — and metadata.total is the real number of sweeps stored, independent of the page. Rows are kept for the account plan retention, like every other family check history, so old timestamps eventually disappear.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

query Parameters
limit
integer [ 1 .. 100 ]
Default: 20
Example: limit=20

Page size. Read only when the key is present; clamped to 1..100 with a default of 20.

offset
integer
Default: 0
Example: offset=0

Rows to skip, floored at 0.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

One sweep in full

Returns a single sweep counters plus the per-list answers behind them: which zone, which watched address, what it replied and what that decodes to. Only answers that carry information are stored, so clean answers are never listed individually — they are the difference between lists_checked and the cells returned, exposed as clean. cells_source states the provenance of the per-list view, because a sweep older than per-list storage can only have its listings rebuilt from the listing-episode windows and can never name the zones that errored. The {time} segment must be the exact time value from the sweep log.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

time
required
integer\d+
Example: 1756100000

Exact unix timestamp of the sweep, as returned in the time field of GET /api/v2/blacklist/{id}/logs

Responses

Response samples

Content type
application/json
{
  • "data": {
    },
  • "metadata": {
    }
}

Delete a blacklist incident

Deletes one CLOSED incident record from the monitor history. The currently open incident cannot be deleted and answers 409; the check runs twice, once against the monitor incident pointer and once against the stored end timestamp, so a race cannot slip an open incident through. Deleting an incident removes the record only — it does not touch the listing episodes or the sweep log behind it.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4102

Blacklist monitor id

incidentId
required
integer\d+
Example: 90211

Incident id, as returned in the error_id field of GET /api/v2/blacklist/{id}/incidents

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Monitors

Cross-type monitor actions: copy, pause and resume.

Pause a single monitor

Pauses a single monitor by type and ID. Creates a pause history entry.

Authorizations:
bearerAuth
path Parameters
type
required
string
Enum: "uptime" "ssl" "domain" "virus" "fpl" "transaction" "rum" "heartbeat" "blacklist" "dns" "api"

Monitor type

id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Resume a single monitor

Resumes a single paused monitor by type and ID. Closes the pause history entry.

Authorizations:
bearerAuth
path Parameters
type
required
string
Enum: "uptime" "ssl" "domain" "virus" "fpl" "transaction" "rum" "heartbeat" "blacklist" "dns" "api"

Monitor type

id
required
integer\d+

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Copy a monitor

Creates a copy of an existing monitor. Currently only supported for uptime monitors.

Authorizations:
bearerAuth
path Parameters
type
required
string
Value: "uptime"

Monitor type (only "uptime" supported)

id
required
integer\d+

Monitor ID to copy

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Groups

Monitor groups — the group IDs the monitor endpoints' groups field expects.

List monitor groups

Returns every monitor group on your account — including groups that currently hold no monitors — with the IDs the monitor endpoints' groups field expects. Ordered by id ascending (creation order). Results are not paginated and take no query parameters. Group-scoped operators only see the groups their access is limited to, and metadata.total counts what was returned after that filter, not the account total.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a monitor group

Creates a monitor group. Both name and color are required. The name is stored with HTML tags stripped and surrounding whitespace removed, so what you send back on a later read may differ from what you sent. Group-scoped operators cannot create groups: a new group is nobody's scope until the owner grants it, so it would vanish from the creator's own list. There is no per-account group limit. A form-encoded body (application/x-www-form-urlencoded) is accepted as well as JSON; when both are present the form fields win. The response carries the new ID only — read it back with GET /api/v2/groups if you need the stored name and color.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string <= 100 characters

Group name. The 100 limit is measured in bytes, so a name of multi-byte characters fits fewer of them, and it is checked before tags are stripped.

color
required
string^#[0-9A-Fa-f]{6}$

Six-digit HEX color with a leading #. Three-digit shorthand and named colors are rejected.

Responses

Request samples

Content type
application/json
{
  • "name": "Production",
  • "color": "#e66465"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a monitor group

Deletes a monitor group and removes its monitor associations (the monitors themselves are kept and keep running). Group-mode maintenance windows stop covering it, and any monitor that was in maintenance only because of this group leaves maintenance immediately — it resumes checks and alerts within the current occurrence. The deletion is not reversible and takes no request body.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 18

Group ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update a monitor group

Partially updates a monitor group: only the supplied fields change, and an omitted field keeps its stored value. Omit a field to keep it — sending it as null is rejected with 400 rather than treated as "unchanged", and neither field can be cleared. Both fields are validated by the same rules as create, and the name is stripped of HTML tags and trimmed before it is stored. Groups outside a group-scoped operator's access respond 404, indistinguishable from ones that do not exist. A form-encoded body is accepted as well as JSON; when both are present the form fields win. Sending an empty body is a no-op that still answers 200.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 18

Group ID

Request Body schema: application/json
name
string <= 100 characters

New group name. The 100 limit is measured in bytes.

color
string^#[0-9A-Fa-f]{6}$

New six-digit HEX color with a leading #

Responses

Request samples

Content type
application/json
{
  • "name": "Production EU",
  • "color": "#5454e6"
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Add or remove monitors in a group

Adds and removes many monitors to and from one group in a single transaction. Adding is additive: a monitor keeps every other group it belongs to. A monitor that is already a member (in add) or not a member (in remove) is a no-op and is not reported. Every referenced monitor must exist on your account; one unknown ID answers 404 and nothing is written. Group-scoped operators can only change their own groups and their own monitors: a monitor outside their access answers the same 404. The response lists in skipped what they could not change: last_scoped_group (removing it would leave the monitor in none of their groups, so it would disappear from their view). type takes the public monitor type names (uptime, speed, transaction, rum, ssl, domain, virus, server, heartbeat, blacklist, dns, api). Each list holds at most 1000 entries, and a monitor cannot appear in both.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 18

Group ID

Request Body schema: application/json
Array of objects <= 1000 items

Monitors to add to the group

Array of objects <= 1000 items

Monitors to remove from the group

Responses

Request samples

Content type
application/json
{
  • "add": [
    ],
  • "remove": [
    ]
}

Response samples

Content type
application/json
{
  • "added": 52,
  • "removed": 3,
  • "skipped": [
    ]
}

Monitor Templates

Monitor settings saved from an existing monitor and reused when creating new ones.

List monitor templates

Returns the authenticated account's saved monitor templates, newest first (id descending), each with its decoded create-payload settings. Unlike every monitor list in this API the response has NO metadata envelope: the body is {"data": [...]} and nothing else, so there is no metadata.total to read — use the length of data. The list is never paginated and accepts no query parameters. Templates saved from a monitor family that has since been retired (transaction) are filtered out of this list and can never reappear in it, yet they still count towards the 100-template account cap — an account can therefore be refused a new template while showing fewer than 100 here. They remain reachable by id on the update, delete and used endpoints, so a hidden row can still be deleted to free its slot. A group-scoped operator only receives templates whose source monitor is inside their scope; the check fails closed, so a template with no resolvable source monitor (source_monitor_id 0, or a monitor that has since been deleted) is invisible to them.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Save a monitor as a template

Stores a named snapshot of a monitor's create payload. monitor_type is the monitor family key; settings is the JSON body that family's create endpoint accepts. The response carries the new ID only — the created resource is not echoed back and no Location header is set; read it back with GET /api/v2/monitor-templates. Creating a monitor FROM a template happens client-side: merge the new name and URL/IP over settings and post the result to POST /api/v2/{monitor_type}, then call POST /api/v2/monitor-templates/{id}/used. source_monitor_id is optional here but load-bearing for team accounts: it is the only key group-scope enforcement reads, and it fails closed, so a template saved without it (or pointing at a monitor that is later deleted) is invisible to every group-scoped operator — silently absent from their list (200, one entry shorter) and answered 404 by the update, delete and used endpoints. An account may hold at most 100 templates, counting templates of retired families that the list endpoint no longer returns; those rows are still deletable by id.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string <= 190 characters

Required. 1..190 characters, unique on the account. The value is trimmed before both the blank check and the uniqueness check, so " Production" collides with an existing "Production". A name made only of markup (for example <b></b>) is rejected as blank.

description
string or null <= 255 characters

Optional free-text note, measured after trimming and stored trimmed. Over 255 characters is rejected rather than truncated. Omitted, null or any non-string value stores an empty description.

monitor_type
required
string
Enum: "uptime" "ssl" "fpl" "domain" "virus" "rum" "heartbeat" "blacklist" "dns" "api"

Required. The monitor family this snapshot belongs to; case-insensitive and trimmed. server (agent-install flow) and transaction (product decision) are not templatable and are rejected.

required
object

Required. The create payload to snapshot — the exact JSON body POST /api/v2/{monitor_type} accepts for the chosen family, whose keys are documented on that family's create endpoint. This API treats it as an opaque per-type blob: it is stored verbatim and never validated key by key, so a payload the family would reject is still accepted here. It must be a non-empty JSON object (a non-empty JSON array is also accepted and stored verbatim; {}, [] and any scalar are rejected) and may not exceed 2 MB (MAX_SETTINGS_BYTES = 2097152 bytes, measured on the re-encoded payload; an API-monitor payload can approach 1 MB). Do not put secrets in it: settings are built from detail reads, which mask HTTP Basic Auth passwords and API-monitor secret variables.

source_monitor_id
integer
Default: 0

Optional. ID of the monitor this payload was read from. Never rejected: the value is cast to an integer and floored at 0 (a negative id and a non-numeric string both store 0), and an ID that does not name one of your monitors is stored as sent. It is not checked against your account here, only when group scope is evaluated on a later read — where 0 and unresolvable IDs both hide the template from group-scoped operators (see the endpoint description).

source_monitor_name
string <= 190 characters

Optional. Display name of the source monitor, stored as a snapshot and never kept in sync. Trimmed and silently truncated to 190 characters rather than rejected.

Responses

Request samples

Content type
application/json
{
  • "name": "Production HTTPS check",
  • "description": "Five-minute uptime check with the standard on-call contacts",
  • "monitor_type": "uptime",
  • "settings": {
    },
  • "source_monitor_id": 8241,
  • "source_monitor_name": "example.com — landing"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a monitor template

Deletes an owned template and frees one slot against the 100-template account cap. Monitors already created from it are untouched — templates are snapshots, not live configuration. Responds 404 when the template does not exist, is not owned by the account, or is outside a group-scoped operator's scope; the three are deliberately indistinguishable. The success body is {"status":"ok"} — note the literal ok, NOT the success that the update and used endpoints in this same tag return. A shared status === "success" check will read every successful delete as a failure.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 41

Template ID

Responses

Response samples

Content type
application/json
{
  • "status": "ok"
}

Update a monitor template

Partially updates an owned template's name and/or description. Responds 404 when the template does not exist, is not owned by the account, or is outside a group-scoped operator's scope — the three are deliberately indistinguishable. settings and monitor_type are immutable (templates are snapshots) and are IGNORED rather than rejected: sending them returns 200 and changes nothing, so a client that expects an error for an unsupported edit will never see one. To change a snapshot, create a new template and delete the old one. Presence, not value, decides what is written. A key that is absent is preserved; a key that is present is applied. {"description": null} therefore CLEARS the description (any non-string value does the same, storing an empty string), while omitting description leaves it untouched. {"name": null} is not the equivalent shortcut — it is rejected with invalid_template_name. A request that carries no recognised key — an empty body, or only settings/monitor_type/unknown keys — returns 200 {"status":"success"} having written nothing, not even updated_at, and records no entry in the account activity log. Success here is indistinguishable from a silent no-op, so verify the change with GET /api/v2/monitor-templates rather than trusting the status.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 41

Template ID

Request Body schema: application/json
name
string <= 190 characters

New name: 1..190 characters, unique on the account (the template's own row is excluded from the uniqueness check, so re-sending the current name is allowed). Trimmed before both the blank and the uniqueness check. Markup-only names are rejected. Omit to keep the current name; null is rejected, not a clear.

description
string or null <= 255 characters

New note, up to 255 characters measured after trimming. Omit to keep the current description; send null (or any non-string) to CLEAR it to an empty string.

Responses

Request samples

Content type
application/json
{
  • "name": "Production HTTPS check",
  • "description": "Five-minute uptime check with the standard on-call contacts"
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Record a template use

Increments the template's times_used counter by one and stamps last_used_at with the current time. Call it after a monitor has been successfully created from the template through POST /api/v2/{monitor_type}; the control panel does exactly this. Bookkeeping only — it creates nothing, changes no monitor, and does not move updated_at. It takes no request body, and any body sent is ignored. It is not idempotent: each call adds one, so a retried call double-counts. The response does not return the counter it just incremented; read times_used back from GET /api/v2/monitor-templates. Responds 404 when the template does not exist, is not owned by the account, or is outside a group-scoped operator's scope.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 41

Template ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Locations

Monitoring checkpoint locations (probes) used when scoping monitors.

List monitoring locations (probes) grouped by region

Returns the full catalogue of monitoring checkpoint probes available to the account, organised into geographic regions; each probe lists its ID, city, country, ISO country code and IP. Use these probe IDs when creating or scoping monitors to choose which locations run the checks.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "regions": [
    ]
}

Location Profiles

Reusable, named sets of monitoring locations that can be applied to monitors in bulk.

List location profiles

Returns the authenticated account's saved location profiles together with the seven code-defined built-in profiles (Europe, North America, Asia, Middle East & Africa, South America, Oceania, EU/GDPR). Every profile carries its RESOLVED probe-id list, not its stored rule alone.

The payload is not wrapped in data: saved profiles arrive under profiles (ordered by id ascending) and built-ins under builtins. The two lists carry the same fields but different id types — a saved profile's id is an integer, a built-in's id is the string builtin:<key>. Both forms are accepted by POST /location-profiles/{id}/apply and by the location_profile field on the monitor write endpoints.

in_use_count is a state match, not a provenance record: it counts the account's monitors whose current probes column resolves to exactly this profile's probe set, across all six location-capable families (uptime, speed, ssl, transaction, api, dns). A monitor hand-picked to the same probes is therefore counted, and a monitor the profile really was applied to stops being counted once its probes are edited. Built-ins always report 0. A profile of kind all — and any profile whose selection resolves to nothing — shares the "all probes" signature, so it reports the count of every default-location monitor on the account.

rule is an object only on kind rule profiles; on static and all profiles the empty rule serialises as an empty array [].

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "profiles": [
    ],
  • "builtins": [
    ]
}

Create a location profile

Creates a profile owned by the authenticated account. name is the only required field; kind defaults to static.

kind static takes probes — a list of probe ids. kind rule takes rule — regions and/or countries, matched with OR (a probe is selected if its region is listed or its country is listed), so an empty rule selects nothing. kind all needs neither and means every probe. An unrecognised kind is silently coerced to static rather than rejected.

A non-all profile must resolve to at least 6 probes or the request is rejected with too_few_locations. That gate runs against the ids as submitted; storage then intersects a static list with the live probe catalogue and drops ids that are not real probes, so a request made entirely of non-existent ids passes the gate, is created, and resolves to an empty list afterwards. Send ids taken from GET /api/v2/locations.

Values are normalised on write: name is trimmed and has markup stripped, region ids are lower-cased, country codes upper-cased, probe ids de-duplicated and sorted ascending, and a color that is not a six-digit HEX string is stored as empty. probes is only persisted for kind static and rule only for kind rule — the other columns are cleared.

Returns the new id only; call GET /location-profiles to read the resolved profile back.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string <= 100 characters

Profile name, 1..100 characters. A name that is blank, or that consists only of markup, is rejected.

kind
string
Default: "static"
Enum: "static" "rule" "all"

How the probe list is derived. Anything outside the enum is coerced to static.

probes
Array of integers

Probe ids for kind static. Ignored for rule and all. The minimum-6 gate counts the DISTINCT positive ids as submitted — it does not check them against the live fleet — while storage keeps only ids that are real probes, so send at least 6 ids taken from GET /api/v2/locations.

object

Selection rule for kind rule. Ignored for static and all. Regions OR countries — both lists may be supplied and a probe matching either is selected.

color
string

Six-digit HEX colour used by the control panel. Anything else is stored as an empty string.

Responses

Request samples

Content type
application/json
{
  • "name": "EU core",
  • "kind": "static",
  • "probes": [
    ],
  • "rule": {
    },
  • "color": "#1d4ed8"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a location profile

Deletes a profile owned by the authenticated account and reaps the provenance links that recorded which monitors it was applied to. Built-ins cannot be deleted.

Monitors are not changed: each keeps the probe set it is currently checking from, it simply stops being attributed to a profile. A profile that does not exist, or belongs to another account, responds 404.

Note the success literal: this operation returns status: "ok", while create and update return status: "success".

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 42

Saved profile id. Built-in ids are not accepted here.

Responses

Response samples

Content type
application/json
{
  • "status": "ok"
}

Update a location profile

Partially updates a profile owned by the authenticated account: only the keys present in the body are written, everything else keeps its stored value. Built-ins cannot be updated. A profile that does not exist, or belongs to another account, responds 404.

The resulting (kind, probes, rule) triplet is re-validated as a whole, so the minimum-6 rule is enforced against what would actually be stored — changing kind alone can therefore fail. Supplying kind also recomputes the stored probes and rule columns from the existing values under the new kind (switching to all clears both; switching to rule clears probes).

Editing the probe set re-points live monitors. A saved profile is a live template: when the resolved probe set changes, the new set is written into the probes column of every monitor on the account — across all six location-capable families — whose current probe set matches the profile's previous resolved set. That is a state match, not a provenance match, so a monitor hand-picked to those same probes is rewritten too even though this profile was never applied to it. The propagation is skipped when the previous set was the "all probes" sentinel. The response reports no count of what was rewritten. DNS monitors are updated by raw column write on this path, so they do not get the rotation-cursor and sweep-lock reset that the apply endpoint performs.

probes and rule are only honoured as arrays. A value that is present but is neither an array nor null (a string, a number, false) clears the stored column even though validation ran against the previous value; an explicit null is treated as "not supplied" and keeps the stored value.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 42

Saved profile id. Built-in ids are not accepted here.

Request Body schema: application/json
name
string <= 100 characters

New name, 1..100 characters. Trimmed and stripped of markup on write; blank or markup-only is rejected.

kind
string
Enum: "static" "rule" "all"

New kind. Anything outside the enum is coerced to static. Supplying it recomputes the stored probes/rule columns.

probes
Array of integers

Full replacement probe-id list for kind static. The minimum-6 gate counts the DISTINCT positive ids as submitted; ids that are not live probes are then dropped at storage.

object

Full replacement rule for kind rule. Regions OR countries — a probe matching either list is selected.

color
string

Six-digit HEX colour. Anything else is stored as an empty string. Not validated by this operation — only normalised.

Responses

Request samples

Content type
application/json
{
  • "name": "EU core (GDPR)",
  • "kind": "rule",
  • "probes": [
    ],
  • "rule": {
    },
  • "color": "#4338ca"
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Apply a location profile to monitors

Resolves the profile — a saved one by numeric id, or a built-in via builtin:<key> — to its probe list, enforces the minimum-6 rule, and writes that selection into each listed monitor's probes column. Every monitor is ownership-checked, and each one also gets a provenance link so the monitor editor can show which profile was applied.

For uptime, speed, ssl, transaction and api monitors the write is byte-identical to a manual hand-pick (kind all stores the "all probes" sentinel; otherwise a sorted JSON integer list). DNS is not identical: it is routed through the DNS family manager, which additionally resets the vantage rotation cursor, pulls the next sweep forward, drops any sweep lease held against the old pool, and applies a second, stricter floor counting only DNS-capable probes. A profile that cleared the profile-level minimum can therefore still fail for its DNS targets alone.

Partial failure is reported inside a 200. The response always carries one result entry per submitted monitor, in request order, and the HTTP status is 200 even when every entry failed — including the whole-profile failure where the profile itself resolves to fewer than 6 probes, in which case every entry reports too_few_locations and nothing is written. Inspect data.results[].ok; do not infer success from the status code.

Re-applying a profile a monitor already uses is a success, not a no-op failure.

Authorizations:
bearerAuth
path Parameters
id
required
string^(\d+|builtin:[a-z-]+)$
Example: builtin:eu-gdpr

A saved profile id (42) or a built-in id (builtin:europe, builtin:northamerica, builtin:asia, builtin:middleeast-africa, builtin:southamerica, builtin:oceania, builtin:eu-gdpr)

Request Body schema: application/json
required
Array of objects [ 1 .. 500 ] items

Targets to rebind. At least one, at most 500 per request.

Array ([ 1 .. 500 ] items)
id
required
integer

Monitor id, within the monitor family named by type

type
required
string
Enum: "uptime" "speed" "ssl" "transaction" "api" "dns"

Monitor family. Anything else fails that entry with invalid_monitor_type.

Responses

Request samples

Content type
application/json
{
  • "monitors": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Incidents

Active and historical incidents across all monitor types.

List active incidents

Returns a list of currently active (ongoing) incidents across all monitor types. Supports filtering by groups or individual monitors. Monitors in a running maintenance window are never active incidents; the ungrouped ones whose down or degraded state a window is holding are listed separately in maintenance[] (same account, scope and filters), and they count neither in data nor in metadata.total.

Authorizations:
bearerAuth
query Parameters
all
boolean
Default: true

Show all monitors (default true)

groups[]
Array of integers

Filter by group IDs

monitors[uptime][]
Array of integers

Filter by specific uptime monitor IDs

monitors[ssl][]
Array of integers

Filter by specific SSL monitor IDs

monitors[domain][]
Array of integers

Filter by specific domain monitor IDs

monitors[fpl][]
Array of integers

Filter by specific speed (full page load) monitor IDs. Note: the type key for speed monitors is "fpl".

monitors[transaction][]
Array of integers

Filter by specific transaction monitor IDs

monitors[virus][]
Array of integers

Filter by specific virus monitor IDs

monitors[rum][]
Array of integers

Filter by specific RUM monitor IDs

monitors[server][]
Array of integers

Filter by specific server monitor IDs

monitors[heartbeat][]
Array of integers

Filter by specific heartbeat monitor IDs

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "maintenance": [
    ],
  • "metadata": {
    }
}

List incident history

Returns a paginated history of resolved and ongoing incidents across all monitor types within the specified date range, newest first. With pin_ongoing=1, every ongoing incident is listed first on page 1 and page and limit page the resolved incidents after them.

Authorizations:
bearerAuth
query Parameters
date_start
string

Start date: Unix timestamp, or YYYYMMDD read as that day's midnight in the account timezone. Defaults to account-zone midnight six days ago (the last 7 days including today)

date_end
string

End date: Unix timestamp, or YYYYMMDD read as the last second of that day in the account timezone (now when it is today). Defaults to now

groups[]
Array of integers

Filter by monitor group IDs: the incidents of every monitor in the groups. Combined with monitors[] as a union.

monitors[uptime][]
Array of integers

Filter by specific uptime monitor IDs

monitors[ssl][]
Array of integers

Filter by specific SSL monitor IDs

monitors[domain][]
Array of integers

Filter by specific domain monitor IDs

monitors[fpl][]
Array of integers

Filter by specific speed (full page load) monitor IDs. Note: the type key for speed monitors is "fpl".

monitors[transaction][]
Array of integers

Filter by specific transaction monitor IDs

monitors[virus][]
Array of integers

Filter by specific virus monitor IDs

monitors[rum][]
Array of integers

Filter by specific RUM monitor IDs

monitors[server][]
Array of integers

Filter by specific server monitor IDs

monitors[heartbeat][]
Array of integers

Filter by specific heartbeat monitor IDs

monitors[api][]
Array of integers

Filter by specific API monitor IDs (every other family key, such as dns and blacklist, works the same way)

q
string

Search: keeps incidents whose monitor name or error text contains this text (case-insensitive)

type
string
Default: "all"

Monitor type filter: a type code (uptime, ssl, domain, fpl or speed, ...), several comma-separated, or "all"

status
string
Default: "all"
Enum: "all" "ongoing" "resolved"

Status filter: all, ongoing (not ended) or resolved

page
integer
Default: 1

Page number (default 1)

limit
integer
Default: 20

Results per page (default 20)

pin_ongoing
integer
Default: 0
Enum: 0 1

Send 1 to list every ongoing incident first on page 1, ahead of the resolved incidents, which page and limit then page. Without it, ongoing and resolved incidents are paged together, newest first.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get incident details

Returns full details for a single incident including monitor info, error data, checkpoint servers, screenshots, response headers/body, and traceroute. Next to those it carries the incident page facts: the monitor target, every probe location that checked the monitor during the incident (failing and passing), the status-page updates posted for it, and per-family facts (speed limit and load times, certificate dates, blacklist listings, DNS expected and received answers, server last report). A fact the product does not store for a family is left out rather than sent empty.

Authorizations:
bearerAuth
path Parameters
type
required
string
Enum: "uptime" "ssl" "domain" "fpl" "speed" "virus" "transaction" "rum" "server" "heartbeat" "blacklist" "dns" "api"

Monitor type (the speed-monitor type key is fpl; speed is accepted as an alias)

id
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete an incident

Permanently deletes an ended incident and its associated status page threads. An ongoing incident is refused with 409 incident_open for every monitor type. An incident of another account, or of a monitor outside a scoped operator's monitor groups, is treated as not existing (400 could_not_delete_incident).

Authorizations:
bearerAuth
path Parameters
type
required
string
Enum: "uptime" "ssl" "domain" "fpl" "speed" "virus" "transaction" "rum" "server" "heartbeat" "blacklist" "dns" "api"

Monitor type (the speed-monitor type key is fpl; speed is accepted as an alias)

id
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Set how much of an incident counts as downtime

The incident, its alerts and its logs stay exactly as recorded; only the downtime figure changes, everywhere availability is shown: the dashboard, monitor pages, reports, status pages, exports and the API. Reports already sent are not re-sent. none adds no downtime. partial adds only the stretch counted_from to counted_until, which must lie inside the incident (an ongoing incident is bounded by now, and later time does not count even if it continues). An incident the severity rule does not count as downtime cannot be overridden. Setting none or partial needs the Professional plan or above; restoring to full works on every plan. Each change writes one row to the account activity log. Needs the monitoring.manage capability (owner, Admin, Editor, and API keys). full behaves as the DELETE route.

Authorizations:
bearerAuth
path Parameters
type
required
stringuptime|ssl|domain|speed|fpl|transaction|virus...
Enum: "uptime" "ssl" "domain" "speed" "fpl" "transaction" "virus" "rum" "server" "heartbeat" "blacklist" "dns" "api" "api-monitor"

Monitor type. speed is accepted for fpl, api-monitor for api.

id
required
integer\d+
Example: 3391

Monitor ID

incidentId
required
integer\d+
Example: 99120

Incident ID. It must belong to the monitor in the path.

Request Body schema: application/json
mode
required
string
Enum: "full" "none" "partial"

full counts the whole incident, none counts nothing, partial counts only the given stretch.

counted_from
integer

Required for partial: start of the stretch that counts, as a Unix timestamp inside the incident.

counted_until
integer

Required for partial: end of the stretch that counts, as a Unix timestamp inside the incident and after counted_from.

reason
string <= 500 characters

Required for none and partial, ignored for full. Shown in incident lists and reports.

Responses

Request samples

Content type
application/json
{
  • "mode": "partial",
  • "counted_from": 1761820000,
  • "counted_until": 1761820720,
  • "reason": "Scheduled failover"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Restore an incident to count in full

Removes the incident's availability impact override, so it counts in full again. Idempotent: an incident without an override answers 200 and writes no activity-log row. Works on every plan. Needs the monitoring.manage capability.

Authorizations:
bearerAuth
path Parameters
type
required
stringuptime|ssl|domain|speed|fpl|transaction|virus...
Enum: "uptime" "ssl" "domain" "speed" "fpl" "transaction" "virus" "rum" "server" "heartbeat" "blacklist" "dns" "api" "api-monitor"

Monitor type. speed is accepted for fpl, api-monitor for api.

id
required
integer\d+
Example: 3391

Monitor ID

incidentId
required
integer\d+
Example: 99120

Incident ID. It must belong to the monitor in the path.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Set or restore availability impact on many incidents

The incident, its alerts and its logs stay exactly as recorded; only the downtime figure changes, everywhere availability is shown: the dashboard, monitor pages, reports, status pages, exports and the API. Reports already sent are not re-sent. none adds no downtime. partial adds only the stretch counted_from to counted_until, which must lie inside the incident (an ongoing incident is bounded by now, and later time does not count even if it continues). An incident the severity rule does not count as downtime cannot be overridden. Setting none or partial needs the Professional plan or above; restoring to full works on every plan. Each change writes one row to the account activity log. Needs the monitoring.manage capability (owner, Admin, Editor, and API keys). All or nothing: every item is checked before anything is written, one unknown monitor or incident answers 404 with nothing changed, and the writes share one transaction. An incident the severity rule does not count is not an error here: with none it is reported in skipped. partial is not available in bulk. One activity-log row is written per incident that actually changed.

Authorizations:
bearerAuth
Request Body schema: application/json
required
Array of objects [ 1 .. 500 ] items

The incidents, at most 500. Duplicates count once.

mode
required
string
Enum: "none" "full"
reason
string <= 500 characters

Required for none, ignored for full. One reason shared by every item.

Responses

Request samples

Content type
application/json
{
  • "items": [
    ],
  • "mode": "none",
  • "reason": "Scheduled failover"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a monitor's open manual incident

Returns the monitor's open manual incident, or data: null when it has none (automatic alerting is running normally). Needs the monitoring.view capability.

Authorizations:
bearerAuth
path Parameters
type
required
string
Enum: "uptime" "speed" "fpl" "transaction" "ssl" "domain" "virus" "server" "heartbeat" "blacklist" "dns" "api"

Monitor type. speed is accepted for fpl.

id
required
integer\d+
Example: 3391

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Open a manual incident on a monitor

Opens an incident on the monitor by hand and pauses its automatic alerting until the incident is resolved with POST .../manual-incident/resolve. While it is open, checks keep running and are logged, but no automatic incident is opened, recovered, re-graded or closed for the monitor. An automatic incident that is open when the call arrives is closed silently and replaced: it gets no recovery alert and no monitor.up webhook, its alert-group membership and escalation ladder are cancelled, and its not-yet-sent alerts are removed. Its ids come back in closed_incident_ids. The manual incident then alerts like any other incident: a DOWN goes to the monitor's contacts at once (the monitor's report_down delay does not apply; a recipient outside their alerting hours gets it when those hours start), alert groups and escalation policies pick it up, and resolving it sends the UP with the duration (subject to report_up). A critical incident counts as downtime; a degraded one does not. Available for every monitor type except rum. Needs the monitoring.manage capability (owner, Admin, Editor, and API keys).

Authorizations:
bearerAuth
path Parameters
type
required
string
Enum: "uptime" "speed" "fpl" "transaction" "ssl" "domain" "virus" "server" "heartbeat" "blacklist" "dns" "api"

Monitor type. speed is accepted for fpl.

id
required
integer\d+
Example: 3391

Monitor ID

Request Body schema: application/json
message
required
string [ 1 .. 500 ] characters

What is wrong, in plain text (1-500 characters after cleaning). It is shown on the incident, in the control panel and in alerts: SMS cuts it to 160 characters, push to 120, and WhatsApp carries only the monitor name. Control characters, bidirectional override characters and characters above U+FFFF (emoji) are removed; line breaks are kept. A message with nothing readable left is refused as invalid_message.

severity
required
string
Enum: "critical" "degraded"

critical alerts as a critical incident and counts as downtime. degraded alerts as a warning and does not count as downtime.

post_to_status_pages
boolean

Also open an incident thread on the status pages that show this monitor (or post an update to the thread already open for it). Only for uptime, speed/fpl and transaction monitors, and only with the statuspages.manage capability. Best effort: a thread that cannot be posted never fails the open; the reason comes back in status_thread_error.

Responses

Request samples

Content type
application/json
{
  • "message": "Checkout payments fail for card customers. The payment provider is investigating.",
  • "severity": "critical",
  • "post_to_status_pages": false
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Resolve a monitor's manual incident

Closes the monitor's open manual incident and resumes automatic alerting: the UP alert goes out with the duration (subject to the monitor's report_up; no UP goes out when the DOWN was skipped because the monitor was silenced), status-page threads move to their recovered close-out state, and the next check judges the monitor from live data again. A monitor that is still failing opens a normal automatic incident through its usual confirmation. Takes no request body. Needs the monitoring.manage capability.

Authorizations:
bearerAuth
path Parameters
type
required
string
Enum: "uptime" "speed" "fpl" "transaction" "ssl" "domain" "virus" "server" "heartbeat" "blacklist" "dns" "api"

Monitor type. speed is accepted for fpl.

id
required
integer\d+
Example: 3391

Monitor ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

List open manual incidents

Every open manual incident on the account, newest first, with the monitor's name. Not paginated: a monitor has at most one open manual incident. A member limited to monitor groups sees only the incidents of monitors in their groups. Needs the monitoring.view capability.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Monitoring Logs

Per-check monitoring logs across all monitor types.

List monitoring logs across all monitor types

Returns a paginated list of monitoring check logs across all monitor types (uptime, SSL, domain, speed, virus, transaction, server, API, DNS, blacklist). Supports filtering by date range, monitor, status, and location. Heartbeat pings are returned when the monitor filter names heartbeat monitors only.

Authorizations:
bearerAuth
query Parameters
date_start
string

Start date (Unix timestamp or YYYYMMDD string read as a day in the account timezone, defaults to account-zone midnight six days ago)

date_end
string

End date (Unix timestamp or YYYYMMDD string read as a day in the account timezone, defaults to now)

monitors[uptime][]
Array of integers

Filter by specific uptime monitor IDs

monitors[ssl][]
Array of integers

Filter by specific SSL monitor IDs

monitors[domain][]
Array of integers

Filter by specific domain monitor IDs

monitors[fpl][]
Array of integers

Filter by specific speed (full page load) monitor IDs. Note: the type key for speed monitors is "fpl".

monitors[transaction][]
Array of integers

Filter by specific transaction monitor IDs

monitors[virus][]
Array of integers

Filter by specific virus monitor IDs

monitors[api][]
Array of integers

Filter by specific API monitor IDs (one row per run)

monitors[dns][]
Array of integers

Filter by specific DNS monitor IDs (one row per sweep; these rows carry no probe location)

monitors[blacklist][]
Array of integers

Filter by specific blacklist monitor IDs (one row per sweep; these rows carry no probe location)

status[up]
boolean
Default: true

Include checks with up status (default true)

status[down]
boolean
Default: true

Include checks with down status (default true)

locations
string
Default: "all"

Location filter: "all" or comma-separated location IDs

page
integer
Default: 1

Page number (default 1)

limit
integer
Default: 20

Results per page (default 20)

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get single monitoring log detail

Returns detailed data for a single monitoring check result.

Authorizations:
bearerAuth
path Parameters
type
required
string
Enum: "uptime" "ssl" "domain" "virus" "fpl" "transaction" "heartbeat" "server" "api" "dns" "blacklist"

Monitor type

id
required
integer\d+

Log entry ID

query Parameters
location
integer

The list row's location_id: the probe that ran the check. With backup and signal it picks one check when several share the id (the probes of one round, a heartbeat start and success in one second); without them the id resolves the same check every time.

backup
boolean

The list row's backup flag (1 = backup-probe re-check)

signal
string

Heartbeat only: the list row's signal (success, start, manual or fail)

Responses

Contacts

Alert contacts and notification channels.

List available contact types (Email, SMS, Phone call + user integrations)

Returns the set of contact channel types you can assign to a new contact: the built-in Email (id 1) and SMS (id 2) types plus one entry per integration profile already configured on your account (Slack, Discord, Telegram, webhooks, etc.). Use the returned ids/type codes when creating or updating contacts.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

List all contacts for the authenticated account

Returns every alert recipient configured on your account, including email and SMS contacts as well as integration-backed contacts, with their confirmation status and the operator they belong to. The response includes a metadata.total count; results are not paginated.

Authorizations:
bearerAuth
query Parameters
scope
string
Value: "account"

Optional scope filter. Defaults to the operator-scoped list (an operator sees only the contacts it owns). Set to "account" to return every contact on the account regardless of the owning operator.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new contact

Adds a new alert recipient to your account. For email/sms types the value is the address or phone number, and SMS numbers must be in international format (starting with a +); for integration types the value is optional and integration_id links to an existing integration profile. E-mail, SMS and phone-call contacts start unverified (is_confirmed=false) and receive no alert until the address or number is confirmed: a verification e-mail (link) or SMS (code + link) is sent automatically, free of SMS credits. Your own login address, once proven by signing in, is verified at once. Integrations need no verification.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Contact display name

type
required
string

Contact type (email, sms, slack, etc.)

value
required
string

Contact value (email address, phone number, etc.)

integration_id
integer

Integration ID if this is an integration contact

user_id
integer

User/operator ID this contact belongs to (0 for main user)

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "type": "email",
  • "value": "[email protected]",
  • "integration_id": 0,
  • "user_id": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single contact by ID

Returns the full record for one alert recipient, including its type, value, confirmation flag and integration linkage. The contact must belong to the authenticated account; a 404 is returned if no matching contact exists.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a contact

Permanently removes an alert recipient from your account so it will no longer receive notifications. This action cannot be undone; returns a 400 if the contact could not be deleted.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing contact

Modifies an existing alert recipient; only the fields you supply are changed and any omitted fields keep their current values. SMS numbers must remain in international format (starting with a +). Changing the address or number of an e-mail, SMS or phone-call contact makes it unverified again and sends a new verification message; an unchanged address keeps its verification state. The contact must belong to the authenticated account, otherwise a 404 is returned.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
name
string

Contact display name

type
string

Contact type

value
string

Contact value

integration_id
integer
user_id
integer

Reassign the contact to this user/operator (0 = main user). Account owner only.

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "type": "string",
  • "value": "string",
  • "integration_id": 0,
  • "user_id": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get contacts with selection state for a specific monitor

Returns all of your contacts annotated with an is_selected flag indicating whether each one will be alerted for the given monitor. Unlike the monitor contacts array — which holds polymorphic references (team / owner / seat / contact) that are only expanded when an alert fires — this endpoint reports the resolved answer: a contact is selected when the monitor names it directly OR when it names a team, the owner, or the seat that owns it. Use it to render an alert-recipient picker, or to answer "who actually gets paged for this monitor". Monitor types: uptime, ssl, domain, fpl, transaction, rum, virus, server, heartbeat, blacklist, dns, api, reports.

Authorizations:
bearerAuth
path Parameters
monitorId
required
integer\d+

Monitor ID

type
required
string

Monitor type (uptime, ssl, domain, fpl, transaction, rum, virus, reports)

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Resend the verification message to a contact

Sends a new verification message to an unverified e-mail, SMS or phone-call contact: an e-mail with a confirmation link, or an SMS with a 6-digit code and a link (phone-call numbers are verified by SMS too). A new message replaces the previous link and code. Verification SMS are never charged to your SMS credits. Limits: one resend per contact per 10 minutes, 20 verification e-mails per account per hour, 3 verification SMS per contact and 10 per account per day, 5 messages per address or number per day. A contact that is already verified, or an integration, needs nothing: the call succeeds with result not_needed. The contact must belong to your account; a team member can resend only for contacts they own.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success",
  • "data": {
    }
}

Allow alerts again for an opted-out contact

Undoes the recipient's own opt-out. When someone uses the "Do not send alerts to this e-mail address" link in an alert e-mail, their contact gets alerts_suppressed = 1 and every alert and report e-mail to it is skipped (alerts are recorded as skipped / contact_opted_out in the delivery record). This sets it back to 0. Because the opt-out was the recipient's choice, an e-mail, SMS or phone-call contact then needs the recipient's confirmation again: it becomes unverified (is_confirmed = 0) and a fresh verification message is sent (the usual verification limits apply), and alerts and reports resume only once the recipient confirms. Your own verified login e-mail stays verified, and integrations need no confirmation. The recipient's decline is remembered for your account and that address or number (also after the contact is deleted and added again); it can be lifted once every 30 days per address: inside that window the call answers 429 too_many_requests with retry_after and nothing changes. The verification field says what happened: sent, confirmed (no confirmation needed), not_required (integration), waiting_for_login, account_unverified, rate_limited, failed or not_sent (use request-confirmation to send it). The link opts out every contact of the account carrying that address, so this clears the flag on each of them that you may edit. The contact must belong to your account; a team member can change only contacts they own.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Verify a contact with the code from its verification SMS

Confirms an SMS or phone-call contact with the 6-digit code from its verification SMS (whoever holds the phone can also tap the link in that SMS instead). On success the contact is verified and receives alerts. A code works for 30 minutes; after 5 wrong entries it stops working and a new one must be sent with request-confirmation. The contact must belong to your account; a team member can confirm only contacts they own.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
code
required
string

The code from the verification SMS

Responses

Request samples

Content type
application/json
{
  • "code": "123456"
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Send the verification message to a contact

Same as POST /api/v2/contacts/{id}/request-confirmation (both paths stay available): sends a new verification message to an unverified e-mail, SMS or phone-call contact — an e-mail with a confirmation link, or an SMS with a 6-digit code and a link (phone-call numbers are verified by SMS too). A new message replaces the previous link and code. Verification SMS are never charged to your SMS credits. Limits: one message per contact per 10 minutes, 20 verification e-mails per account per hour, 3 verification SMS per contact and 10 per account per day, 5 messages per address or number per day. A contact that is already verified, or an integration, needs nothing: the call succeeds with result not_needed. The contact must belong to your account; a team member can send only for contacts they own.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success",
  • "data": {
    }
}

Verify a contact with the code from its verification SMS

Same as POST /api/v2/contacts/{id}/confirm (both paths stay available): confirms an SMS or phone-call contact with the 6-digit code from its verification SMS (whoever holds the phone can also tap the link in that SMS instead). On success the contact is verified and receives alerts. A code works for 30 minutes; after 5 wrong entries it stops working and a new one must be sent with send-verification. The contact must belong to your account; a team member can verify only contacts they own.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
code
required
string

The code from the verification SMS

Responses

Request samples

Content type
application/json
{
  • "code": "123456"
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Send a test alert to a contact

Sends a sample Down alert marked TEST to one verified e-mail, SMS or phone-call contact, through the same sender, SMS account and caller number a real alert uses. Nothing is down and no incident is opened. An SMS or phone-call test uses one of your SMS or phone-call credits, like a real alert. Every test is recorded in the alert delivery record (GET /api/v2/deliveries, kind test) with what happened to it. Limits: 5 tests per contact and 20 per account per hour. Integrations have their own test: POST /api/v2/integrations/{id}/test. The contact must belong to your account; a team member can test only contacts they own.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success",
  • "data": {
    }
}

Unverified contacts that monitors rely on

Lists the unverified e-mail, SMS and phone-call contacts that at least one active (not paused) monitor would alert, directly, through a team or seat, or through its escalation policy. These contacts receive no alert until they are verified. Opted-out contacts are not listed. A team member sees only the contacts they own.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Alert Groups

Grouped incidents sharing one escalation ladder, with acknowledge / un-acknowledge.

List active (open) alert groups

Returns every OPEN alert group on the account — single-monitor groups included — newest first, and never paginated. For a monitor-scoped seat (Editor or Read-only member limited to monitor groups) each card carries only the members in its scope, the counts are computed from those members, and a group with no member in scope is left out. Each element is the GroupCard: the members folded into the storm, distinct-monitor counts, acknowledgement state with MTTA, the notifications-sent tally and the storm-math counterfactual (without_grouping). GET /api/v2/alert-groups/{id} returns this same card plus the detail-only extras, so an incident dashboard can list here and drill in there without reshaping anything.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Get one alert group

Returns one owned alert group as the same GroupCard the active list returns, plus nine detail-only extras: the raw events trail, the ladder (per-row schedule and status), the delivery ledger, a live policy_snapshot, ack_url_enabled, the alerts_sent tally, the undelivered delivery_failures, and every per-recipient delivery in deliveries with its delivery_counts. Any owned group can be fetched, not only open ones — resolved and cancelled groups stay readable. A group whose escalation state row has been purged still returns, with an empty ladder. A monitor-scoped seat gets 404 for a group with no member in its scope; for any other group the card is account-wide and only the recipient-level delivery sections are narrowed to its members.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Alert group ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Acknowledge an alert group

Pauses the group's escalation ladder — pending steps and repeat rounds stop — without closing the incident: monitoring continues and the recovery notice still goes out. Records who acknowledged, through which channel, and the MTTA. Acknowledging is an operational action, so every operator seat that can view alerting may do it, read-only viewers included. A group whose earlier acknowledgement already auto-resumed can be acknowledged again; a resolved or cancelled one cannot. A monitor-scoped seat can only acknowledge a group with at least one member in its scope; any other group answers 404. Takes no request body.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Alert group ID

Responses

Response samples

Content type
application/json
{
  • "status": "success",
  • "acked": {
    }
}

Un-acknowledge an alert group

Clears the acknowledgement and re-arms the ladder from the current step; steps whose scheduled time passed while the group was paused fire immediately. Every acknowledgement link already distributed for this group stops working (the ack epoch is bumped). Allowed for every operator seat that can view alerting, viewers included. Unlike acknowledging, this is not restricted to open groups — ownership, monitor-group scope (a scoped seat gets 404 for a group with no member in its scope) and an existing acknowledgement are the only checks, so a resolved group can still be un-acknowledged. Takes no request body, and returns no acked block.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 4821

Alert group ID

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Alert Deliveries

What happened to every alert sent: accepted, dropped after every attempt failed, skipped, cancelled or pending, with each attempt and its error.

List the alert deliveries of an incident

Returns one entry per recipient per alert sent for this incident (outage and recovery alerts, alert-group digests and escalation steps), whatever happened to it: accepted by our mail relay or the channel's API, dropped after every attempt failed, skipped before sending (an opted-out or unconfirmed contact, for example), cancelled (acknowledged, paused, recovered before it was due), or still pending (queued, held by quiet hours, retrying). Each entry carries its attempts with the sanitized error of each failed one. The recipient is a snapshot taken when the alert was queued, so deliveries to a contact deleted since still show. accepted means the relay or API took the message; delivery to the inbox is not tracked.

Authorizations:
bearerAuth
path Parameters
type
required
string
Enum: "uptime" "ssl" "domain" "fpl" "speed" "virus" "transaction" "rum" "server" "heartbeat" "blacklist" "dns" "api"

Monitor type (the speed-monitor type key is fpl; speed is accepted as an alias)

id
required
integer\d+

Incident ID

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

List alert deliveries

Returns your account's alert deliveries, newest first, so you can find the alerts that did not reach anyone — for example ?status=dropped for every alert whose attempts all failed. Filters combine. The time window applies to when the alert was queued and defaults to the last 30 days. Deliveries are kept for as long as your plan keeps resolved incidents. A member limited to monitor groups sees only the deliveries of monitors in those groups.

Authorizations:
bearerAuth
query Parameters
status
string
Example: status=dropped

Only these statuses, comma-separated: queued, held, retrying, accepted, dropped, skipped, cancelled

reason
string

Only this reason code (for example max_attempts, contact_opted_out, acknowledged)

channel
string

Only this channel code (email, sms, voice, slack, webhook, push, fcm, …)

monitor_type
string
Enum: "uptime" "ssl" "domain" "fpl" "speed" "virus" "transaction" "rum" "server" "heartbeat" "blacklist" "dns" "api"

Only this monitor type (speed is accepted as an alias of fpl). Required with monitor_id and incident_id.

monitor_id
integer

Only this monitor

incident_id
integer

Only this incident

from
string
Example: from=20260901

Window start: Unix timestamp, or a date as YYYYMMDD / YYYY-MM-DD in your account timezone. Defaults to 30 days ago.

to
string
Example: to=20260930

Window end: Unix timestamp, or a date as YYYYMMDD / YYYY-MM-DD (the whole day is included). Defaults to now.

page
integer
Default: 1

Page number (default 1)

limit
integer <= 200
Default: 50

Results per page (default 50, max 200)

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Escalation Policies

Reusable named escalation ladders that monitors opt into.

List escalation policies

Returns every escalation policy on the account, oldest id first, each with its ordered ladder of steps, its repeat block and how many monitors currently point at it. Not paginated and not filterable. The id of a policy here is the value the monitor endpoints of all twelve escalation-capable monitor types (uptime, SSL, speed, domain, transaction, virus, RUM, server, heartbeat, blacklist, DNS, API) accept as escalation_policy_id.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create an escalation policy

Creates an escalation policy — a reusable ladder that monitors then bind to by id.

The ladder is the whole resource. Step 0 fires the moment the incident opens (whatever wait_minutes it was sent, the stored value is 0); every later step fires wait_minutes after the PREVIOUS step, so a ladder of 0 / 10 / 15 pages at t+0, t+10 and t+25. Every step must page at least one recipient: a step with an empty or missing recipients list is refused with invalid_steps.

repeat is optional. Omit it (or send null) and the policy is stored with repeats off: {enabled: false, scope: "last", every_minutes: 30, max_rounds: 2}. advance_on_failure is optional too and defaults to true. The response is the new id only — read it back with GET /escalation-policies/{id} if you need the stored shape.

Requires the Owner, Admin or Editor role, and the Professional plan or above; AppSumo lifetime accounts are exempt from the plan gate. Existing policies on a lower plan keep firing — only creation is gated.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string <= 100 characters

Policy name, 1..100 characters. Stored trimmed and with HTML tags stripped, so Ops <b>tier 1</b> comes back as Ops tier 1. A name that is blank once tags are stripped is rejected.

required
Array of objects [ 1 .. 10 ] items

The ladder, 1..10 steps, in fire order. Must be a JSON array (a keyed object is rejected).

advance_on_failure
boolean
Default: true

When every alert of a step ends undelivered and nobody got it, fire the next step at once instead of waiting. Optional; defaults to true. 0/1 are accepted too.

object or null

What happens once the last step has fired and the incident is still open. Optional; each key falls back to the default shown.

Responses

Request samples

Content type
application/json
{
  • "name": "Production — pager ladder",
  • "steps": [
    ],
  • "advance_on_failure": true,
  • "repeat": {
    }
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single escalation policy

Returns one escalation policy owned by the account, in the same shape as the list entry. Unlike the list, the response carries no metadata envelope.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 41

Policy ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete an escalation policy

Deletes a policy owned by the account, along with its steps. The delete cascades, and it is not reversible:

  • every monitor of every type bound to this policy is detached (escalation_policy_id back to 0) and falls back to its own all-at-once recipient list — fallback, never silence. The count is returned as detached.
  • escalation ladders currently running on this policy are cancelled where they stand.
  • alert groups still open on this policy are cancelled, and their queued-but-unsent notification rows are deleted. Alerts that were already queued for those incidents will not be delivered.

The monitors themselves, and their own contact lists, are untouched. Requires the Owner, Admin or Editor role.

Note that status here is "ok", not the "success" the create and update paths return.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 41

Policy ID

Responses

Response samples

Content type
application/json
{
  • "status": "ok",
  • "detached": 7
}

Update an escalation policy

Partially updates a policy owned by the account. Four keys are read — name, steps, repeat and advance_on_failure — and anything else in the body is ignored rather than rejected. A key you omit is left alone; sending all four is equivalent to a full save.

The two supplied keys behave differently, and the difference matters:

  • steps is a full replace. The submitted array becomes the ladder; every step not in it is deleted. There is no way to edit one rung — read the policy, change the array, send it back.
  • repeat is a merge. Keys you send are validated and written; keys you omit keep the value already stored, so {"repeat":{"every_minutes":15}} on an all / 120 / 5 policy leaves scope all and 5 rounds in place. Sending "repeat": null is the one exception: it is an explicit reset to {enabled: false, scope: "last", every_minutes: 30, max_rounds: 2}.

Nothing is written until the whole body validates, so a rejected request leaves the policy exactly as it was. The response carries no policy — read it back if you need the stored shape.

Requires the Owner, Admin or Editor role. There is no plan gate here: a policy that already exists stays editable on any plan.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 41

Policy ID

Request Body schema: application/json
name
string <= 100 characters

New name, 1..100 characters. Stored trimmed and with HTML tags stripped. Omit to keep the current name; null is not a clear, it is rejected as invalid_policy_name.

Array of objects [ 1 .. 10 ] items

FULL REPLACEMENT of the ladder, 1..10 steps in fire order. Omit to keep the existing steps. Step 0 fires at t+0 (its wait_minutes is stored as 0); every later step fires wait_minutes after the previous one.

advance_on_failure
boolean

When every alert of a step ends undelivered and nobody got it, fire the next step at once instead of waiting. Omit to keep the stored value. 0/1 are accepted too.

object or null

Merged over the stored repeat block: send only the keys you want to change. Omit the whole object to leave repeats untouched; send null to reset them to off / last / 30 / 2.

Responses

Request samples

Content type
application/json
{
  • "name": "Production — pager ladder",
  • "steps": [
    ],
  • "advance_on_failure": true,
  • "repeat": {
    }
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Alerting Settings

Account-wide incident grouping and acknowledgement behaviour, including what the acknowledgement link in an alert does: one_click, sign_in (a password sign-in to the control panel first) or off.

Get incident grouping & acknowledgement settings

Returns the account's grouping and acknowledgement settings. An account that has never saved them gets the product defaults: grouping on, scope policy, 3-minute rolling window, 3-minute update throttle, one-click acknowledgement links, no auto-resume. Values are always catalogue members, so a client can render them as fixed choices.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update incident grouping & acknowledgement settings

Partial update — only the fields you send change, and every value must be a catalogue member: window_minutes 1|2|3|5|10, window_mode rolling|fixed, throttle_minutes 1|3|5|10, group_scope policy|policy+group, ack_resume_minutes 0|30|60|120 (0 = never), ack_link_mode off|one_click|sign_in. The two boolean fields also accept 0 and 1, as integer or string. ack_link_mode wins when a body carries both it and ack_links_enabled; a lone ack_links_enabled false sets the mode to off, and true sets one_click unless links are already on (a sign_in account stays sign_in). Groups snapshot the window and throttle when they open, so an edit only affects groups opened after it. Requires a seat that can manage alerting (Owner, Admin or Editor); Read-only and Accounting seats get 403. A body carrying no recognised field is accepted and writes nothing, so a mistyped field name still answers 200 — check the field names against the list above rather than trusting the status code.

Authorizations:
bearerAuth
Request Body schema: application/json
grouping_enabled
boolean

Whether incidents are folded into groups at all

group_scope
string
Enum: "policy" "policy+group"

What has to match for two incidents to share a group

window_minutes
integer
Enum: 1 2 3 5 10

How long a group keeps accepting new members, in minutes

window_mode
string
Enum: "rolling" "fixed"

rolling restarts the window on every join; fixed measures it once from the group anchor

throttle_minutes
integer
Enum: 1 3 5 10

Minimum minutes between join-update notices for one group

ack_links_enabled
boolean

Legacy switch for acknowledgement links. false = mode off; true = one_click, or keeps sign_in when that is the current mode. Ignored when ack_link_mode is in the same body.

ack_link_mode
string
Enum: "off" "one_click" "sign_in"

How the acknowledgement link in an alert works: one_click (anyone holding the alert), sign_in (only an owner or team member signed in with email and password) or off (no link)

ack_resume_minutes
integer
Enum: 0 30 60 120

Minutes an acknowledgement holds the ladder before resuming on its own; 0 = never

Responses

Request samples

Content type
application/json
{
  • "grouping_enabled": true,
  • "group_scope": "policy",
  • "window_minutes": 3,
  • "window_mode": "rolling",
  • "throttle_minutes": 3,
  • "ack_links_enabled": true,
  • "ack_link_mode": "one_click",
  • "ack_resume_minutes": 0
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Integrations

Third-party integrations and outbound webhooks.

List all integrations for the authenticated account

Returns every third-party notification channel configured on your account (Slack, Discord, Telegram, Google Chat, Gotify, ntfy, Pushover, Jira Cloud issues, GitHub Issues, GitLab Issues, Datadog, PagerDuty, Jira Service Management / Opsgenie, ilert, Splunk On-Call, SIGNL4, MS Teams, Statuspage, Mattermost, Slack-compatible webhooks, Twilio, WhatsApp, webhooks, etc.) with its id, name and type. The response includes a metadata.total count; results are not paginated.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new integration

Creates a third-party notification channel of the given type (slack, discord, telegram, mattermost, pagerduty, whatsapp, twilio, statuspage, etc.). Required and meaningful fields vary by type and are validated server-side; the type-specific values map onto component_id, page_id, custom_headers, additional_value_1 and settings (for example the Slack channel or the Twilio phone number). An unknown type is rejected with a validation_error. A matching alert contact is created automatically, so the response returns both the integration id and the new contact_id.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Integration display name

type
required
string

Integration type (slack, discord, telegram, mattermost, pagerduty, whatsapp, twilio, statuspage, etc.)

api_key
required
string

API key or webhook URL

component_id
string

Component ID (statuspage/twilio)

page_id
string

Page ID (statuspage/twilio)

custom_headers
string

Custom headers (webhook)

additional_value_1
string

Additional value (slack channel, twilio phone)

settings
string

JSON object of channel settings; jira only: {"issue_type":"Task","resolve_transition":"Done","labels":["uptimia"],"priority":true}. Validated and re-serialised server-side.

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "type": "slack",
  • "api_key": "string",
  • "component_id": "string",
  • "page_id": "string",
  • "custom_headers": "string",
  • "additional_value_1": "string",
  • "settings": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List all webhook integrations

Returns only the webhook-type integrations on your account, each with its target URL (api_key) and any custom headers. Use this to manage outbound HTTP notification endpoints separately from other integration types.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Create a new webhook

Registers a new outbound webhook that Uptimia will POST to when alerts fire. The api_key field must be a valid public URL; it is validated and screened against an SSRF guard, so internal/private addresses are rejected with a 400. Optionally supply custom_headers as a JSON string to attach to each request.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Webhook display name

api_key
required
string

Webhook URL

custom_headers
string

Custom headers as JSON string

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "api_key": "string",
  • "custom_headers": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single webhook by ID

Returns the configuration of one webhook integration, including its target URL and custom headers. The integration must belong to your account and be of type webhook; a 404 is returned otherwise.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a webhook

Permanently removes a webhook integration so it will no longer receive alert notifications. The integration must belong to your account and be of type webhook (404 otherwise); returns a 400 if deletion fails.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update a webhook

Updates the name, target URL or custom headers of an existing webhook; omitted fields keep their current values. The integration must belong to your account and be of type webhook, otherwise a 404 is returned.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
name
string
api_key
string

Webhook URL

custom_headers
string

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "api_key": "string",
  • "custom_headers": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single integration by ID

Returns the full configuration of one integration of any type, including its api_key plus type-specific fields such as component_id, page_id, custom_headers and additional_value_1. The integration must belong to the authenticated account; a 404 is returned if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete an integration

Permanently removes an integration of any type along with its associated alert contacts so it no longer receives notifications. The integration must belong to your account (404 otherwise); returns a 400 if deletion fails.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing integration

Updates any field of an existing integration of any type; omitted fields retain their current values. If the integration name changes, the linked alert contact is renamed to match. The integration must belong to your account, otherwise a 404 is returned.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
name
string
type
string
api_key
string
component_id
string
page_id
string
custom_headers
string
additional_value_1
string

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "type": "string",
  • "api_key": "string",
  • "component_id": "string",
  • "page_id": "string",
  • "custom_headers": "string",
  • "additional_value_1": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Send a test notification for an integration

Dispatches a sample alert through the integration using its stored credentials so you can confirm the channel is wired up correctly before relying on it. The integration must belong to your account (404 otherwise); unsupported integration types or delivery failures (for example an invalid Twilio phone number) return a 400. Requires a verified account e-mail (403 email_not_verified). At most 5 tests per account every 10 minutes, shared with POST /api/v1/integrations-test/{id}; WhatsApp tests are also limited to 3 a day on free and trial plans and 5 a day per destination number across all accounts (429 rate_limited with a Retry-After header). A URL-based integration whose address fails the outbound address check answers 400 test_failed and nothing is sent.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Event Subscriptions

Outbound events: subscribe a URL and Uptimia POSTs each matching event to it (Zapier, Make, n8n or your own service). See Event subscriptions in the introduction for events, payloads and signatures.

List event subscriptions

Returns every outbound event subscription on the account (Zapier hooks and API-created ones): the event, the target URL, the optional monitor filter, when it last delivered and whether it has been disabled after repeated failures. Secrets are never returned after creation.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Subscribe a URL to an event

Creates an outbound event subscription. Every matching event is POSTed to target_url as JSON with the headers X-Uptimia-Event, X-Uptimia-Delivery and X-Uptimia-Signature (sha256= HMAC-SHA256 of the raw body with the secret returned here — it is shown once). Events: monitor.down, monitor.up, expiry.warning (ssl/domain countdowns, with kind), incident.acknowledged. Optional monitor_type and monitor_id narrow the subscription to one family or one monitor. Targets must be https and public; hooks.zapier.com targets are recorded as source zapier. Any 2xx counts as delivered; a 410 Gone (or a 404 from hooks.zapier.com) removes the subscription; other failures are retried five times with backoff (six attempts), and after 25 consecutive failed deliveries (events whose every attempt failed) the subscription is disabled; POSTing the same subscription again replaces a disabled one.

Authorizations:
bearerAuth
Request Body schema: application/json
event
required
string
Enum: "monitor.down" "monitor.up" "expiry.warning" "incident.acknowledged"
target_url
required
string
monitor_type
string or null

Family filter: uptime, transaction, speed, rum, ssl, domain, virus, server, heartbeat, blacklist, dns, api

monitor_id
integer or null

One monitor of that family; omit or 0 for all

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Recent events in the delivery payload shape (sample data)

Returns the most recent real events of one kind for the account, newest first, in exactly the JSON shape a subscription delivers — automation tools use this for sample data while a workflow is being built. Empty when the account has no such event yet.

Authorizations:
bearerAuth
query Parameters
event
required
string
Enum: "monitor.down" "monitor.up" "expiry.warning" "incident.acknowledged"
limit
integer <= 25
Default: 3

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Delete an event subscription

Stops deliveries for the subscription. Returns 204; a subscription that does not exist on this account is a 404.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Maintenance

Scheduled maintenance windows that suppress alerting.

List all maintenance windows for the authenticated user

Returns every scheduled maintenance window belonging to the authenticated account, each with its schedule, current status, and the monitors it covers — plus a computed schedule decoration: a truthful computed_status (running/recurring/scheduled/expired/invalid), a structured schedule block, the current/next occurrence, and every concrete occurrence intersecting the requested horizon. All occurrence epochs are computed in the account timezone. The metadata object reports the total count, the account timezone, the server now, and one entry per horizon day.

Authorizations:
bearerAuth
query Parameters
horizon_days
integer [ 1 .. 31 ]
Default: 14

How many account-local days (starting today) to expand occurrences over. Clamped to 1..31.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new maintenance window

Schedules a new maintenance window during which alerts are suppressed for the selected monitors. Set type to once, daily, weekly, or monthly, and pick monitors via selection_mode (all, by_type, by_group, or individual). For a one-off window you may also publish a status page thread via status_page and status_summary. Returns the new window ID.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Maintenance window name

type
required
string
Enum: "once" "daily" "weekly" "monthly"

Schedule type: once, daily, weekly, monthly

time_start
string

Start time (datetime string for once, HHMM string for recurring)

time_end
string

End time (datetime string for once, HHMM string for recurring)

days
Array of strings

Days (weekday numbers for weekly, day-of-month for monthly)

weeks
Array of strings

Week numbers for weekly type

selection_mode
string
Enum: "all" "by_type" "by_group" "individual"

Monitor selection mode: all, by_type, by_group, individual

uptime
integer

Include uptime monitors (for by_type mode)

ssl
integer
domain
integer
virus
integer
fpl
integer
transaction
integer
rum
integer
server
integer
heartbeat
integer
blacklist
integer
dns
integer
api
integer
individual_monitors
Array of strings

Monitor IDs as type|id strings

individual_groups
Array of integers

Group IDs

status_page
integer

Create status page thread (published for both one-time and recurring windows)

status_summary
string

Status page thread summary

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "type": "once",
  • "time_start": "string",
  • "time_end": "string",
  • "days": [
    ],
  • "weeks": [
    ],
  • "selection_mode": "all",
  • "uptime": 0,
  • "ssl": 0,
  • "domain": 0,
  • "virus": 0,
  • "fpl": 0,
  • "transaction": 0,
  • "rum": 0,
  • "server": 0,
  • "heartbeat": 0,
  • "blacklist": 0,
  • "dns": 0,
  • "api": 0,
  • "individual_monitors": [
    ],
  • "individual_groups": [
    ],
  • "status_page": 0,
  • "status_summary": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get all monitors available for maintenance selection

Returns all of the account monitors that can be attached to a maintenance window, grouped by monitor type (uptime, ssl, domain, virus, fpl, transaction, rum, server, heartbeat, api). Use the returned IDs when building the individual_monitors selection.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Preview the concrete occurrences of a maintenance draft without saving it

Validates a create/update payload with the exact same schedule rules as POST/PATCH and, when valid, expands the draft into its next occurrences (up to 5, computed in the account timezone over the next 400 days) plus the first overlap with any other maintenance window. Name/title/summary problems never block a preview — they are returned as non-blocking warnings, because the preview concerns the schedule, not the announcement. Always responds 200; inspect data.valid.

Authorizations:
bearerAuth
Request Body schema: application/json
name
string

Maintenance window name (missing/short name only produces a warning here)

type
required
string
Enum: "once" "daily" "weekly" "monthly"
time_start
string

Start time (datetime string for once, HHMM string for recurring)

time_end
string

End time (datetime string for once, HHMM string for recurring; next-day ends encoded as hour+24, e.g. 2630)

days
Array of strings

Days (weekday numbers 1-7 for weekly, day-of-month 1-31 for monthly). Required for weekly/monthly — an empty selection, or a value outside those ranges, makes the preview invalid with invalid_days

weeks
Array of strings

Week of the month (1-5) for weekly type; anything outside that range makes the preview invalid with invalid_weeks

selection_mode
string
Enum: "all" "by_type" "by_group" "individual"

Monitor selection mode. Defaults to all when omitted. The same selection rule create/PATCH apply is applied here (see the server flag), but the selection does not change the computed occurrences, and preview does not run the group-scope confinement create/PATCH run — a scoped member can preview a selection those endpoints would reject

uptime
integer

Include uptime monitors (for by_type mode)

ssl
integer
domain
integer
virus
integer
fpl
integer
transaction
integer
rum
integer
server
integer

Accepted for request-body symmetry only: a truthy server flag with selection_mode=by_type makes the preview invalid with invalid_selection, because the maintenance table has no server by-type column. Attach servers through individual selection instead

heartbeat
integer
blacklist
integer
dns
integer
api
integer
individual_monitors
Array of strings

Monitor IDs as type|id strings (for individual mode)

individual_groups
Array of integers

Group IDs (for by_group mode)

status_page
integer

Publish a status page thread. Set to 1 to have the announcement rules checked — they come back as non-blocking warnings (invalid_title, invalid_summary), never as an invalid preview

status_summary
string

Status page thread summary; under 10 characters produces the invalid_summary warning when status_page is 1

status_page_ids
Array of integers

Status page IDs the thread should be published to. Accepted for symmetry with create/PATCH — it travels through the same payload builder, but the preview only expands the schedule, so it changes nothing in the response

exclude_id
integer

Window id to exclude from the overlap scan (edit mode: the window being edited)

Responses

Request samples

Content type
application/json
{
  • "name": "Nightly database failover",
  • "type": "weekly",
  • "time_start": "0130",
  • "time_end": "0300",
  • "days": [
    ],
  • "weeks": [
    ],
  • "selection_mode": "by_type",
  • "uptime": 1,
  • "ssl": 0,
  • "domain": 0,
  • "virus": 0,
  • "fpl": 0,
  • "transaction": 0,
  • "rum": 0,
  • "server": 0,
  • "heartbeat": 0,
  • "blacklist": 0,
  • "dns": 0,
  • "api": 0,
  • "individual_monitors": [
    ],
  • "individual_groups": [
    ],
  • "status_page": 1,
  • "status_summary": "We are failing the primary database over to its replica.",
  • "status_page_ids": [
    ],
  • "exclude_id": 5120
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single maintenance window with full details

Returns the full configuration of one maintenance window, including its schedule type, start/end times, recurrence days and weeks, monitor selection, and whether the window is currently running. Returns 404 if the window does not exist or does not belong to your account.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a maintenance window and revert affected monitors

Permanently deletes a maintenance window and reverts any monitors currently held in maintenance by it back to active checking. Returns 404 if the window does not exist or does not belong to your account.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing maintenance window

Replaces the configuration of an existing maintenance window with the supplied schedule and monitor selection, then returns the updated window (same shape as GET /{id}, including the additive selection_mode and *_list array fields). Returns 404 if the window does not exist or does not belong to your account.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
name
string
type
string
Enum: "once" "daily" "weekly" "monthly"
time_start
string
time_end
string
days
Array of strings
weeks
Array of strings
selection_mode
string
Enum: "all" "by_type" "by_group" "individual"
uptime
integer
ssl
integer
domain
integer
virus
integer
fpl
integer
transaction
integer
rum
integer
server
integer
heartbeat
integer
blacklist
integer
dns
integer
api
integer
individual_monitors
Array of strings
individual_groups
Array of integers
status_page
integer
status_summary
string

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "type": "once",
  • "time_start": "string",
  • "time_end": "string",
  • "days": [
    ],
  • "weeks": [
    ],
  • "selection_mode": "all",
  • "uptime": 0,
  • "ssl": 0,
  • "domain": 0,
  • "virus": 0,
  • "fpl": 0,
  • "transaction": 0,
  • "rum": 0,
  • "server": 0,
  • "heartbeat": 0,
  • "blacklist": 0,
  • "dns": 0,
  • "api": 0,
  • "individual_monitors": [
    ],
  • "individual_groups": [
    ],
  • "status_page": 0,
  • "status_summary": "string"
}

Delete all expired one-time maintenance windows

Permanently deletes every one-time (type once) maintenance window of the authenticated account whose end time is in the past. Unlike deleting a single window, resolved status-page threads and their history (updates and page targeting) are PRESERVED; only unresolved announcement threads are removed together with the windows. Returns how many windows were deleted.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Status Pages

Public status pages and their incident threads.

List all status pages for the authenticated account

Returns every public status page owned by the authenticated account, each with its display name, link slug, custom domain, visibility toggles and custom CSS/JS/HTML. The response includes a metadata.total count.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new status page

Creates a new public status page for the account from the supplied name, URL slug, optional custom domain, visibility toggles, custom styling/logo and section structure (sections each listing the monitors they display). Returns the new page ID on success, or a 400 validation error.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Status page display name

status_page_link_name
required
string

URL slug for the status page

custom_domain_name
string

Custom CNAME domain

is_incident_history_on
integer
Enum: 0 1

Show incident history

is_current_incidents_on
integer
Enum: 0 1

Show current incidents

is_scheduled_maintenances_on
integer
Enum: 0 1

Show scheduled maintenances

is_past_maintenances_on
integer
Enum: 0 1

Show past maintenances

is_footer_link_on
integer
Enum: 0 1

Show footer link

is_timezone_utc
integer
Enum: 0 1

Use UTC timezone

custom_css
string

Custom CSS

custom_js
string

Custom JavaScript

custom_html
string

Custom HTML

custom_logo
string

Custom logo URL or base64

required
Array of objects

Page sections with monitors

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "status_page_link_name": "string",
  • "custom_domain_name": "string",
  • "is_incident_history_on": 0,
  • "is_current_incidents_on": 0,
  • "is_scheduled_maintenances_on": 0,
  • "is_past_maintenances_on": 0,
  • "is_footer_link_on": 0,
  • "is_timezone_utc": 0,
  • "custom_css": "string",
  • "custom_js": "string",
  • "custom_html": "string",
  • "custom_logo": "string",
  • "structure": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Count the confirmed subscribers who would actually be emailed

Computes how many confirmed email subscribers would be notified for the affected monitor/incident across every owned status page that displays it, mirroring the incident notification fan-out. Only pages with subscriptions enabled (subscribe_enabled=1) contribute; pages with subscriptions off count 0 so the figure reflects who is ACTUALLY emailed. Scoped to the authenticated account.

Authorizations:
bearerAuth
query Parameters
status_page_id
integer

Restrict to a single owned status page

monitor_type
string
Enum: "uptime" "fpl" "transaction"

Affected monitor type

monitor_id
integer

Affected monitor (site) ID

incident_id
integer

Affected incident ID

thread_id
integer

Reach of the next update on this existing thread, resolved the way it is delivered: a general thread's own page; otherwise its explicit target pages, or every page listing one of its monitors when it has none. Takes precedence over every other parameter.

status_page_ids[]
Array of integers

Explicit pages a new thread will be published to (its 'Publish to' set); delivery honours these over monitor membership. Pages you do not own are ignored. Takes precedence over status_page_id and the monitor/incident parameters. A comma-separated status_page_ids=1,2 is accepted too.

Responses

Response samples

Content type
application/json
{
  • "total": 0,
  • "pages": [
    ],
  • "hidden_by_impact": true
}

Get a single status page with settings and structure

Retrieves one status page by ID, including all of its settings, visibility toggles, custom styling and its section/monitor structure. The page must belong to the authenticated account; returns 404 if it does not exist or is not yours.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a status page

Permanently deletes the status page identified by ID along with its configuration. The page must belong to the authenticated account. This action cannot be undone and returns a 400 error if the deletion fails.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing status page

Partially updates a status page; any omitted field keeps its current value, which is merged from the stored record before saving. A logo may be supplied either as a multipart file upload or via the custom_logo JSON field. The page must belong to the authenticated account; returns 404 if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
name
string
status_page_link_name
string
custom_domain_name
string
is_incident_history_on
integer
Enum: 0 1
is_current_incidents_on
integer
Enum: 0 1
is_scheduled_maintenances_on
integer
Enum: 0 1
is_past_maintenances_on
integer
Enum: 0 1
is_footer_link_on
integer
Enum: 0 1
is_timezone_utc
integer
Enum: 0 1
custom_css
string
custom_js
string
custom_html
string
custom_logo
string
Array of objects

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "status_page_link_name": "string",
  • "custom_domain_name": "string",
  • "is_incident_history_on": 0,
  • "is_current_incidents_on": 0,
  • "is_scheduled_maintenances_on": 0,
  • "is_past_maintenances_on": 0,
  • "is_footer_link_on": 0,
  • "is_timezone_utc": 0,
  • "custom_css": "string",
  • "custom_js": "string",
  • "custom_html": "string",
  • "custom_logo": "string",
  • "structure": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List threads filtered by resolved status

Returns the account's status threads (incidents, scheduled maintenances and general announcements shown on status pages), filtered by the is_resolved query flag (0 = active, 1 = resolved). Each entry summarises the thread and how many status updates it has, with a metadata.total count.

Authorizations:
bearerAuth
query Parameters
is_resolved
integer
Default: 0
Enum: 0 1

0 = active, 1 = resolved

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new thread

Opens a new status thread of the chosen type (general, incident or maintenance) with a title, summary and a first status update. Depending on the type you must reference the relevant status_page_id, incident_id or maintenance_id and may list affected monitors. Returns the new thread ID, or a 400 validation error.

Authorizations:
bearerAuth
Request Body schema: application/json
thread_type
required
string
Enum: "general" "incident" "maintenance"

Thread type

title
required
string

Thread title (min 5 chars)

summary
required
string

Thread summary (min 10 chars)

initial_status_update
required
string

Initial status update message (min 5 chars)

status_page_id
integer

Status page ID (for general type)

incident_id
integer

Incident ID (for incident type)

monitor_type
string
Enum: "uptime" "speed" "transaction"

Monitor type (for incident type)

maintenance_id
integer

Maintenance ID (for maintenance type)

Array of objects

Affected monitors

next_update_at
integer

"Next update by" ETA for the initial update (epoch seconds; 0 or omit = none)

Responses

Request samples

Content type
application/json
{
  • "thread_type": "general",
  • "title": "string",
  • "summary": "string",
  • "initial_status_update": "string",
  • "status_page_id": 0,
  • "incident_id": 0,
  • "monitor_type": "uptime",
  • "maintenance_id": 0,
  • "monitors": [
    ],
  • "next_update_at": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Find the existing thread for a monitor or incident

Looks up whether a status thread already exists for the given monitor (monitor_type + monitor_id) and/or incident (incident_id), so the control panel can offer to continue posting to it instead of opening a duplicate. An UNRESOLVED thread is preferred; if none is open the most recent RESOLVED thread for the same incident/monitor is returned with resolved=true so the client can offer to reopen it. Returns thread=null, resolved=false when nothing matches. Scoped to the authenticated account.

Authorizations:
bearerAuth
query Parameters
monitor_type
string
Enum: "uptime" "fpl" "transaction"

Monitor type of an incident thread

monitor_id
integer

Monitor (site) ID

incident_id
integer

Incident ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single thread with all updates

Retrieves one status thread by ID together with its full chronological list of status updates (each with status, message and timestamp). The thread must belong to the authenticated account; returns 404 if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a thread and all its updates

Permanently deletes a status thread together with every status update posted to it. The thread must belong to the authenticated account. This action cannot be undone and returns a 400 error if it fails.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing thread

Updates a status thread's title, summary and the list of affected monitors. To change the thread status post a new status update instead. The thread must belong to the authenticated account; returns 404 if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
title
string

Thread title (min 5 chars)

summary
string

Thread summary (min 10 chars)

status_page_id
integer

Status page ID (required for general threads)

Array of objects

Affected monitors

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "summary": "string",
  • "status_page_id": 0,
  • "monitors": [
    ]
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Post a status update to a thread

Appends a new status update to the thread identified by threadId, advancing its current status (for example investigating, monitoring or resolved) with an accompanying message. The parent thread must belong to the authenticated account. Returns the new update ID, or a 400 validation error.

Authorizations:
bearerAuth
path Parameters
threadId
required
integer\d+
Request Body schema: application/json
status
required
string
Enum: "open" "acknowledged" "investigating" "in_progress" "monitoring" "resolved" "scheduled" "completed" "update" "closed"

Status progression value

message
required
string

Update message (min 10 chars)

next_update_at
integer

"Next update by" ETA for this update (epoch seconds; 0 or omit = none)

Responses

Request samples

Content type
application/json
{
  • "status": "open",
  • "message": "string",
  • "next_update_at": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a single status update

Removes one status update from its thread without deleting the thread itself. The update must belong to a thread owned by the authenticated account. This action cannot be undone and returns a 400 error if it fails.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Edit an existing status update

Edits a previously posted status update, changing its status and message. You must pass the parent thread_id alongside the update ID. The update must belong to a thread owned by the authenticated account.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
thread_id
required
integer

Parent thread ID

status
required
string

Status value

message
required
string

Update message (min 10 chars)

next_update_at
integer

"Next update by" ETA for this update (epoch seconds; 0 or omit = none)

Responses

Request samples

Content type
application/json
{
  • "thread_id": 0,
  • "status": "string",
  • "message": "string",
  • "next_update_at": 0
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Get presentation settings for a status page

Returns the default theme and subscribe toggle for one owned status page.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update presentation settings for a status page

Sets the presentation settings of one owned status page — default theme, whether the public Subscribe affordance is shown, whether the page name is shown next to the logo — and its access control (public, shared password, or private IP allowlist). Note that the two toggles are absolute, not partial: a body that omits subscribe_enabled or show_name_with_logo stores 0 for it, so send the full pair. Access control is the exception — omitting visibility keeps the current mode. Establishing or rotating protection needs an eligible plan (422 upgrade_required); removing it never does. Turning subscribe_enabled on (0 to 1) needs a verified account e-mail (422 email_not_verified); a stored 1 is kept on save; on free and trial plans it stays inert, with no Subscribe button and no subscriber mail, while the account e-mail is unverified, and on the expired free plan it always does. The response echoes the stored settings in the same shape as GET /status-pages/{id}/settings.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 314

Status page ID

Request Body schema: application/json
default_theme
string
Enum: "system" "light" "dark"

Anything other than system, light or dark is stored as system

subscribe_enabled
integer
Enum: 0 1

Any falsy value stores 0; anything else stores 1. Omitting the key stores 0

show_name_with_logo
integer
Enum: 0 1

Any falsy value stores 0; anything else stores 1. Omitting the key stores 0

visibility
string
Enum: "public" "password" "private"

public removes protection exactly like clear_password. Omit the key to edit the current protected mode in place (rotate the password, change the allowlist); an unrecognised value behaves like omitting it

password
string

New shared password (>=10 chars) when visibility=password; omit to keep the current one. Setting or rotating it signs every current visitor out

clear_password
boolean

Remove protection (revert to public + revoke grants). Always permitted, even on a plan that could not re-establish it

access_ip_allowlist
string

Newline/comma-separated IPs/CIDRs required when visibility=private. Stored de-duplicated and newline-joined

Responses

Request samples

Content type
application/json
{
  • "default_theme": "dark",
  • "subscribe_enabled": 1,
  • "show_name_with_logo": 0,
  • "visibility": "password",
  • "password": "winter-harbour-42",
  • "clear_password": false,
  • "access_ip_allowlist": "203.0.113.4\n198.51.100.0/24"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List email subscribers for a status page

Returns the email subscribers of one owned status page with their confirmation state, plus a metadata.total / metadata.confirmed count. Unconfirmed (pending double opt-in) subscribers are included; the whole list is returned, unpaginated.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 314

Status page ID

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Remove an email subscriber from a status page

Unsubscribes one email address from an owned status page: the subscriber row is deleted outright, so the address stops receiving incident and maintenance notifications and would have to opt in again. The deletion is scoped to the page, so a subscriberId belonging to another status page is never touched. The call is idempotent — an unknown or already-removed subscriberId still returns 200 with status "success"; only an unknown or non-owned status page id produces a 404. This action cannot be undone.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Example: 314

Status page ID

subscriberId
required
integer\d+
Example: 4821

Subscriber ID as returned by GET /status-pages/{id}/subscribers

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Reports

Scheduled and on-demand email reports.

List all scheduled reports for the authenticated account

Returns the recurring email reports configured on your account, each with its frequency (and a human-readable frequency_label), last/next send timestamps, attachment options and monitor-scope flags. One-time temporary reports are excluded; the response includes a metadata.total count and is not paginated.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new scheduled report

Creates a recurring email report delivered on the chosen frequency (1=Daily, 7=Weekly, 30=Monthly, 90=Quarterly, 365=Yearly). Choose monitors via the per-type all_* flags or by selecting specific monitors, set which contacts receive it, and toggle PDF/HTML/CSV attachments and incident/maintenance inclusion. Contacts are validated for ownership; invalid frequencies or contacts return a 400.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Report name

frequency
required
integer

Frequency: 1=Daily, 7=Weekly, 30=Monthly, 90=Quarterly, 365=Yearly

theme
integer

Branding theme ID

all_monitors
integer

Include all monitors

all_uptime
integer
all_fpl
integer
all_rum
integer
all_ssl
integer
all_domain
integer
all_virus
integer
all_transaction
integer
monitors_uptime
Array of integers

Specific uptime monitor IDs to include (when not using all_uptime).

monitors_ssl
Array of integers

Specific SSL monitor IDs to include.

monitors_domain
Array of integers

Specific domain monitor IDs to include.

monitors_fpl
Array of integers

Specific speed (full page load) monitor IDs to include. The type key for speed monitors is "fpl".

monitors_transaction
Array of integers

Specific transaction monitor IDs to include.

monitors_virus
Array of integers

Specific virus monitor IDs to include.

monitors_rum
Array of integers

Specific RUM monitor IDs to include.

monitors_blacklist
Array of integers

Specific blacklist monitor IDs to include. There is no all_blacklist toggle — blacklist monitors are picked individually or covered by all_monitors.

show_all_incidents
integer
show_maintenances
integer
attach_pdf
integer
attach_html
integer
attach_csv
integer
Array of objects

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "frequency": 7,
  • "theme": 0,
  • "all_monitors": 1,
  • "all_uptime": 0,
  • "all_fpl": 0,
  • "all_rum": 0,
  • "all_ssl": 0,
  • "all_domain": 0,
  • "all_virus": 0,
  • "all_transaction": 0,
  • "monitors_uptime": [
    ],
  • "monitors_ssl": [
    ],
  • "monitors_domain": [
    ],
  • "monitors_fpl": [
    ],
  • "monitors_transaction": [
    ],
  • "monitors_virus": [
    ],
  • "monitors_rum": [
    ],
  • "monitors_blacklist": [
    ],
  • "show_all_incidents": 0,
  • "show_maintenances": 0,
  • "attach_pdf": 0,
  • "attach_html": 0,
  • "attach_csv": 0,
  • "contacts": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single report with monitors and contacts

Returns one scheduled report including its full settings plus the expanded list of monitors it covers and the contacts (individual recipients, teams, users and operators) it is delivered to. Monitors and contacts are resolved only when they belong to the report owner. The report must belong to the authenticated account; a 404 is returned if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a scheduled report

Permanently deletes a scheduled report along with its monitor and contact associations so it stops being sent. The report must belong to the authenticated account; a 404 is returned if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing scheduled report

Updates the settings, monitor selection, contacts and attachment options of an existing scheduled report. The report must belong to your account (404 otherwise); supplied contacts are validated for ownership and an invalid set returns a 400.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
name
string
frequency
integer
theme
integer
all_monitors
integer
all_uptime
integer
all_fpl
integer
all_rum
integer
all_ssl
integer
all_domain
integer
all_virus
integer
all_transaction
integer
monitors_uptime
Array of integers

Specific uptime monitor IDs to include (when not using all_uptime).

monitors_ssl
Array of integers

Specific SSL monitor IDs to include.

monitors_domain
Array of integers

Specific domain monitor IDs to include.

monitors_fpl
Array of integers

Specific speed (full page load) monitor IDs to include. The type key for speed monitors is "fpl".

monitors_transaction
Array of integers

Specific transaction monitor IDs to include.

monitors_virus
Array of integers

Specific virus monitor IDs to include.

monitors_rum
Array of integers

Specific RUM monitor IDs to include.

monitors_blacklist
Array of integers

Specific blacklist monitor IDs to include. There is no all_blacklist toggle — blacklist monitors are picked individually or covered by all_monitors.

show_all_incidents
integer
show_maintenances
integer
attach_pdf
integer
attach_html
integer
attach_csv
integer
Array of objects

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "frequency": 0,
  • "theme": 0,
  • "all_monitors": 0,
  • "all_uptime": 0,
  • "all_fpl": 0,
  • "all_rum": 0,
  • "all_ssl": 0,
  • "all_domain": 0,
  • "all_virus": 0,
  • "all_transaction": 0,
  • "monitors_uptime": [
    ],
  • "monitors_ssl": [
    ],
  • "monitors_domain": [
    ],
  • "monitors_fpl": [
    ],
  • "monitors_transaction": [
    ],
  • "monitors_virus": [
    ],
  • "monitors_rum": [
    ],
  • "monitors_blacklist": [
    ],
  • "show_all_incidents": 0,
  • "show_maintenances": 0,
  • "attach_pdf": 0,
  • "attach_html": 0,
  • "attach_csv": 0,
  • "contacts": [
    ]
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

List branding themes available for reports

Returns the branding themes (logo/colour presets) defined on your account that can be applied to report emails and exports via the theme field when creating or updating a report.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Send a report email immediately

Generates the report on demand and emails it right away to each of its email recipients that is verified and has not opted out (free and trial accounts: only the account's own login address and addresses proven through contact verification, at most 10 distinct addresses per send with the account's own address first, and at most 50 report recipients per rolling 24 hours across scheduled and on-demand reports), honouring the report's configured PDF/HTML/CSV attachments, then updates its last_sent timestamp. Your account email must be verified (403 email_not_verified otherwise), the report must belong to you (404 otherwise), and a temporary one-time report is removed after sending. Refused with 403 reports_unsubscribed when the account unsubscribed from Uptimia e-mails, and with 429 rate_limited (Retry-After header) after 5 on-demand sends per rolling 24 hours on free and trial plans or 50 on paid plans — a budget shared with POST /api/v2/reports/custom email delivery. Returns the number of emails actually sent.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success",
  • "emails_sent": 0
}

Download report as PDF

Generates the report on demand and returns it as a downloadable PDF file (application/pdf) rather than emailing it. The report must belong to your account (404 otherwise), a report with no data returns a 400, and a temporary one-time report is removed after the export.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Download report as HTML

Generates the report on demand and returns it as a downloadable standalone HTML file (text/html). The report must belong to your account (404 otherwise), a report with no data returns a 400, and a temporary one-time report is removed after the export.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Download report as CSV

Generates the report on demand and returns its data as a downloadable CSV file (text/csv) for use in spreadsheets. The report must belong to your account (404 otherwise), a report with no data returns a 400, and a temporary one-time report is removed after the export.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Create and deliver a custom one-time report

Builds an ad-hoc report for an explicit date range and monitor/contact selection and delivers it in one call according to the delivery field: email it to the chosen contacts, return it as a downloadable file in the requested format (pdf, html or csv), or publish it as a public link. Email delivery requires a verified account email (403 email_not_verified otherwise), mails only verified recipients that have not opted out (free and trial accounts: only the account's own login address and addresses proven through contact verification, at most 10 distinct addresses with the account's own address first, and at most 50 report recipients per rolling 24 hours across scheduled and on-demand reports), is refused with 403 reports_unsubscribed when the account unsubscribed from Uptimia e-mails, and with 429 rate_limited (Retry-After header) after 5 on-demand sends per rolling 24 hours on free and trial plans or 50 on paid plans, a budget shared with POST /api/v2/reports/{id}/send; download and public_link are not limited. The temporary report is removed after delivery and the response returns its id plus a url when a public link was generated.

Authorizations:
bearerAuth
Request Body schema: application/json
name
string

Report name (defaults to "Custom Report" when omitted)

date_started
integer

Start date as YYYYMMDD integer

date_ended
integer

End date as YYYYMMDD integer

Array of objects
Array of objects
show_all_incidents
integer
show_maintenances
integer
delivery
string
Enum: "email" "download" "public_link"
format
string
Enum: "pdf" "html" "csv"

Export format for download delivery

all_monitors
integer
theme
integer

Responses

Request samples

Content type
application/json
{
  • "name": "Custom Report",
  • "date_started": 20240301,
  • "date_ended": 20240331,
  • "monitors": [
    ],
  • "contacts": [
    ],
  • "show_all_incidents": 1,
  • "show_maintenances": 0,
  • "delivery": "email",
  • "format": "pdf",
  • "all_monitors": 0,
  • "theme": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Teams

Team members and multi-user access.

List all teams for the authenticated account

Returns every alerting team owned by the authenticated account, including each team members, alerting-hours window, do-not-alert days, and whether the team overrides individual members alerting settings. The metadata object reports the total count.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new team

Creates an alerting team that groups members so they can be notified together as a single contact. Requires a name and at least one member, and every member must belong to your account. Optionally override members individual alerting with a custom alerting-hours window (from must be before to) and do-not-alert days. Returns the new team ID.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Team name

members
required
Array of integers

Array of user/operator IDs

is_alerting_settings_override
boolean

Override individual alerting settings

do_not_alert_days
Array of strings
Items Enum: "mon" "tue" "wed" "thu" "fri" "sat" "sun"

Days to suppress alerts

alert_hours_from
integer

Alert window start hour (0-23)

alert_hours_to
integer

Alert window end hour (0-23)

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "members": [
    ],
  • "is_alerting_settings_override": true,
  • "do_not_alert_days": [
    ],
  • "alert_hours_from": 8,
  • "alert_hours_to": 17
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single team with full member details

Returns one team with its full roster of members (each flagged as the main account user or an operator) plus its alerting-override flag, alerting-hours window, and do-not-alert days. Returns 404 if the team does not exist or does not belong to your account.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a team

Permanently deletes a team belonging to the authenticated account; the underlying member users themselves are not deleted. Returns an error if the team could not be removed.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing team

Updates a team; only the supplied fields change while omitted fields keep their current values. The member list must remain non-empty and every member must belong to your account, and alerting-hours from must be before to. Returns 404 if the team does not exist or does not belong to your account.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
name
string
members
Array of integers
is_alerting_settings_override
boolean
do_not_alert_days
Array of strings
Items Enum: "mon" "tue" "wed" "thu" "fri" "sat" "sun"
alert_hours_from
integer
alert_hours_to
integer

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "members": [
    ],
  • "is_alerting_settings_override": true,
  • "do_not_alert_days": [
    ],
  • "alert_hours_from": 0,
  • "alert_hours_to": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Users

Account user profile information.

Roles & permissions matrix

Returns the fixed five-role model and the permission matrix, serialized from the very map the backend enforces on every request (RoleCapabilities) — the matrix shown on /cp/roles can never disagree with enforcement. Cell values: y = yes, v = usage only (plan counters, no invoices or prices), n = no, o = optional. A row may cover several capabilities that grant exactly the same roles. footnotes holds plain sentences shown under the matrix. Columns are in owner, admin, editor, viewer, billing order.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Recent team access changes

Returns the most recent access-change events on the account (invites, role changes, member removals, invite resends) for the audit card on the team-members page. Visible to the account owner and Admin operators; the sentence to render is "{actor} {detail}".

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

List all users and operators for the authenticated account

Returns the account owner (main user) and every operator (sub-user) on the account, including each one's contact email, alerting schedule (do-not-alert days and alert-hour window) and confirmation state. The response includes a metadata.total count.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new operator

Adds a new operator (sub-user) to the account with a full name, email and optional alerting schedule, and mails them an activation link. If no contacts are supplied an email contact is auto-created (unverified) from the operator's email. The full name is stored as plain text: tags, URLs, domains, e-mail addresses and control characters are removed and it is capped at 60 characters. Alert hours must form a valid range and the operator count is capped by the account plan; returns a 400 error on validation failure or plan limit. Requires the account owner's login e-mail to be verified (403 email_not_verified). Invite mails are rate-limited per account (10 per day on free and trial, 100 on paid plans, re-sends included) and per recipient address (5 per day across all accounts): 429 rate_limited with a Retry-After header.

Authorizations:
bearerAuth
Request Body schema: application/json
full_name
required
string

Operator full name

email
required
string <email>

Operator email address

Array of objects

Array of contacts for the operator

do_not_alert_days
Array of strings
Items Enum: "mon" "tue" "wed" "thu" "fri" "sat" "sun"

Days to suppress alerts

alert_hours_from
integer

Alert window start hour (0-23)

alert_hours_to
integer

Alert window end hour (0-23)

time_zone
integer

Timezone id (1-127) the alert window is evaluated in. 0 = inherit the account timezone.

Responses

Request samples

Content type
application/json
{
  • "full_name": "string",
  • "email": "[email protected]",
  • "contacts": [
    ],
  • "do_not_alert_days": [
    ],
  • "alert_hours_from": 8,
  • "alert_hours_to": 17,
  • "time_zone": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single user or operator

Retrieves one operator (sub-user) by ID with a whitelisted set of fields: email, full name and their alerting schedule (do-not-alert days and alert-hour window). The operator must belong to the authenticated account; returns 404 if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete an operator

Permanently removes an operator (sub-user) and their contacts from the account. The operator must belong to the authenticated account. This action cannot be undone and returns a 400 error if it fails.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an operator

Partially updates an operator's full name, email and alerting schedule; omitted fields keep their current values, and a full_name sent back unchanged is kept as stored. A changed full_name is stored as plain text (no links or e-mail addresses). The email must be valid and unique and the alert hours must form a valid range. Changing the email counts as one team invite: it needs a verified account owner e-mail (403 email_not_verified) and draws from the invite limits (429 rate_limited with Retry-After). The operator must belong to the authenticated account; returns 404 if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
full_name
string
email
string <email>
do_not_alert_days
Array of strings
Items Enum: "mon" "tue" "wed" "thu" "fri" "sat" "sun"
alert_hours_from
integer
alert_hours_to
integer
time_zone
integer

Timezone id (1-127) the alert window is evaluated in. 0 = inherit the account timezone.

Responses

Request samples

Content type
application/json
{
  • "full_name": "string",
  • "email": "[email protected]",
  • "do_not_alert_days": [
    ],
  • "alert_hours_from": 0,
  • "alert_hours_to": 0,
  • "time_zone": 0
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Update main user alerting preferences

Updates the alerting preferences of the authenticated account owner (main user): the do-not-alert days and the daily alert-hour window during which notifications are sent. Alert hours must form a valid range or a 400 error is returned.

Authorizations:
bearerAuth
Request Body schema: application/json
do_not_alert_days
Array of strings
Items Enum: "mon" "tue" "wed" "thu" "fri" "sat" "sun"

Days to suppress alerts

alert_hours_from
integer

Alert window start hour (0-23)

alert_hours_to
integer

Alert window end hour (0-23)

Responses

Request samples

Content type
application/json
{
  • "do_not_alert_days": [
    ],
  • "alert_hours_from": 8,
  • "alert_hours_to": 17
}

Response samples

Content type
application/json
{
  • "status": "success"
}

Re-send the activation email to a pending operator

Re-sends the activation (direct-access) email for an operator who has not yet activated their access, with a freshly minted activation link valid 14 days. Owner + Admin; returns 404 if the operator does not exist, does not belong to the account, or has already activated. Requires the account owner's login e-mail to be verified (403 email_not_verified). One re-send per pending member per hour, and each re-send counts toward the account's daily invite budget and the recipient's daily limit (429 rate_limited with a Retry-After header).

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Reset a team member's two-factor authentication

Turns off two-factor authentication for one operator (sub-user) and removes any authenticator app and recovery codes set up for it, so a member who can no longer complete their own 2FA (lost mailbox or phone) can sign in again and re-enrol. Owner + Admin only (team management), account-scoped, and written to the team audit log and to the account activity log as a security row (details.event twofa_reset_by_admin); the member is emailed that it happened. Does not affect the account owner's own 2FA, and a member cannot reset their own (403). Returns 400 when the member already has 2FA off.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Settings

Account profile and timezone settings.

List available timezones

Returns the complete map of supported timezone IDs to their human-readable labels, intended to populate a timezone picker before setting the time_zone field on the user profile. This endpoint requires no parameters.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": { }
}

Get current user profile

Returns the authenticated user's profile (name, email, timezone, custom email sender, 2FA and login-email flags) plus the account plan, trial state and per-monitor-type usage versus plan limits. When signed in as an operator the operator's own name and email are returned along with impersonation context.

Authorizations:
bearerAuth
header Parameters
X-Browser-Time-Zone
string
Example: Europe/Vilnius

IANA zone of the caller's browser (Intl.DateTimeFormat().resolvedOptions().timeZone). Fills the account zone once when it is not set (owner sessions only)

Responses

Response samples

Content type
application/json
{
  • "data": {
    },
  • "plan": {
    }
}

Update user profile

Updates the authenticated user's full name, email, timezone and custom email sender. The email must be valid and unique and the custom sender must be 3-11 alphanumeric characters. A changed name is cleaned of links, domains and e-mail addresses and cut to 60 characters (400 invalid_name when nothing is left); an unchanged name is kept as stored. Changing the account e-mail needs the current password and is limited to 3 changes per account per 24 hours (429). For operator sessions the operator's own name and email are returned so the form is not overwritten with the owner's values; returns a 400 error on validation failure.

Authorizations:
bearerAuth
Request Body schema: application/json
full_name
string
email
string <email>
time_zone
string
custom_sender
string

Responses

Request samples

Content type
application/json
{
  • "full_name": "string",
  • "email": "[email protected]",
  • "time_zone": "string",
  • "custom_sender": "string"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Branding

Branding themes (colors and logos) for emails and reports.

List all branding themes for the authenticated account

Returns every branding theme owned by the account, each with its ID, name, a fully-qualified logo URL (relative filenames are expanded to the CDN uploads base URL), the full colour map, and live usage counts (how many scheduled reports and monitors currently reference the theme). Themes control the colours and logo applied to email reports and status pages. The response includes a metadata.total count.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "metadata": {
    }
}

Create a new branding theme

Creates a new branding theme for the account with a required name and an optional map of colour overrides; unspecified colours fall back to defaults. A logo is added separately via the logo upload endpoint. Returns the new theme ID, or a 400 error if the name is missing or creation fails.

Authorizations:
bearerAuth
Request Body schema: application/json
name
required
string

Theme name

colors
object

Color overrides

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "colors": { }
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get a single branding theme with all color data

Retrieves one branding theme by ID with its name, logo URL and the full set of colour fields (backgrounds, text, headers, links and separators). The theme must belong to the authenticated account; returns 404 if it does not exist or is not yours.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete a branding theme

Permanently deletes a branding theme from the account. The theme must belong to the authenticated account; returns 404 if not found. This action cannot be undone.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}

Update an existing branding theme

Updates a branding theme's name and colours; supplied colour fields are merged over the theme's existing colours and the current logo is preserved. Returns the full updated theme. The theme must belong to the authenticated account; returns 404 if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: application/json
name
string
colors
object

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "colors": { }
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Duplicate a branding theme

Creates a copy of an existing theme — same colours, name suffixed with " (copy)", and a physical copy of the logo file (so deleting either theme later cannot orphan the other's logo). The source theme must belong to the authenticated account; returns 404 if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Upload a logo for a branding theme

Uploads a logo image (PNG, JPG or SVG, max 2MB; SVGs are sanitized server-side) via multipart form-data and attaches it to the theme, replacing any previous logo. Returns the fully-qualified logo URL. The theme must belong to the authenticated account; returns 404 if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+
Request Body schema: multipart/form-data
logo
string <binary>

Logo file (PNG, JPG or SVG, max 2MB). SVGs are sanitized server-side.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Remove the logo from a branding theme

Clears the logo from a branding theme while keeping the theme and its colours intact. The theme must belong to the authenticated account; returns 404 if not found.

Authorizations:
bearerAuth
path Parameters
id
required
integer\d+

Responses

Response samples

Content type
application/json
{
  • "status": "success"
}