---
title: "Get the 90-day signal exception strip for a check"
method: GET
path: "/api/v1/checks/{id}/signal"
tags: ["Checks"]
---

# Get the 90-day signal exception strip for a check

`GET /api/v1/checks/{id}/signal`

## Request

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

Returns the same 90-day history the dashboard's monitor detail page
renders as its signal strip, as JSON. **Only exception days** (`down`,
`nodata`) **are included** — an up day emits nothing, so a caller
renders every `offset` from 1 to 90 that is absent from `exceptions`
as up. `late` is never emitted: this strip distinguishes down vs. up
vs. no-data over a calendar day, not the live "late" status a check
can be in right now.

`nodata` is all-or-nothing per check, not per day: it appears when
the monitor has **no ping history at all** — every one of the 90
days comes back `nodata` in that case, never a mix of `nodata` and
`down`/absent-meaning-up days. A monitor with any ping history gets
ordinary `down`-or-absent days for the whole window instead.

404 if the check does not exist in the authenticated project (no
existence oracle — cross-tenant access is indistinguishable from a
non-existent id).

**Console stability note.** This response is shaped by a console screen:
the fields are the ones that screen draws, in the grouping it draws them
in. It stays published because reading it is a reasonable thing to
automate, and no field will be removed or change meaning without a
version. Fields may be ADDED as the screen grows, so treat unknown keys
as normal rather than as an error.

## Response `200`

The 90-day exception list.

- Signal: The body of GET /api/v1/checks/{id}/signal.
  - `days` integer, required: Width of the tracked window in days. Always 90.
  - `exceptions` SignalException[], required
    - `offset` integer, required: How many days ago this exception fell, ranging **1 to 90**: 1 means yesterday, 90 means ninety days ago. Today has no slot — the tracked window ends at yesterday, so `offset` is never 0.
    - `state` 'down' | 'nodata', required: `late` is never emitted here — the signal strip only ever distinguishes down-vs-up-vs-no-data over a calendar day, not the live "late" status a check can be in right now.
    - `date` string, date, required: The exception's calendar date, UTC.

## Other responses

- `400`: id is not a valid UUID.
- `401`: Missing or invalid API key.
- `404`: Check not found in this project (`MONITOR_NOT_FOUND`).
- `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)
