Skip to main content
Version: v0.7.6

Manage WhatsApp groups

Create groups, read their metadata and participant lists, add or remove members, change admins, edit the subject and description, share invite links, and leave — all through one session's REST API.

Prerequisites
  • A session that is started and connected. See Sessions and Connect your first session.
  • An API key with the operator role for any write (create, modify, leave, revoke). Read routes accept any valid key. See Authentication.
  • A group id in WhatsApp's @g.us format, for example 120363021234567890@g.us.

Examples use the local base URL http://localhost:2785/api, a session id of my-session, and the header X-API-Key: YOUR_API_KEY. Replace YOUR_API_KEY with a key from your dashboard. In production, swap the base URL for your domain over TLS.

How group routes work

Every group route is nested under a session, so the session id is always in the path. There are 13 in all — listing, reading, participant management, subject and description, invite links, and leaving:

GET /api/sessions/{sessionId}/groups
POST /api/sessions/{sessionId}/groups
GET /api/sessions/{sessionId}/groups/{groupId}
POST /api/sessions/{sessionId}/groups/{groupId}/participants
DELETE /api/sessions/{sessionId}/groups/{groupId}/participants
POST /api/sessions/{sessionId}/groups/{groupId}/participants/promote
POST /api/sessions/{sessionId}/groups/{groupId}/participants/demote
PUT /api/sessions/{sessionId}/groups/{groupId}/subject
PUT /api/sessions/{sessionId}/groups/{groupId}/description
GET /api/sessions/{sessionId}/groups/{groupId}/invite-code
POST /api/sessions/{sessionId}/groups/{groupId}/invite-code/revoke
POST /api/sessions/{sessionId}/groups/{groupId}/leave

Two rules apply to all of them:

  • Identifiers. A group is addressed by its @g.us jid; an individual member by their @c.us jid (the phone number in international format without +, for example 628123456789@c.us).
  • Roles. GET routes need a plain API key. Writes — create, participant changes, subject, description, leave, revoke — require an operator-role key and return 403 otherwise.

The session must be started. Any group route on a session that is not started returns 400.

List groups

GET /api/sessions/{sessionId}/groups returns the groups the session belongs to as a raw array (no envelope). Page with the limit (1–1000, default 1000) and offset (default 0) query parameters.

curl "http://localhost:2785/api/sessions/my-session/groups?limit=50&offset=0" \
-H "X-API-Key: YOUR_API_KEY"
[
{
"id": "120363021234567890@g.us",
"name": "Project Team",
"participantsCount": 12,
"isAdmin": true,
"linkedParentJID": null
}
]

isAdmin reflects whether this session's account is an admin of the group — check it before attempting a write that requires group-admin rights on WhatsApp's side. linkedParentJID is set when the group is linked to a community, otherwise null.

Read group metadata

GET /api/sessions/{sessionId}/groups/{groupId} returns full details, including the participant list. It returns 404 if the group is not found in this session.

curl "http://localhost:2785/api/sessions/my-session/groups/120363021234567890@g.us" \
-H "X-API-Key: YOUR_API_KEY"
{
"id": "120363021234567890@g.us",
"name": "Project Team",
"description": "Internal coordination group.",
"owner": "628123456789@c.us",
"createdAt": 1718900000,
"isReadOnly": false,
"isAnnounce": false,
"linkedParentJID": null,
"participants": [
{
"id": "628123456789@c.us",
"number": "628123456789",
"name": "Alice",
"isAdmin": true,
"isSuperAdmin": true
}
]
}

Each participant carries isAdmin (group admin) and isSuperAdmin (the group owner). isAnnounce is true when only admins can post. isReadOnly is a best-effort mirror of isAnnounce — both derive from WhatsApp's announce flag, so it always equals isAnnounce.

Create a group

POST /api/sessions/{sessionId}/groups creates a group from a name and a non-empty list of participant jids. The session's own account becomes the owner. Both fields are required; an empty participants array fails validation with 400.

curl -X POST "http://localhost:2785/api/sessions/my-session/groups" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Project Team",
"participants": ["628123456789@c.us", "628987654321@c.us"]
}'

The response is the created group (status 201). Use the returned id as the groupId in every later call.

{
"id": "120363021234567890@g.us",
"name": "Project Team",
"participantsCount": 3,
"isAdmin": true,
"linkedParentJID": null
}

Manage participants

The four participant routes all take the same body — a non-empty participants array of @c.us jids — and return a fixed acknowledgement.

{ "participants": ["628123456789@c.us"] }
ActionMethod + pathAcknowledgement message
AddPOST .../participantsParticipants added
RemoveDELETE .../participantsParticipants removed
Promote to adminPOST .../participants/promoteParticipants promoted to admin
Demote from adminPOST .../participants/demoteParticipants demoted from admin

Add participants

curl -X POST "http://localhost:2785/api/sessions/my-session/groups/120363021234567890@g.us/participants" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "participants": ["628123456789@c.us"] }'
{ "success": true, "message": "Participants added" }

Remove participants

Removal is a DELETE that carries a JSON body — set the Content-Type header so the body is parsed.

curl -X DELETE "http://localhost:2785/api/sessions/my-session/groups/120363021234567890@g.us/participants" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "participants": ["628123456789@c.us"] }'
{ "success": true, "message": "Participants removed" }

Promote and demote admins

promote grants group-admin rights; demote revokes them. The session's account must itself be a group admin for either to take effect.

curl -X POST "http://localhost:2785/api/sessions/my-session/groups/120363021234567890@g.us/participants/promote" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "participants": ["628123456789@c.us"] }'
{ "success": true, "message": "Participants promoted to admin" }

Change the subject and description

The subject is the group name. PUT .../subject requires a non-empty subject.

curl -X PUT "http://localhost:2785/api/sessions/my-session/groups/120363021234567890@g.us/subject" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "subject": "New Team Name" }'
{ "success": true, "message": "Group subject updated" }

PUT .../description requires a description field. Unlike the subject, an empty string is valid and clears the description.

curl -X PUT "http://localhost:2785/api/sessions/my-session/groups/120363021234567890@g.us/description" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "description": "Internal coordination group." }'
{ "success": true, "message": "Group description updated" }

GET .../invite-code returns the current invite code and the full https://chat.whatsapp.com/<code> link.

curl "http://localhost:2785/api/sessions/my-session/groups/120363021234567890@g.us/invite-code" \
-H "X-API-Key: YOUR_API_KEY"
{
"inviteCode": "AbCdEf123456",
"inviteLink": "https://chat.whatsapp.com/AbCdEf123456"
}

To invalidate the existing link and mint a fresh one, call POST .../invite-code/revoke with an empty body. The response contains the new code and link — anyone holding the old link can no longer join.

curl -X POST "http://localhost:2785/api/sessions/my-session/groups/120363021234567890@g.us/invite-code/revoke" \
-H "X-API-Key: YOUR_API_KEY"
{
"inviteCode": "XyZ987654321",
"inviteLink": "https://chat.whatsapp.com/XyZ987654321",
"message": "Invite code revoked and new one generated"
}

Leave a group

POST .../leave removes the session's own account from the group. Send an empty body.

curl -X POST "http://localhost:2785/api/sessions/my-session/groups/120363021234567890@g.us/leave" \
-H "X-API-Key: YOUR_API_KEY"
{ "success": true, "message": "Left the group" }

Do it with the SDK

The JavaScript SDK wraps every route above. Note the client baseUrl is the host root (http://localhost:2785), without the /api prefix.

import { OpenWAClient } from '@rmyndharis/openwa';

const client = new OpenWAClient({
baseUrl: 'http://localhost:2785',
apiKey: 'YOUR_API_KEY',
});

const group = await client.groups.create('my-session', {
name: 'Project Team',
participants: ['628123456789@c.us', '628987654321@c.us'],
});

await client.groups.addParticipants('my-session', group.id, ['628111222333@c.us']);
await client.groups.promoteParticipants('my-session', group.id, ['628111222333@c.us']);
await client.groups.setSubject('my-session', group.id, 'Project Team — Q3');

const { inviteLink } = await client.groups.inviteCode('my-session', group.id);
console.log(inviteLink);

See SDK usage for client setup and typed error handling.

Troubleshooting

StatusCauseFix
400Validation failed (empty name, empty participants, empty subject, missing description), or the session is not started.Send a complete body; start the session first (see Sessions).
401Missing or invalid X-API-Key.Send a valid key in the X-API-Key header.
403The key's role is below operator on a write route.Use an operator-role key. See Authentication.
404The group jid is not found in this session.Confirm the @g.us id, and that this session is a member.
Group-admin rights are separate from API roles

An operator-role API key authorizes the request, but participant, subject, description, and invite changes still require the session's WhatsApp account to be a group admin. Check isAdmin on the group before attempting them.

Next steps