# Run summary with trend

**GET** `/api/stats/summary`

Totals for a window, with the window before it for comparison, and the workflows failing most.

Needs [an API token](https://docs.gorunner.io/api/authentication#scopes) with the **Read** permission for runs (`run:read`).

## Parameters

### Query

- `window` · Optional · string: `24h`, `7d` (the default) or `30d`, ending now. Anything else reads as 7d.
- `environment` · Optional · string: `production` (the default), `test` or `all`.

## Read it

`successRate` is worked ÷ (worked + failed): cancelled runs are left out. It is 0 when nothing finished, so check `total` before showing it. `avgDurationMs` averages runs that worked.

`previous` is the same length of time just before. When `previousCovered` is `false`, the records don’t reach back that far, so don’t compare.

`topFailing` holds up to 5 workflows with the most failed runs; `failingWorkflows` counts all with at least one. `activeWorkflows` is the live workflows now.

## Responses

- 200 OK

  The totals.

- 403 `FORBIDDEN`

  The token lacks the **Read** permission for runs.

- 500 `INTERNAL_ERROR`

  The totals couldn’t be read. Try again.

Any call can also answer: [`401 UNAUTHORIZED`](https://docs.gorunner.io/errors#UNAUTHORIZED) · [`401 TOKEN_ENDED`](https://docs.gorunner.io/errors#TOKEN_ENDED) · [`403 TOKEN_SURFACE_OFF`](https://docs.gorunner.io/errors#TOKEN_SURFACE_OFF) · [`403 FEATURE_OFF`](https://docs.gorunner.io/errors#FEATURE_OFF) · [`403 EMBED_NOT_ALLOWED`](https://docs.gorunner.io/errors#EMBED_NOT_ALLOWED) · [`403 EMBED_NOT_AVAILABLE`](https://docs.gorunner.io/errors#EMBED_NOT_AVAILABLE) · [`403 ACCOUNT_SUSPENDED`](https://docs.gorunner.io/errors#ACCOUNT_SUSPENDED) · [`429 RATE_LIMITED`](https://docs.gorunner.io/errors#RATE_LIMITED) · [`503 BUSY`](https://docs.gorunner.io/errors#BUSY) · [`503 PAUSED`](https://docs.gorunner.io/errors#PAUSED) · [`503 SERVICE_UNAVAILABLE`](https://docs.gorunner.io/errors#SERVICE_UNAVAILABLE). See [Errors](https://docs.gorunner.io/api/errors#by-status).

Request

**curl**

```bash
GORUNNER="https://api.gorunner.io"
GORUNNER_TOKEN="grt_…"  # needs Read for runs

curl "$GORUNNER/api/stats/summary?window=7d" \
  -H "Authorization: Bearer $GORUNNER_TOKEN"
```

**JavaScript**

```js
const GORUNNER = "https://api.gorunner.io";
const TOKEN = process.env.GORUNNER_TOKEN;

const res = await fetch(
  `${GORUNNER}/api/stats/summary?window=7d`,
  {
    headers: { Authorization: `Bearer ${TOKEN}` },
  },
);
const { data } = await res.json();
```

**Python**

```python
import os, requests

GORUNNER = "https://api.gorunner.io"
TOKEN = os.environ["GORUNNER_TOKEN"]

res = requests.get(
    f"{GORUNNER}/api/stats/summary",
    params={"window": "7d"},
    headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]
```

Response · 200 OK

```json
{
  "data": {
    "window": "7d",
    "current": {
      "total": 120,
      "completed": 108,
      "failed": 10,
      "cancelled": 2,
      "inFlight": 0,
      "successRate": 0.915,
      "avgDurationMs": 1840
    },
    "previous": {
      "total": 96,
      "completed": 90,
      "failed": 6,
      "cancelled": 0,
      "inFlight": 0,
      "successRate": 0.9375,
      "avgDurationMs": 1720
    },
    "previousCovered": true,
    "activeWorkflows": 6,
    "failingWorkflows": 1,
    "topFailing": [
      {
        "workflowId": "3b1e5c2a-7d4f-4e8b-a1c6-5f2d9b0e7a31",
        "name": "Order intake",
        "failed": 10,
        "total": 64
      }
    ]
  }
}
```

**Every field**

It takes no body.

### Response · 200 OK

- `data` · object
  - `window` · string: One of `24h`, `7d`, `30d`.
  - `current` · object: Run counts for one window. `successRate` = completed ÷ (completed + failed): cancelled runs are left out (someone stopped them, which says nothing about whether the workflow works; `cancelled` still counts them). Reported as 0 when nothing completed or failed in the window — render — when `total` is 0 rather than reading 0 as "everything failed". Releases up to v2026.10.5 counted cancelled runs as not worked. `avgDurationMs` averages COMPLETED runs only.
    - `total` · integer
    - `completed` · integer
    - `failed` · integer
    - `cancelled` · integer
    - `inFlight` · integer: Runs still pending/running/paused whose started_at falls in the window.
    - `successRate` · number
    - `avgDurationMs` · number
  - `previous` · object: Run counts for one window. `successRate` = completed ÷ (completed + failed): cancelled runs are left out (someone stopped them, which says nothing about whether the workflow works; `cancelled` still counts them). Reported as 0 when nothing completed or failed in the window — render — when `total` is 0 rather than reading 0 as "everything failed". Releases up to v2026.10.5 counted cancelled runs as not worked. `avgDurationMs` averages COMPLETED runs only. The same fields as `data.current` above.
  - `previousCovered` · boolean: Whether the records hold the whole of the previous window: the workspace existed when it began, and run retention has not cut into it. When false, `previous` counts only part of that window and is no basis for a trend. Absent from servers before 2026-10-22.
  - `activeWorkflows` · integer: The workspace’s ACTIVE (published) workflows right now — not windowed.
  - `failingWorkflows` · integer: How many DISTINCT workflows had at least one failed run in the window — the whole of what `topFailing` shows the top of.
  - `topFailing` · array of objects: Up to 5 workflows with the most failed runs in the window, most-failing first. Workflows with zero failures are excluded; always `[]` rather than null.
    - `workflowId` · UUID
    - `name` · string
    - `failed` · integer
    - `total` · integer

Related: [Runs over time](https://docs.gorunner.io/api/stats/get-stats-timeseries) · [The last 7 days](https://docs.gorunner.io/api/stats/get-stats-week) · [Count runs by state](https://docs.gorunner.io/api/stats/count-runs)

Source: https://docs.gorunner.io/api/stats/get-stats-summary
