Skip to content

feat(api): add listGroups endpoint for customer summaries#360

Open
dionlow wants to merge 1 commit into
mainfrom
feat/list-groups-endpoint
Open

feat(api): add listGroups endpoint for customer summaries#360
dionlow wants to merge 1 commit into
mainfrom
feat/list-groups-endpoint

Conversation

@dionlow

@dionlow dionlow commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

What

Adds GET /projects/{projectIdOrName}/groups (operationId: listGroups, tag Group) returning lightweight, pre-aggregated GroupSummary rows instead of full installations.

GroupSummary: groupRef, groupName, installationCount, nullable lastUpdated, and integrationIds[] — wrapped in a { results, pagination } envelope that reuses the existing PaginationInfo.

Why

The Customers list view today fetches every installation in a project and groups them client-side, shipping each installation's config and connection even though the list only renders four aggregated fields. Groups are far fewer than installations, so a summary endpoint cuts the payload ~order-of-magnitude and removes the client-side grouping. It makes the Customers list scale with number of customers rather than total installations.

Design notes

  • Optional pagination + server-side search/sort. pageSize/pageToken/query/sortBy/order are all optional. Omit paging → server returns all group summaries in one page (pagination.done = true) and the client filters/sorts locally. Provide them later → server-side pagination, no contract change.
  • integrationIds[] exists purely so the list can match a customer by integration during client-side search; it renders nothing and can be dropped later for payload size.

Notes

  • Contract only — the backend handler (aggregation) and the client wiring land separately.
  • api/generated/api.json regenerated via make gen / gen:json.

🤖 Generated with Claude Code

Adds GET /projects/{projectIdOrName}/groups (operationId listGroups,
tag Group) returning lightweight, pre-aggregated GroupSummary rows
(groupRef, groupName, installationCount, lastUpdated, integrationIds)
in a {results, pagination} envelope reusing PaginationInfo.

Lets the Customers list view render one row per customer without
shipping every installation's config and connection. Pagination and
server-side search/sort params (pageSize, pageToken, query, sortBy,
order) are optional so the endpoint can start in fetch-all mode and
graduate to server-side pagination without a contract change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread api/generated/api.json
Comment on lines +31212 to +31254
"example": "2024-01-15T10:30:00.000Z"
},
"integrationIds": {
"type": "array",
"items": {
"type": "string"
},
"description": "The distinct integration IDs the group has installations on. Provided so list views can match a group by integration during client-side search. Not rendered; may be dropped in future for payload size.",
"example": [
"550e8400-e29b-41d4-a716-446655440000"
]
}
}
}
},
"pagination": {
"title": "Pagination Information",
"type": "object",
"required": [
"done"
],
"properties": {
"done": {
"type": "boolean",
"description": "If set to true, this is the last page of results for the given operation. There are no more results & there will be no nextPageToken sent when done is true.",
"example": false
},
"nextPageToken": {
"type": "string",
"description": "If present, set this value against your 'pageToken' query parameter in the next API call, which will retrieve the next set of results.",
"example": "Q9JT+2qfys28V4ODN+UayA=="
}
}
}
}
},
"example": {
"results": [
{
"groupRef": "org_12345",
"groupName": "Acme Corp",
"installationCount": 4,
"lastUpdated": "2024-01-15T10:30:00.000000Z",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date-time format inconsistency in examples. Line 31212 shows "2024-01-15T10:30:00.000Z" (millisecond precision) but line 31254 shows "2024-01-15T10:30:00.000000Z" (microsecond precision). This inconsistency will confuse API consumers about the expected format.

// Fix: Use consistent precision throughout, e.g.:
"example": "2024-01-15T10:30:00.000000Z"
Suggested change
"example": "2024-01-15T10:30:00.000Z"
},
"integrationIds": {
"type": "array",
"items": {
"type": "string"
},
"description": "The distinct integration IDs the group has installations on. Provided so list views can match a group by integration during client-side search. Not rendered; may be dropped in future for payload size.",
"example": [
"550e8400-e29b-41d4-a716-446655440000"
]
}
}
}
},
"pagination": {
"title": "Pagination Information",
"type": "object",
"required": [
"done"
],
"properties": {
"done": {
"type": "boolean",
"description": "If set to true, this is the last page of results for the given operation. There are no more results & there will be no nextPageToken sent when done is true.",
"example": false
},
"nextPageToken": {
"type": "string",
"description": "If present, set this value against your 'pageToken' query parameter in the next API call, which will retrieve the next set of results.",
"example": "Q9JT+2qfys28V4ODN+UayA=="
}
}
}
}
},
"example": {
"results": [
{
"groupRef": "org_12345",
"groupName": "Acme Corp",
"installationCount": 4,
"lastUpdated": "2024-01-15T10:30:00.000000Z",
"example": "2024-01-15T10:30:00.000000Z"
},
"integrationIds": {
"type": "array",
"items": {
"type": "string"
},
"description": "The distinct integration IDs the group has installations on. Provided so list views can match a group by integration during client-side search. Not rendered; may be dropped in future for payload size.",
"example": [
"550e8400-e29b-41d4-a716-446655440000"
]
}
}
}
},
"pagination": {
"title": "Pagination Information",
"type": "object",
"required": [
"done"
],
"properties": {
"done": {
"type": "boolean",
"description": "If set to true, this is the last page of results for the given operation. There are no more results & there will be no nextPageToken sent when done is true.",
"example": false
},
"nextPageToken": {
"type": "string",
"description": "If present, set this value against your 'pageToken' query parameter in the next API call, which will retrieve the next set of results.",
"example": "Q9JT+2qfys28V4ODN+UayA=="
}
}
}
}
},
"example": {
"results": [
{
"groupRef": "org_12345",
"groupName": "Acme Corp",
"installationCount": 4,
"lastUpdated": "2024-01-15T10:30:00.000000Z",

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant