One run's full detail
One run's complete timeline, declared expectations judged against its outcome, output excerpt and, for a CI run, provider metadata — the trace-level detail GET /api/v1/runs and GET /api/v1/checks/{id}/runs deliberately omit.
events is the single time axis: every ping this run recorded (start, log, note, blocked, success, fail, cancel), interleaved with its step progress markers, plus one synthetic incident_opened event when an incident correlates with this rid. Ordered by at ascending; two events that tie on timestamp keep a stable source order (a run's own fail ping always precedes the incident_opened event it triggered, never the reverse). A step is listed once, as its step event, never twice.
events is capped at 200 entries. A run with more pings than that (a verbose CI job streaming per-line log pings is the realistic case) has the middle of its timeline dropped, oldest kept first; events_truncated is true whenever this happened. The run's own terminal ping (success/fail/cancel) is fetched independently of this cap and is always the last entry in events when one exists, even if it would otherwise have fallen past position 200 — so outcome, started_at, ended_at, duration_ms, output_excerpt and ci are never wrong because of this cap; only the interior of a very chatty run's displayed timeline is what gets thinned.
outcome, started_at, ended_at, duration_ms, title and exit_code are computed by the identical rule GET /api/v1/runs uses (see that endpoint's description), from this run's own real pings rather than a summary row — the two endpoints can never disagree about a run they both serve.
A run with spans but no pings (traced: true, see Run.traced) answers 200 with an empty events, its spans, and the outcome its spans give. A rid with neither pings nor spans is 404.
assertions reports every expectation declared via POST .../expectations, each judged against the run's terminal ping body using the same evaluator that judges the run when it closes. verdict is not_evaluated when the run has no terminal ping yet (there is no body to judge against), else pass or fail; failure carries the evaluator's one-line reason on fail and is null otherwise.
ci merges the ci_meta of every ping on this run, field by field, a later non-empty value winning, so the terminal ping's failing stage and duration sit beside the start ping's commit and run URL. null for an agent/heartbeat run with no CI provider attached.
newer_rid and older_rid are this MONITOR's runs either side of this one in time: the run that started just after it, and the one just before. Both are rids on the check named in the path, so a caller builds the neighbour's URL by swapping the rid segment. Either is null at that end of the monitor's own history (within the 90-day ping window), which is a fact about the monitor rather than about what a client happens to have listed, so a run reached by a direct link knows its neighbours without fetching a list first. Runs of OTHER monitors are never named here, however a list happens to be filtered.
spans is this run's OTLP spans, when any exporter sent them, in tree order: parents before children, siblings ordered by start time, and an orphan (a span whose parent_span_id matches no span in this same run) appended after every real root's subtree. Capped at 2,000 (spans_truncated); the separate per-run storage cap surfaces as spans_dropped, null when the run has no span stats at all. span_count, tokens_in, tokens_out and cost_usd (inherited from Run) are null the same way when the run was never traced.
Spans themselves are retained for 30 days; span_count, tokens_in, tokens_out and cost_usd survive for 90. A run between 31 and 90 days old therefore reports those four stats normally while spans comes back an empty array — retention, not a bug.
title, output_excerpt, events[].body, events[].label, steps[].name and every string field on spans[] are free text the run itself supplied (a ping's body_excerpt, a step's name, a run's title, an OTLP exporter's span content); render them as text, never interpret them as markup.
Request
- Base URL: https://app.lastping.dev
- URL: https://app.lastping.dev/api/v1/checks/{id}/runs/{rid}
- Auth: API key in header X-Api-Key
Response
The run's full detail.
Example response
{
"check_id": "550e8400-e29b-41d4-a716-446655440000",
"check_name": "Nightly backup",
"project": "reddit-bot",
"failure_cause": "upstream",
"upstream_error": "server_error",
"rid": "9876543210",
"title": "nightly backup",
"outcome": "failed",
"started_at": "2026-09-12T08:00:00Z",
"ended_at": "2026-09-12T08:14:00Z",
"duration_ms": 840000,
"step_count": 3,
"exit_code": 1,
"incident": {
"id": 4821,
"cause": "fail",
"opened_at": "2026-09-12T08:14:00Z",
"closed_at": "2026-09-12T08:45:00Z"
},
"span_count": 14,
"tokens_in": 1820,
"tokens_out": 340,
"cost_usd": "0.021400",
"cost_source": "estimated",
"agent_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"agent_name": "triage-bot",
"source_name": "triage-bot",
"events": [
{
"kind": "fail",
"at": "2026-09-12T08:14:00Z",
"label": "fail",
"body": "exit 1: tests failed",
"step_seq": 2
}
],
"steps": [
{
"seq": 2,
"name": "db migrate",
"at": "2026-07-20T10:04:00Z"
}
],
"assertions": [
{
"kind": "contains",
"value": "ok",
"verdict": "pass"
}
],
"output_excerpt": "exit 1: tests failed",
"ci": {
"run_url": "https://github.com/acme/api/actions/runs/128734",
"commit_sha": "a1b2c3d4e5f6",
"branch": "main",
"actor": "octocat",
"failing_stage": "test",
"duration_s": 128734
},
"spans": [
{
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"parent_span_id": "00f067aa0ba90111",
"name": "chat.completions",
"kind": "client",
"status": "ok",
"started_at": "2026-09-17T10:00:00.120Z",
"ended_at": "2026-09-17T10:00:01.480Z",
"duration_ms": 1360,
"gen_ai": {
"system": "anthropic",
"model": "claude-sonnet-4-5",
"tokens_in": 512,
"tokens_out": 128,
"cost_usd": "0.003400",
"cost_source": "estimated"
},
"attributes": {
"http.method": "POST",
"http.status_code": 200
},
"source_name": "triage-bot",
"peer_kind": "model",
"peer_name": "anthropic claude-sonnet-4-5"
}
],
"newer_rid": "run-2026-08-23-002",
"older_rid": "run-2026-08-22-014"
}Changes
No recorded changes to this operation across all 2 revisions of this API.