## List

**get** `/zones/{zoneId}/groups`

Returns a paginated list of the groups in the specified zone. Use cursor pagination via `after`/`before`. Sort: comma-separated field list; prefix with `-` for descending (allowed: created_at, name, identifier). Pass `expand[]=member_count` to include each group's member count, `expand[]=roles` to include the identifiers of the roles assigned to each group, and `expand[]=total_count` to include the matching row count. Filter by exact identifier via `filter[identifier]` (repeatable, OR'd across values). Search via `query[]` (case-insensitive substring match, OR'd across repeated values); it matches the group's name and identifier. Pass `filter[id]` (repeatable, max 100) to restrict results to a known set of groups — mutually exclusive with `after`/`before` (returns 400 if combined). When `filter[id]` is set, `limit` is ignored and the response contains every requested group that exists in the zone, in a single page. IDs not in the zone are silently omitted.

### Path Parameters

- `zoneId: string`

### Query Parameters

- `after: optional string`

  Cursor for forward pagination

- `before: optional string`

  Cursor for backward pagination

- `"expand[]": optional "total_count" or "member_count" or "roles" or array of "total_count" or "member_count" or "roles"`

  - `UnionMember0 = "total_count" or "member_count" or "roles"`

    - `"total_count"`

    - `"member_count"`

    - `"roles"`

  - `UnionMember1 = array of "total_count" or "member_count" or "roles"`

    - `"total_count"`

    - `"member_count"`

    - `"roles"`

- `"filter[id]": optional string or array of string`

  Restrict results to groups with this ID. Repeatable, max 100. Mutually exclusive with after/before.

  - `UnionMember0 = string`

    Restrict results to groups with this ID. Repeatable, max 100. Mutually exclusive with after/before.

  - `UnionMember1 = array of string`

- `"filter[identifier]": optional string or array of string`

  Filter by exact group identifier

  - `UnionMember0 = string`

    Filter by exact group identifier

  - `UnionMember1 = array of string`

- `limit: optional number`

  Maximum number of items to return

- `"query[]": optional string or array of string`

  Search across name and identifier (substring match)

  - `UnionMember0 = string`

    Search across name and identifier (substring match)

  - `UnionMember1 = array of string`

- `sort: optional string`

  Comma-separated sort fields. Prefix with - for descending. Allowed: created_at, name, identifier

### Returns

- `items: array of Group`

  - `id: string`

    Unique identifier of the group

  - `created_at: string`

    Entity creation timestamp

  - `external: boolean`

    Whether the group is synced from an external directory. When true the group is directory-owned and its membership is read-only; when false it is managed in Keycard. Read-only: set by external sync, never by the caller.

  - `identifier: string`

    User-specified identifier, unique within the zone. Automatically assigned for groups from an external directory.

  - `name: string`

    Human-readable group name

  - `organization_id: string`

    Organization this group belongs to

  - `updated_at: string`

    Entity update timestamp

  - `zone_id: string`

    Zone this group belongs to

  - `member_count: optional number`

    Number of users in the group. Included only when requested via `expand[]=member_count` (group get or list).

  - `roles: optional array of string`

    Identifiers of the roles assigned to the group; members inherit them. Deduped across scopes. Included only when requested via `expand[]=roles` (group get or list).

- `pagination: object { after_cursor, before_cursor, total_count }`

  Cursor-based pagination metadata

  - `after_cursor: string`

    An opaque cursor used for paginating through a list of results

  - `before_cursor: string`

    An opaque cursor used for paginating through a list of results

  - `total_count: optional number`

    Total number of items matching the query. Only included when expand[]=total_count is requested.

### Example

```http
curl https://api.keycard.ai/zones/$ZONE_ID/groups \
    -H "Authorization: Bearer $KEYCARD_API_API_KEY"
```
