Docs / Monitors / API monitors and assertions

API monitors and assertions

Probe JSON APIs with custom methods, headers and auth, then assert on status, latency, headers and JSON body values with JSONPath.
Last updated · 5 min read

An API monitor sends a fully-configured HTTP request — method, headers, authentication, body — and evaluates an ordered list of assertions against the response. The check passes only when every assertion passes; each assertion's pass/fail, expected and actual values are recorded on the result so you can see exactly what broke.

Need a whole flow — log in, extract a token, call an authenticated endpoint? Chain up to 10 of these requests with variable extraction in a Transaction monitor (Business plan and up).

Create an API monitor

  1. Go to /monitors/create and choose Type: API.
  2. Set the shared fields (project, name, interval, ownership attestation) and the Target — the endpoint URL, starting with http:// or https://.
  3. Configure the request and at least one assertion (the form requires a minimum of one), then save.

Request configuration

  • HTTP method — GET, POST, PUT, PATCH, DELETE or HEAD.
  • Request headers — repeatable name/value rows sent verbatim (e.g. Accept: application/json).
  • Authentication — one of:
    • None
    • Bearer token — sent as Authorization: Bearer <token>.
    • Basic auth — username + password, sent as an Authorization: Basic header.
    • API key header — a header name (e.g. X-API-Key) plus the key value.
  • Request body — free text (e.g. a JSON payload), sent only for POST, PUT and PATCH.

Note: Secrets (bearer token, basic password, API key value) are stored encrypted and never shown again. On the edit form, leave the secret field blank to keep the saved value. In check results and logs, secret headers and auth values are always masked.

Assertions

Each assertion is a row of type, optional path, operator and expected value.

Assertion types

Type What it tests Uses the path field?
Status code The HTTP response status No
Latency (ms) Total response time in milliseconds No
JSON path A value extracted from the JSON body Yes — the JSONPath
Response header A response header's value Yes — the header name
Body contains The raw response body No

Operators

Operator Meaning
equals / not equals Loose comparison — "200" equals 200, "true" equals true
greater than / less than Numeric comparison (both sides must be numeric)
contains Substring match; on a list (from a wildcard JSONPath), membership
matches (regex) The actual value matches the regular expression

For Body contains, equals is treated as contains automatically.

Examples

  • Status code equals 200
  • Latency (ms) less than 800
  • JSON path $.status equals ok
  • JSON path $.data.items[*].sku contains WIDGET-1
  • Response header content-type contains application/json
  • Body contains — expected "healthy":true

JSONPath syntax

CompleteStatus supports a focused JSONPath subset:

Syntax Meaning Example
$ The root (every path starts here) $
.key Child by name (letters, digits, _, -) $.data.user.name
['key'] or ["key"] Child by name, any characters $['odd key.name']
[n] Array element by index (negative counts from the end) $.items[0].sku, $.items[-1]
[*] or .* Wildcard over an array or object $.items[*].sku

Wildcards fan out: $.items[*].sku yields the list of every item's sku. With a wildcard path, equals compares the whole list, and contains checks whether any element matches — usually what you want. A path with no wildcard yields the single first match, or nothing when absent (an absent value fails equals and passes not equals against anything non-null).

Not supported: recursive descent (..), filter expressions ([?(...)]), slices ([0:2]) and unions.

How the check behaves

  • If you somehow have an API monitor with no assertions, it falls back to "any 2xx/3xx status passes".
  • The whole check is time-boxed to 30 seconds, retries once on a network error, follows redirects (each hop is re-validated against internal networks), and runs from a single probe region.
  • On failure, the result's detail lists every assertion with its expected vs. actual value plus a N assertion(s) failed error; a confirmed failure (two consecutive) opens an incident, exactly like uptime monitors — see HTTP uptime monitors.

Content-change monitoring

If what you want is "tell me when this page changes" rather than "assert this value", use the separate Change detection monitor type:

  • Comparison modeText (hash the normalized text content) or Visual (text hash plus a screenshot captured on change).
  • Render JS with headless Chrome — enable for JavaScript-rendered pages; off, the raw HTML is compared.
  • CSS selector (optional) — scope the comparison to one region, e.g. #main or article.post. A single simple selector (tag, #id, .class or a combination of those) is supported; descendant selectors like #main .content are not, and an unmatched selector falls back to the whole page.
  • Ignore patterns — regex patterns stripped before hashing, for content that legitimately changes every load (CSRF tokens, timestamps): csrf-token="[^"]+".

The first check stores a baseline. A later change fails the check and, once confirmed, opens an incident carrying a unified diff of what was added and removed (and a screenshot in visual mode). The last 50 snapshots are kept per monitor.

There is also a simpler Keyword monitor type: assert a literal string or regex is present (or absent) in a page, with a case-sensitivity toggle — a lighter tool for "did the error page appear?" checks.

Related guides

Ready to try it?
10 monitors, security grading and email-authentication checks on the free tier — commercial use allowed.
Start free Run a free check
Uptime is table stakes. We watch the rest — security headers, email authentication, certs and DNS, with the fix attached.
Start free
Company
© 2026 CompleteStatus. All rights reserved. CompleteStatus — operated in the United States · support@completestatus.com