---
title: "Get an audit run's report"
method: GET
path: "/v1/agent-runs/{id}/report"
tags: ["Audits"]
---

# Get an audit run's report

`GET /v1/agent-runs/{id}/report`

## Request

- Base URL: `https://api.squirrelscan.com`
- URL: `https://api.squirrelscan.com/v1/agent-runs/{id}/report`
- Auth: HTTP bearer

Fetch the summarized report data for a completed run.

**Polling pattern:** this endpoint returns `404` both when the run/report does not exist AND while a valid run's report is not generated yet. To distinguish the two, poll `GET /v1/agent-runs/{id}` and wait for `status: "completed"` before fetching the report — that is the canonical way to track progress. As a convenience, the "not ready yet" 404 additionally carries the run's current status under `error.runStatus` (e.g. `{ "error": { "code": "NOT_FOUND", "message": "Report not available yet", "runStatus": "running" } }`), so a client can keep polling this endpoint alone if it prefers. **Footgun:** only keep polling while `error.runStatus` is a non-terminal state (`pending`/`running`); a `404` with `error.runStatus: "completed"` (or `"failed"`/`"cancelled"`, or a `404` with NO `error.runStatus` at all) means the report is genuinely missing/unavailable — stop polling.

## Path parameters

- `id` string, required

## Response `200`

Report summary + scored issues for the run.

- AuditRunReport: Summarized report data + top scored issues for a completed run, wrapped under `report`.
  - `report` object, required
    - `id` string, required
    - `url` string, uri, required
    - `visibility` 'public' | 'unlisted' | 'private', required
    - `siteKey` string
    - `baseUrl` string, uri, required
    - `timestamp` string, date-time
    - `totalPages` integer
    - `failed` integer
    - `warnings` integer
    - `passed` integer
    - `healthScore` number, nullable: The precise overall score from the report (a float, e.g. 82.5), read straight from the report JSON. Intentionally a `number` here — the rounded `integer` `healthScore` on `AuditRun`/`Report` mirrors the persisted DB column, while this is the unrounded source value.
    - `categories` object[]
    - `topIssues` object[]: Up to 25 failing/warning checks, fails first.
      - `ruleId` string
      - `ruleName` string
      - `category` string
      - `subcategory` string
      - `severity` 'error' | 'warning'
      - `status` 'fail' | 'warn'
      - `message` string
      - `pageUrl` string, nullable
    - `history` object[]

## Other responses

- `401`: Missing or invalid credentials (including the shared auth middleware: no/invalid bearer token). Typed envelope with code `UNAUTHORIZED`. Branch on the `401` status, not the message.
- `404`: Run or report not found, OR the run's report is not generated yet. When not-ready, `error.runStatus` holds the run's current status (`pending`/`running`/...); keep polling.
- `429`: Too many requests. Retry after the window resets. (Rate limiting is planned — issue #69 — these headers document the intended contract.)

---

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