---
title: "Get Recent Anomalies"
method: GET
path: "/api/admin/anomalies/recent"
tags: ["admin"]
---

# Get Recent Anomalies

`GET /api/admin/anomalies/recent`

## Request

- Base URL: `https://api.equity-rank.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.equity-rank.com/api/admin/anomalies/recent`
- Auth: HTTP bearer

Return last `hours` of av_anomaly_log rows + aggregated summary.

Response shape:
    {
        "rows": [ {id, created_at, ticker, field_path, rule, raw_value,
                   fetch_function, severity, root_cause}, ... ],
        "summary": {
            "total": int,
            "unexplained": int,     # rows with root_cause IS NULL
            "known_benign": int,    # rows auto-classified by _derive_root_cause
            "root_causes": {class: count, ...},  # non-null classes only
            "categories": {av_bounds, av_format, calc_failures, zero_weight},
            "top_rules":   [[rule, count], ... up to 10 entries desc],
            "top_tickers": [[ticker, count], ... up to 10 entries desc],
            "truncated": bool,      # True iff the scan cap bounded the read
            "scan_cap": int,        # ANOMALY_SCAN_CAP
        },
        "generated_at": ISO timestamp,
        "hours": int,
    }

Admin-only. Graceful degradation on Supabase failure: returns 200 with
empty rows + zero counts (see module docstring).

## Query parameters

- `hours` integer

## Response `200`

Successful Response

- object

## Other responses

- `422`: Validation Error

---

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