---
title: "List people in a library"
method: GET
path: "/api/people"
tags: ["people"]
---

# List people in a library

`GET /api/people`

Returns a paginated list of person records, which may be named or unnamed and may have zero or more faces, ordered according to `sort` (newest first by default), optionally filtered by asset, album, name, or ID.

By default only people with a non-null name are returned; pass `name_filter=all` for every person or `name_filter=unnamed` for people whose name is null.

To list the underlying faces for a specific person, use `list_faces` with `person_id`.

**Pagination** is cursor-based: when `has_more` is true, pass the `id` of the last person in `data` as `starting_after_id` to fetch the next page.

## Query parameters

- `limit` integer — Maximum number of people to return per page (1–200). Defaults to 20.
- `starting_after_id` string, nullable — Cursor for pagination. Pass the `id` of the last person in the previous response's `data` to fetch the next page. Omit for the first page.
- `asset_id` string, nullable — Return only people who have at least one face in this asset. Useful for 'who is in this photo?'.
- `album_id` string, nullable — Return only people who appear in at least one asset of this album. Useful for 'who is in this album?'.
- `ids` string[], nullable — Look up specific people by ID (max 200; each ID has the `person_` prefix). Accepts multiple `ids=` query params or a single comma-delimited value (e.g., `ids=person_1,person_2`). When set, `name_filter` defaults to `all` so unnamed people are included in the lookup.
- `name` string, nullable — Filter by name using case-insensitive substring matching. Use this to resolve a user-supplied name like 'Alice' into a `person_id`, then pass that ID into `search_assets.person_ids` or `list_assets.person_ids`.
- `name_filter` 'named' | 'unnamed' | 'all' — Which people to include, based on name nullness: `named` returns people whose name is non-null; `unnamed` returns people whose name is null; `all` returns both.
- `sort` 'created_at_desc' | 'created_at_asc' | 'name_asc' | 'name_desc' | 'asset_count_desc' | 'asset_count_asc' — Sort orders for list_people. Each value encodes column + direction; decompose via the `column` and `direction` properties.
- `library_id` string, nullable — Library to list from. Optional if the user has a single live (non-trashed) library; required when they have multiple.
- `include` string[], nullable — Opt-in expansion fields. Supported values: `cluster_metrics` (adds the nested `cluster_metrics` object — `pairwise_p90`, `pairwise_mean`, `face_count` — for each Person with a populated centroid). Accepts multiple `include=` query params or a single comma-delimited value. Unknown values return 422.

## Response `200`

Successful Response

- PaginatedPeopleResponse
  - `data` PersonResponse[], required — List of people
    - `id` string, required — Unique person identifier with 'person_' prefix
    - `name` string, nullable — Optional name assigned to this person
    - `birth_date` string, date, nullable — Optional birth date of this person
    - `is_hidden` boolean, required — Whether this person should be hidden from the UI
    - `is_favorite` boolean, required — Whether this person is marked as a favorite
    - `asset_count` integer, nullable — Number of unique photos this person appears in, or null if not computed
    - `thumbnail_face_id` string, nullable — ID of the face resource used as this person's thumbnail
    - `asset_urls` object, nullable — Asset variants from this person's thumbnail face. May be null when embedded in an AssetResponse; use /api/people endpoints for full person data.
    - `cluster_metrics` ClusterMetricsResponse — Cohesion metrics for a Person's face cluster — surfaced via ``include=cluster_metrics`` on the people endpoints. These describe how tight the cluster is in embedding space (lower = more cohesive) and drive both the production face-assignment cohesion gate and the operator-facing face cleanup dashboard.
      - `pairwise_p90` number, required — 90th-percentile pairwise cosine distance between faces in this person's cluster. Lower = more cohesive cluster; loose clusters (higher pairwise_p90) are gated out of the face-assignment path to prevent further drift.
      - `pairwise_mean` number, required — Mean pairwise cosine distance between faces in this person's cluster.
      - `face_count` integer, required — Number of faces that fed into the centroid and pairwise metrics. This is the cluster-membership count, **not** the same as `asset_count` — `face_count` counts every face row, while `asset_count` counts distinct assets (one asset can contribute multiple faces of the same person).
    - `created_at` string, date-time, required — When this person record was created
    - `updated_at` string, date-time, required — When this person record was last updated
  - `has_more` boolean, required — True if there are more people after this page. Pass the last person's `id` as `starting_after_id` to fetch the next page.

## Other responses

- `401` — Missing, invalid, or expired credentials.
- `403` — The credentials are valid but not authorized for this operation — for example an API key whose action or library scope excludes it, or a credential type this operation does not accept.
- `404` — Not found
- `422` — Validation Error
- `429` — Rate limit exceeded. Retry after the interval in the `Retry-After` header.

---

[API](https://skmtc.net/gumnut-ai/apis/gumnut-api.md) · [All operations](https://skmtc.net/gumnut-ai/apis/gumnut-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/gumnut-ai/gumnut-api/revisions/e71db45f5d4a/schema)
