---
title: "List monitor runs"
method: GET
path: "/monitors/{id}/runs"
tags: ["monitors"]
---

# List monitor runs

`GET /monitors/{id}/runs`

## Request

- Base URL: `https://www.socialcrawl.dev/v1`
- URL: `https://www.socialcrawl.dev/v1/monitors/{id}/runs`
- Auth: API key in header `x-api-key`

Returns the monitor's run history, newest first, each with the credits it used, its per-leg envelope, any alerts it fired, and the delivery record for its webhook. Reads stored runs; it never calls an upstream and is free. Pass `include=result` to get each run's stored result inline.

## Path parameters

- `id` string, required

## Query parameters

- `status` 'ok' | 'partial' | 'failed' | 'skipped'
- `from` string, date-time
- `to` string, date-time
- `include` string
- `cursor` string
- `limit` integer

## Response `200`

A page of runs

- object
  - `items` object[]
    - `alerts_fired` object[]: Alert rules that fired on this run, with their from/to values.
    - `credits_used` integer
    - `finished_at` string, date-time, nullable
    - `id` string
    - `legs` object[]: The recipe's per-leg transparency envelope: each leg's endpoint, status, credits and latency.
    - `monitor_id` string
    - `deltas` object, nullable: Numbers-only monitors, with `include=numbers`: the change against the previous `ok` or `partial` run, `{ rows: { <row_id>: { <metric>: { prev, cur, abs, pct } } }, rows_new, rows_gone }`. `pct` is null when the previous value was 0. Null on the first run.
    - `numbers` object, nullable: Numbers-only monitors, with `include=numbers`: the tracked numbers of this run, `{ <row_id>: { <metric>: number | null } }`. Numbers read off the page itself sit under the row id `_`.
    - `result` unknown
    - `scheduled_for` string, date-time
    - `skip_reason` string, nullable: Why a `skipped` run never executed, for example an insufficient credit balance. A skipped run is never charged.
    - `started_at` string, date-time, nullable
    - `status` 'ok' | 'partial' | 'failed' | 'skipped'
    - `webhook_delivery` object, nullable: Delivery record stamped by the QStash callbacks: `{attempts, lastStatus, deliveredAt, failedAt}`.
  - `next_cursor` string, nullable

## Other responses

- `400`: Invalid request - missing or malformed parameters
- `401`: Unauthorized - missing or invalid API key
- `404`: Not found - the endpoint does not exist, or the requested resource was not found upstream
- `429`: Rate or concurrency limit exceeded. `RATE_LIMITED`: more than 600 requests in a 1-minute sliding window on this API key (headers `X-RateLimit-Limit`/`Remaining`/`Reset`; `Retry-After` is seconds until the window resets). `CONCURRENCY_LIMIT`: more than 50 simultaneous in-flight requests (headers `X-Concurrency-Limit`/`Remaining`; short static `Retry-After`). Both are unbilled. Honor `Retry-After`, then back off with jitter. See /docs/rate-limits.
- `500`: Internal server error - an immediate refund is attempted; credits_used reports the committed net charge and exact compensation is queued if that refund cannot commit

---

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