---
title: "List members"
method: GET
path: "/api/v1/users/members"
tags: ["Users"]
---

# List members

`GET /api/v1/users/members`

## Request

- Base URL: `https://app.scanopy.net`
- URL: `https://app.scanopy.net/api/v1/users/members`
- Auth: one of:
  - API key in header `Authorization`
  - API key in cookie `session_id`

The organization's users and its pending invites in one list, each limited to the ones the
caller may see: every user and invite for an owner, otherwise the caller themselves, members
below their role, and invites they created.

## Query parameters

- `statuses` MemberStatus[], nullable
- `permissions` UserOrgPermissions[], nullable
- `site_ids` string[], nullable
- `all_sites` boolean, nullable
- `auth_methods` string[], nullable
- `invited_by` string[], nullable
- `email_verified` boolean[], nullable
- `search` string, nullable
- `group_by` 'created_at' | 'email' | 'invite_status' | 'permissions' | 'oidc_provider' | 'updated_at' | 'invited_by' | 'expires_at' | 'email_verified' | 'oidc_linked_at': Fields the members list can be ordered and grouped by. Every one is derived in Rust.
- `order_by` 'created_at' | 'email' | 'invite_status' | 'permissions' | 'oidc_provider' | 'updated_at' | 'invited_by' | 'expires_at' | 'email_verified' | 'oidc_linked_at': Fields the members list can be ordered and grouped by. Every one is derived in Rust.
- `order_direction` 'asc' | 'desc': Direction for ORDER BY clauses.
- `limit` integer, nullable
- `offset` integer, nullable

## Response `200`

Users and pending invites

- PaginatedApiResponseMember: Response type for paginated list endpoints (pagination is always present in meta)
  - `data` union[], required: The page of results. Empty when nothing matched the query.
    - union: One row of the members list: a user, or an invite still waiting to be accepted.
      - object
        - `auth_method` string, required: How the user signs in: `<provider>`, `<provider>+password`, `password` or `none`. Provider names come from the server's OIDC config.
        - `data` User, required
          - `display_settings` DisplaySettings: Per-user display preferences for dates and times in the UI. Stored as a JSONB blob with `#[serde(default)]` on the struct, so a stored object missing a key (including the `{}` every existing row starts with) reads as that field's default. Every default reproduces the UI's behaviour from before the setting existed, except `table_density`, which defaults to the tighter of its two layouts.
            - `clock` 'browser_default' | 'twelve_hour' | 'twenty_four_hour'
            - `date_order` 'browser_default' | 'iso' | 'day_first' | 'month_first'
            - `table_density` 'comfortable' | 'compact'
            - `time_zone` string, nullable: IANA time zone dates are shown in. `None` uses the browser's zone.
            - `timestamps` 'relative' | 'absolute'
            - `week_start` 'monday' | 'sunday'
          - `email` string, email, required: The user's email address, also their login identifier.
          - `email_settings` EmailSettings: Per-user toggles for the pausable email categories. Each field is named after one [`EmailCategory`] whose `pausable()` is true; required categories are never gated here. Stored as a JSONB blob, so new categories are added as new fields rather than via migration. New fields carry `#[serde(default = "default_true")]` so a category is opted in by default if its key is absent from the stored JSON.
            - `daemon_alerts` boolean: Send an alert when a daemon stops reporting.
            - `discovery_digest` boolean, required: Send a periodic summary of what discovery found.
            - `product_onboarding` boolean: Send getting-started guidance.
            - `product_updates` boolean: Send the release notes when this server upgrades.
            - `trial_and_usage` boolean: Send trial reminders and plan-usage warnings.
          - `email_verification_required` boolean: Whether the user must verify their email before the API serves their session (an org on a license plan, see `auth::verification_gate`). Computed and set like `terms_acceptance_required`.
          - `email_verified` boolean: Whether the user has verified their email address
          - `has_password` boolean: Whether the user has a password set — computed from password_hash, never stored in DB
          - `oidc_linked_at` string, date-time, nullable: When the account was linked to the identity provider.
          - `oidc_provider` string, nullable: Slug of the identity provider this account signs in through, when linked.
          - `organization_id` string, uuid, required: The organization that owns this record.
          - `permissions` 'Owner' | 'Admin' | 'Member' | 'Viewer', required
          - `site_ids` string[], required: The sites this entity applies to.
          - `terms_acceptance_required` boolean: Whether the user must accept the current terms before the API serves their session. Computed, never stored: set only on the signed-in user's own record (`/api/auth/me`, login, accept), false everywhere else.
          - `created_at` string, date-time, required: When this record was first created.
          - `id` string, uuid, required: Server-assigned unique identifier.
          - `updated_at` string, date-time, required: When this record was last modified.
        - `id` string, uuid, required: The user's id.
        - `status` 'pending' | 'you' | 'user', required: A member's place in the organization, as the status column shows it.
        - `type` 'user', required
      - object
        - `data` Invite, required
          - `created_by` string, uuid, required: User who sent the invite.
          - `expires_at` string, date-time, required: When this record stops being valid.
          - `organization_id` string, uuid, required: The organization that owns this record.
          - `permissions` 'Owner' | 'Admin' | 'Member' | 'Viewer', required
          - `send_to` string, nullable, required: Optional email address to send the invite to
          - `site_ids` string[], required: The sites this entity applies to.
          - `url` string, required: Link the recipient follows to accept the invite.
          - `created_at` string, date-time, required: When this record was first created.
          - `id` string, uuid, required: Server-assigned unique identifier.
          - `updated_at` string, date-time, required: When this record was last modified.
        - `id` string, uuid, required: The invite's id.
        - `status` 'pending' | 'you' | 'user', required: A member's place in the organization, as the status column shows it.
        - `type` 'invite', required
  - `error` string, nullable: Human-readable failure message. Omitted on success.
  - `meta` PaginatedApiMeta, required: API metadata for paginated list responses (pagination is always present)
    - `api_version` integer, required: API version (integer, increments on breaking changes)
    - `pagination` PaginationMeta, required: Pagination metadata returned with paginated responses.
      - `group_counts` GroupCount[], nullable: Size of every group, in the same order the rows are grouped, when the request specified a `group_by`. Lets a paginated client show a group's true size instead of the slice of it that happens to be on this page. Absent when the list isn't grouped.
        - `count` integer, required: How many rows fall in this group in total, not just on this page.
        - `value` string, nullable: The group's value, rendered as text. `null` for rows whose group key is NULL (the "ungrouped" bucket).
      - `has_more` boolean, required: Whether there are more items after this page
      - `limit` integer, required: Maximum items per page (as requested)
      - `offset` integer, required: Number of items skipped
      - `total_count` integer, required: Total number of items matching the filter (ignoring pagination)
    - `server_version` string, required: Server version (semver)
  - `success` boolean, required: `true` when the request succeeded. `false` responses carry `error` instead of `data`.

## Changes

- **2026-10-31** `c4e6ec11e35b`: 1 info
  - added the optional property `data/items/oneOf[subschema #1: User]/data/allOf[#/components/schemas/UserBase]/email_verification_required` to the response with the `200` status
- **2026-10-23** `9dda1a8b8ed1`: 5 breaking, 13 warning, 5 info
  - the `data/items/oneOf[subschema #1: User]/data/allOf[#/components/schemas/UserBase]/display_settings/clock` response's property type changed from no type to `string` for status `200`
  - the `data/items/oneOf[subschema #1: User]/data/allOf[#/components/schemas/UserBase]/display_settings/date_order` response's property type changed from no type to `string` for status `200`
  - the `data/items/oneOf[subschema #1: User]/data/allOf[#/components/schemas/UserBase]/display_settings/table_density` response's property type changed from no type to `string` for status `200`
  - the `data/items/oneOf[subschema #1: User]/data/allOf[#/components/schemas/UserBase]/display_settings/timestamps` response's property type changed from no type to `string` for status `200`
  - …19 more
- …earlier changes not shown

[Operation history](https://skmtc.dev/scanopy/apis/scanopy-api/changes/api/v1/users/members/get.md)

---

[API](https://skmtc.dev/scanopy/apis/scanopy-api.md) - [All operations](https://skmtc.dev/scanopy/apis/scanopy-api/llms.txt) - [OpenAPI document](https://skmtc.dev/scanopy/apis/scanopy-api/revisions/966ba786bdb5?raw)
