---
title: "User directory with per-user rollups"
method: GET
path: "/stats/users"
tags: ["Stats"]
---

# User directory with per-user rollups

`GET /stats/users`

## Request

- Base URL: `https://api.nippy.host`
- URL: `https://api.nippy.host/stats/users`
- Auth: `bearer` (a scheme the document does not define)

Admin-only paginated list of users, each enriched with their active account-membership count, the sites reachable through those accounts, their highest plan tier, and the time of their last platform activity. Filterable by name/email search, platform role and email-verification state; sortable by sign-up time, last activity or name.

## Query parameters

- `search` string
- `role` 'user' | 'admin'
- `verified` boolean
- `risk` 'high' | 'medium' | 'low' | 'flagged'
- `billing` 'paid' | 'trialing' | 'past_due' | 'canceling'
- `banned` boolean
- `sort` 'created' | 'lastActive' | 'name' | 'risk'
- `sortDir` 'asc' | 'desc'
- `page` number
- `pageSize` number

## Response `200`

- APIPaginatedAdminUsersResponse
  - `data` APIAdminUser[], required
    - `id` string, required: User id (UUID).
    - `name` string, required: Display name.
    - `email` string, required: Email address.
    - `emailVerified` boolean, required: Whether the email address is verified.
    - `role` 'user' | 'admin', required: Platform role.
    - `createdAt` string, required: Sign-up time (ISO 8601).
    - `accountsCount` number, required: Number of accounts the user has an active membership in.
    - `sitesCount` number, required: Number of sites across the accounts the user has an active membership in.
    - `plan` 'free' | 'basic' | 'pro' | 'max', required: Highest plan tier across the subscriptions of the accounts the user has an active membership in (`free` when none).
    - `lastActiveAt` string, nullable, required: Time of the user’s most recent activity event (ISO 8601) — null if they have never acted.
    - `signupRef` string, nullable, required: The `ref` slug the user signed up with (acquisition channel); null for an unattributed signup.
    - `marketingOptOut` boolean, required: Whether the user opted out of lifecycle and marketing email.
    - `bannedAt` string, nullable, required: When an admin banned the user (ISO 8601); null if not banned.
    - `bannedReason` string, nullable, required: The reason the admin gave for the ban; null if not banned.
    - `bannedByName` string, nullable, required: Display name of the admin who applied the ban; null if not banned or that admin no longer exists.
    - `riskScore` number, nullable, required: Advisory risk score (0–100) from the last recompute; null when the user is not flagged (ADR 0049).
    - `riskLevel` 'high' | 'medium' | 'low', nullable, required: Advisory risk level; null when not flagged.
    - `riskReviewed` boolean, required: True while an admin review marks the user’s cluster as not a problem (ADR 0055). The score stays; the risk filters skip the user.
  - `page` number, required
  - `pageSize` number, required
  - `total` number, required
  - `totalPages` number, required

## Other responses

- `403`: Admin access required

---

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