---
title: "Auth-event audit log — newest-first, paginated (SEC-AUTH-014)"
method: GET
path: "/api/v1/admin/auth-events"
tags: ["admin"]
---

# Auth-event audit log — newest-first, paginated (SEC-AUTH-014)

`GET /api/v1/admin/auth-events`

## Request

- Base URL: `https://api.badgeia.com`
- URL: `https://api.badgeia.com/api/v1/admin/auth-events`
- Auth: none declared

Return the auth-event audit log, newest first.

SEC-AUTH-014. Backs an operator's account-takeover / brute-force
investigation: "what IPs hit this email, when, and did any succeed?"

Authorization:
    - Anonymous → 401 (handled by the auth dep on `require_admin`).
    - Authenticated non-admin → 403 (handled by `require_admin`).
    - Admin (email in `ADMIN_EMAILS`) → 200.

Pagination (CLAUDE.md rule #9): `page_size` caps at 100 — `page_size=200`
returns 422 via the `le=100` Query bound, matching every other paginated
endpoint. `page` is 1-based.

Filters (both optional, exact match, AND-combined):
    - `event_type` — e.g. `login_failure`.
    - `email` — the email the caller presented at auth time.

Response shape:
    {
      "items": [
        {"id": "<uuid>", "event_type": "login_failure", "user_id": "<uuid|null>",
         "email": "a@b.com", "ip_address": "1.2.3.4", "user_agent": "...",
         "success": false, "detail": "bad_password",
         "created_at": "<ISO8601 UTC>"},
        ...
      ],
      "total": <int>, "page": <int>, "page_size": <int>, "pages": <int>
    }

Privacy: this surface intentionally DOES expose per-event IP / email /
user-agent — that's the security purpose of the table (unlike the
aggregate-only `/admin/kpis`). It is admin-gated for exactly that
reason. No password / token / secret is ever stored, so none can leak.

Flag gate (rule #4): 404 when ``ADMIN_DASHBOARD_ENABLED`` is off, so the whole
``/admin/*`` surface — including this SEC-AUTH-014 audit log now surfaced by
the BRIEF-ADMIN-004 Activity tab — stays uniformly gated.

## Query parameters

- `page` integer
- `page_size` integer
- `event_type` string, nullable: Filter to a single event_type (exact match).
- `email` string, nullable: Filter to a single presented email (exact match).

## Response `200`

Successful Response

- object

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/badgeia/apis/badge.md) · [All operations](https://skmtc.dev/badgeia/apis/badge/llms.txt) · [OpenAPI document](https://skmtc.dev/badgeia/apis/badge/revisions/7e7f7fee8b77?raw)
