You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
GET /api/{session}/groups returns object keyed by chatId on NOWEB, not an array #2263
Bug description:
GET /api/{session}/groups returns an object keyed by chat ID ({"120363...@g.us": {...}, ...}) instead of an array, at least on the NOWEB engine. The endpoint's controller (src/api/groups.controller.ts#getGroups) returns session.getGroups(pagination) untyped (any), with no normalization and no documented/typed response shape.
This is already known internally: getGroupsCount() in the same codebase defensively handles both shapes:
Array.isArray(data) ? data : Object.values(data)
but the public getGroups endpoint itself does not apply the same normalization, so consumers naively doing Array.isArray(data) ? data : [] silently get an empty list even though groups exist.
Expected behavior:
GET /groups should consistently return an array (matching the OpenAPI/Swagger expectation), regardless of engine — either by normalizing in the controller the same way getGroupsCount() already does, or by documenting the object-keyed shape explicitly with a proper TypeScript return type.
Steps to reproduce:
Run WAHA with WHATSAPP_DEFAULT_ENGINE=NOWEB.
Connect a session with at least one WhatsApp group.
Call GET /api/{session}/groups.
Response is an object keyed by chat ID, not a JSON array.
We need a new version for this—GET /api/{session}/groups/v2/...—with unified data across all engines (and we also need to replicate the current GET /api/{session}/groups/{id}/participants/v2 as GET /api/{session}/groups//v2/{id}/participants for convenience).
I’ll be happy to review the corresponding PR (provided it has been tested across all engines and polished following the LLM-related changes!).
Thanks for confirming the direction! Before I start the implementation, want to
make sure the shape is right so I don't have to redo it.
Plan:
GET /api/{session}/groups/v2 — returns Group[] (always an array,
regardless of engine), each with:
id
subject
description
owner
creation (timestamp)
Mapped per engine the same way GroupParticipant already is (ToGroup
functions in webjs/noweb/gows, mirroring ToGroupParticipant/ToGroupParticipants).
Existing GET /groups stays untouched (NOWEB's getGroup(id) still relies on
its keyed-by-id shape internally, so changing it in place would be breaking).
GET /api/{session}/groups/v2/{id}/participants — same behavior as the
existing .../participants/v2, just under the new /v2 prefix for
consistency. Old route stays for backward compat.
Does that field list match what you had in mind for "unified data", or should
I include/drop anything (e.g. participant count, picture url)? Want to lock
the shape before writing the per-engine mappers.
Activity
devlikepro commentedon Sep 11, 2026
We need a new version for this—
GET /api/{session}/groups/v2/...—with unified data across all engines (and we also need to replicate the currentGET /api/{session}/groups/{id}/participants/v2asGET /api/{session}/groups//v2/{id}/participantsfor convenience).I’ll be happy to review the corresponding PR (provided it has been tested across all engines and polished following the LLM-related changes!).
danilipari commentedon Sep 14, 2026
Thanks for confirming the direction! Before I start the implementation, want to
make sure the shape is right so I don't have to redo it.
Plan:
GET /api/{session}/groups/v2 — returns Group[] (always an array,
regardless of engine), each with:
Mapped per engine the same way GroupParticipant already is (ToGroup
functions in webjs/noweb/gows, mirroring ToGroupParticipant/ToGroupParticipants).
Existing GET /groups stays untouched (NOWEB's getGroup(id) still relies on
its keyed-by-id shape internally, so changing it in place would be breaking).
GET /api/{session}/groups/v2/{id}/participants — same behavior as the
existing .../participants/v2, just under the new /v2 prefix for
consistency. Old route stays for backward compat.
Does that field list match what you had in mind for "unified data", or should
I include/drop anything (e.g. participant count, picture url)? Want to lock
the shape before writing the per-engine mappers.