---
title: "Replace output assertions for a check"
method: PUT
path: "/api/v1/checks/{id}/assertions"
tags: ["Checks"]
---

# Replace output assertions for a check

`PUT /api/v1/checks/{id}/assertions`

## Request

- Base URL: `https://app.lastping.dev`
- URL: `https://app.lastping.dev/api/v1/checks/{id}/assertions`
- Auth: API key in header `X-Api-Key`

Replaces the complete set of output assertions for the check
(**replace-the-set** semantics) — the request body is the new set in
its entirety; assertions absent from the body are deleted.

Every assertion is validated before any write, using the exact
evaluator that runs on every successful ping
(the same validation everywhere): an uncompilable regexp, a `matches`
pattern over 1000 bytes, a missing required field for the given
`kind`, or a `json_path` containing `[`, `*` or `$` all fail the
request with `400` and **nothing is written**. The `400` message
names the offending assertion by its `name`.

At most **20 assertions** are allowed per check — the same cap
applied to tags — because assertions are evaluated on every
successful ping and an unbounded set is an unbounded per-ping cost.
A request over the cap is rejected with `400` before any per-assertion
validation runs.

Returns the resulting set (same shape as `GET`) on success.

## Request body

- object
  - `assertions` Assertion[], required: The complete new set of assertions (at most 20). An empty array clears all assertions.
    - `id` string, uuid: Server-assigned. Present on GET/PUT responses; ignored if sent in a PUT request body.
    - `name` string, required: Human label for the assertion. Appears in the alert's failure reason.
    - `kind` 'contains' | 'not_contains' | 'matches' | 'json_path', required: How the body is inspected. `contains`/`not_contains` and `matches` read `value` against the raw body text. `json_path` decodes the body as JSON and compares the value at `path` to `value` using `op`.
    - `value` string: Required for `contains`, `not_contains` and `matches` (substring or RE2 pattern, max 1000 bytes). For `json_path`, the expected value to compare against — compared numerically if both the extracted value and `value` parse as a number (so `"12.5" > "3"` is true), otherwise compared as strings.
    - `path` string: Required for `json_path` only. A dotted path into the body decoded as JSON, e.g. `"result.rows_processed"`. Must not contain `[`, `*` or `$` — this is a fixed lookup, not a query.
    - `op` 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte': Required for `json_path` only. Comparison operator between the extracted value and `value`.

## Response `200`

Resulting output assertions after applying the replace-the-set operation.

- AssertionsResponse: The complete set of output assertions configured for a check.
  - `assertions` Assertion[], required: Always a JSON array, empty when the check has no assertions configured.
    - `id` string, uuid: Server-assigned. Present on GET/PUT responses; ignored if sent in a PUT request body.
    - `name` string, required: Human label for the assertion. Appears in the alert's failure reason.
    - `kind` 'contains' | 'not_contains' | 'matches' | 'json_path', required: How the body is inspected. `contains`/`not_contains` and `matches` read `value` against the raw body text. `json_path` decodes the body as JSON and compares the value at `path` to `value` using `op`.
    - `value` string: Required for `contains`, `not_contains` and `matches` (substring or RE2 pattern, max 1000 bytes). For `json_path`, the expected value to compare against — compared numerically if both the extracted value and `value` parse as a number (so `"12.5" > "3"` is true), otherwise compared as strings.
    - `path` string: Required for `json_path` only. A dotted path into the body decoded as JSON, e.g. `"result.rows_processed"`. Must not contain `[`, `*` or `$` — this is a fixed lookup, not a query.
    - `op` 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte': Required for `json_path` only. Comparison operator between the extracted value and `value`.

## Other responses

- `400`: Invalid request — one of: - More than 20 assertions in the request. - An assertion fails validation: missing `name`, missing `value`/`path`/`op` for the given `kind`, an uncompilable `matches` regexp, a `matches` pattern over 1000 bytes, an invalid `op`, or a `json_path` containing `[`, `*` or `$`. - Malformed JSON body. Nothing is written when any entry fails validation.
- `401`: Missing or invalid API key.
- `404`: Check not found in this project.
- `429`: Too many requests. The per-principal fixed-window rate limit has been exceeded. Retry after the number of seconds indicated by the `Retry-After` response header. The problem body's `code` is `RATE_LIMITED`. It names this limiter specifically, so a client can tell it apart from the application-level throttles that also answer 429 with their own codes and their own, much longer, `Retry-After` values (`TEST_PING_RATE_LIMITED`, `TOO_MANY_ATTEMPTS`). Back off globally on `RATE_LIMITED`; back off on the one operation for the others. The principal is the API key for a key-authenticated request and the USER for a browser session, so every tab one person has open shares one budget.

---

[API](https://skmtc.dev/lastping/apis/lastping-management-api.md) · [All operations](https://skmtc.dev/lastping/apis/lastping-management-api/llms.txt) · [OpenAPI document](https://skmtc.dev/lastping/apis/lastping-management-api/revisions/bbc6eda91c46?raw)
