Skip to main content
The Groups struct provides methods for managing WhatsApp groups, including creating groups, managing participants, and modifying group settings.

Access

Access group operations through the client:

Methods

query_info

Query group information with caching support.
query_info and get_metadata return different, purpose-built views of a group — pick based on what you’re doing with the result:Use query_info_with_freshness when you need explicit control over query_info’s staleness instead of the default cache-preferred behavior.
Parameters:
  • jid - Group JID (must end with @g.us)
Returns:
  • Arc<GroupInfo> - Shared, reference-counted snapshot containing the participants list and addressing mode. Repeated calls for the same group return the same Arc from the in-memory cache, so warm sends avoid deep-cloning group metadata.
Example:

query_info_with_freshness

Query group information with an explicit cache Freshness policy, instead of the always-cache-preferred behavior of query_info.
Parameters:
  • jid - Group JID (must end with @g.us)
  • freshness - Freshness::CachePreferred (same as query_info) or Freshness::Refresh to force a network round-trip
Returns:
  • Arc<GroupInfo> - Same shared snapshot type as query_info
A Refresh query leaves the currently cached snapshot readable to concurrent callers while the network request is in flight, then atomically replaces it once the response arrives — there is no window where the cache is empty. Example:

get_participating

Get all groups the client is participating in.
Returns:
  • HashMap<Jid, GroupMetadata> - Map of group Jid to metadata
This map is keyed by Jid. Call .to_string() on the key if you need the string form.
GroupMetadata implements PartialEq and Eq, allowing direct comparison of group metadata instances. GroupMetadata fields:
  • id: Jid - Group JID
  • subject: String - Group name
  • notify: Option<String> - Display notification string reported by the server (from the notify attribute)
  • participants: Vec<GroupParticipant> - List of participants
  • addressing_mode: AddressingMode - Phone number or LID mode
  • creator: Option<Jid> - Group creator JID
  • creator_pn: Option<Jid> - Creator’s phone-number JID, when creator is a LID
  • creator_username: Option<String> - Creator’s Meta username, when present
  • creator_country_code: Option<String> - Creator’s ISO country code, when present
  • creation_time: Option<u64> - Group creation timestamp (Unix seconds)
  • participant_version_id: Option<String> - Participant-list version identifier (from p_v_id)
  • admin_version_id: Option<String> - Admin-list version identifier (from a_v_id)
  • open_thread_id: Option<String> - Open thread identifier associated with the group
  • has_missing_participant_identification: bool - Whether participant identity information was incomplete in this response
  • subject_time: Option<u64> - Subject modification timestamp (Unix seconds)
  • subject_owner: Option<Jid> - Subject owner JID
  • subject_owner_pn: Option<Jid> - Subject owner’s phone-number JID (from s_o_pn)
  • subject_owner_username: Option<String> - Subject owner’s Meta username (from s_o_username)
  • description: Option<String> - Group description body text
  • description_id: Option<String> - Description ID (for conflict detection)
  • description_owner: Option<Jid> - JID of the participant who set the description
  • description_owner_pn: Option<Jid> - Description owner’s phone-number JID
  • description_owner_username: Option<String> - Description owner’s Meta username
  • description_time: Option<u64> - Timestamp when the description was set (Unix seconds)
  • is_locked: bool - Whether only admins can edit group info
  • is_announcement: bool - Whether only admins can send messages
  • ephemeral: Option<GroupEphemeralSettings> - Disappearing-message settings. None when the server response has no <ephemeral> node at all; Some(GroupEphemeralSettings { expiration, trigger }) when the node is present — expiration is None if the node omitted the attribute, which is distinct from Some(0) (timer explicitly disabled)
  • membership_approval: bool - Whether admin approval is required to join
  • member_add_mode: Option<MemberAddMode> - Who can add members
  • member_link_mode: Option<MemberLinkMode> - Who can use invite links
  • size: Option<u32> - Total participant count
  • is_parent_group: bool - Whether this group is a community parent group
  • parent_membership_approval_required: bool - Whether joins to this parent group require approval by default
  • parent_group_jid: Option<Jid> - JID of the parent community (for subgroups)
  • is_default_sub_group: bool - Whether this is the default announcement subgroup of a community
  • is_general_chat: bool - Whether this is the general chat subgroup of a community
  • allow_non_admin_sub_group_creation: bool - Whether non-admin community members can create subgroups
  • no_frequently_forwarded: bool - Whether frequently-forwarded messages are restricted
  • member_share_history_mode: Option<MemberShareHistoryMode> - Who can share message history with new members
  • growth_locked: Option<GrowthLockInfo> - Growth lock status (invite links temporarily disabled by the system)
  • is_suspended: bool - Whether the group is suspended
  • suspension_can_auto_file: bool - Whether a suspension appeal may be filed automatically
  • appeal_status: Option<GroupAppealStatus> - Current suspension-appeal state
  • appeal_update_time: Option<u64> - Last suspension-appeal update timestamp (Unix seconds)
  • is_support_group: bool - Whether the group is marked as a support group
  • allow_admin_reports: bool - Whether admin reports are allowed
  • is_hidden_group: bool - Whether the group is hidden
  • is_incognito: bool - Whether incognito mode is enabled
  • has_group_history: bool - Whether group history is enabled
  • is_auto_add_disabled: bool - Whether automatic participant addition is disabled
  • has_capi: bool - Whether the group carries the CAPI capability marker
  • evolution_version: Option<u32> - Group schema evolution version
  • has_group_safety_check: bool - Whether the group safety-check feature is enabled
  • participant_label_enabled: bool - Whether participant labels are enabled
  • is_limit_sharing_enabled: bool - Whether limit sharing is enabled
  • limit_sharing_trigger: Option<u32> - Source trigger for limit-sharing enablement
ephemeral_expiration: u32 and ephemeral_trigger: Option<u32> were replaced by the single ephemeral: Option<GroupEphemeralSettings> field. Migrate reads like metadata.ephemeral_expiration to metadata.ephemeral.as_ref().and_then(|e| e.expiration).unwrap_or(0).
See Community API for community-specific operations. GroupParticipant implements PartialEq and Eq. GroupParticipant fields:
  • jid: Jid - Participant JID
  • phone_number: Option<Jid> - Phone number JID (for LID groups)
  • lid: Option<Jid> - Participant’s LID JID, when the server includes one
  • username: Option<CompactString> - Participant’s Meta username, when present
  • participant_type: ParticipantType - Participant role (member, admin, or super admin)
  • details: Option<Box<GroupParticipantDetails>> - Less-common participant metadata (label, join time, display name, etc.); boxed and only populated when at least one field is present
Example:

get_metadata

Get metadata for a specific group.
Parameters:
  • jid - Group JID
Returns:
  • GroupMetadata - Owned, full user-facing metadata: subject, description, creator, per-participant admin roles, and ephemeral/membership settings (see get_participating for the full field list). In a LID-addressed group, participant phone numbers the server left out are backfilled from known LID/PN mappings on a best-effort basis; a participant with no known mapping keeps phone_number: None.
The query always hits the network (no phash is sent, so the server never answers not-modified) and the result does not populate the group cache. Use this for displaying or auditing a group; when you only need the participant list to send a message, prefer the cached query_info. Example:

create_group

Create a new group.
Parameters:
  • options: GroupCreateOptions - Group creation options
    • subject: String - Group name (max 100 characters)
    • participants: Vec<GroupParticipantOptions> - Initial participants
    • member_link_mode: Option<MemberLinkMode> - Who can use invite links (default: AdminLink)
    • member_add_mode: Option<MemberAddMode> - Who can add members (default: AllMemberAdd)
    • membership_approval_mode: Option<MembershipApprovalMode> - Require admin approval (default: Off)
    • ephemeral_expiration: Option<u32> - Disappearing messages timer in seconds (default: 0)
    • is_parent: bool - Create as a community parent group (default: false)
    • closed: bool - Whether the community requires approval to join. Only used when is_parent is true (default: false)
    • allow_non_admin_sub_group_creation: bool - Allow non-admin members to create subgroups. Only used when is_parent is true (default: false)
    • create_general_chat: bool - Create a general chat subgroup alongside the community. Only used when is_parent is true (default: false)
    • linked_parent: Option<Jid> - Atomically link this group as a subgroup of an existing community on create. Mutually exclusive with is_parent — when set, the new group is always classified as a subgroup even if is_parent: true is also passed. (added in v0.6)
    • description: Option<String> - Inline group description, emitted as a <description> child of the <create> stanza so it lands in one round-trip. Matches the existing community-create behavior. (added in v0.6)
Returns:
  • CreateGroupResult with a metadata: GroupMetadata field carrying the full server response (JID, subject, addressing mode, participants with display names, parent/community linkage, etc.).
When the PRIVACY_TOKEN_ON_GROUP_CREATE AB prop is enabled, the library automatically resolves and attaches privacy tokens (tc_token) to each participant during group creation. This is handled internally — you don’t need to manage tokens yourself. Example:
Since v0.6, create_group returns the full GroupMetadata (matching get_metadata) instead of just the JID. Inspect result.metadata for participants, addressing mode, ephemeral timer, and parent linkage in a single round-trip. GroupMetadata.participants is a Vec<GroupParticipant> (the IQ-response shape), not the GroupParticipantInfo used by group notification events — but masked-number display_name labels are available here too, via participant.details.as_ref().and_then(|d| d.display_name.as_deref()), in addition to the event-side GroupParticipantInfo.display_name for live group-update events.

set_subject

Change the group name.
Parameters:
  • jid - Group JID
  • subject - New group name (max 100 characters)
Example:

set_description

Set or delete the group description.
Parameters:
  • jid - Group JID
  • description - New description (max 2048 characters) or None to delete
  • prev - The description this update replaces, as a PreviousDescription. The server accepts the update only when this token matches the group’s current description id — a group that already has a description cannot be updated without it.
PreviousDescription::Resolve (the default) reads the current id from the server first, which always works but costs one extra query. If you already hold fresh GroupMetadata::description_id, pass it directly — metadata.description_id.as_deref().into() — to skip that query. Use PreviousDescription::Absent for a group you know has no description yet, such as one you just created.
Returns GroupError::DescriptionConflict if the group’s description changed on the server between the read and this update (for example, another device changed it first). Example:

leave

Leave a group.
Parameters:
  • jid - Group JID to leave
Example:

add_participants

Add participants to a group.
Parameters:
  • jid - Group JID
  • participants - Array of participant JIDs to add
Returns:
  • Vec<ParticipantChangeResponse> - Result for each participant
When the PRIVACY_TOKEN_ON_GROUP_PARTICIPANT_ADD AB prop is enabled, the library automatically resolves and attaches privacy tokens (tc_token) to each participant. This is handled internally — you don’t need to manage tokens yourself. Example:

remove_participants

Remove participants from a group.
Parameters:
  • jid - Group JID
  • participants - Array of participant JIDs to remove
Returns:
  • Vec<ParticipantChangeResponse> - Result for each participant
Example:

remove_participants_including_linked_groups

Remove participants from a group and cascade the removal to its linked/child groups. Used for community-linked groups, where removing someone from the community should also remove them from subgroups.
Parameters:
  • jid - Group JID (typically the community parent group)
  • participants - Array of participant JIDs to remove
Returns:
  • Vec<ParticipantChangeResponse> - Result for each participant
Example:

promote_participants

Promote participants to admin.
Parameters:
  • jid - Group JID
  • participants - Array of participant JIDs to promote
Returns:
  • Vec<ParticipantChangeResponse> - Result for each participant
Example:
promote_participants returns Vec<ParticipantChangeResponse> (one entry per participant) instead of ().

demote_participants

Demote admin participants to regular members.
Parameters:
  • jid - Group JID
  • participants - Array of admin JIDs to demote
Returns:
  • Vec<ParticipantChangeResponse> - Result for each participant
Example:
demote_participants returns Vec<ParticipantChangeResponse> (one entry per participant) instead of ().
Get or reset the group invite link.
Parameters:
  • jid - Group JID
  • reset - Whether to reset and generate a new invite link
Returns:
  • String - Invite link code
Example:

join_with_invite_code

Join a group using an invite code or full invite URL.
Parameters:
  • code - Invite code or full URL (e.g., "AbCdEfGh" or "https://chat.whatsapp.com/AbCdEfGh")
Returns:
  • JoinGroupResult - Either Joined(Jid) if immediately joined, or PendingApproval(Jid) if the group requires admin approval
Example:

join_with_invite_v4

Accept a V4 group invite received as a GroupInviteMessage (not a link). V4 invites are sent directly by a group admin as a message, rather than shared as a URL.
Parameters:
  • group_jid - The target group JID
  • code - Invite code from the GroupInviteMessage
  • expiration - Invite expiration timestamp (Unix seconds). The method returns an error if the invite has expired.
  • admin_jid - JID of the admin who sent the invite
Returns:
  • JoinGroupResult - Either Joined(Jid) if immediately joined, or PendingApproval(Jid) if the group requires admin approval
Example:
V4 invites expire. The method automatically checks the expiration timestamp and returns an error if the invite has already expired. You can pass 0 as the expiration to skip the expiration check.

get_invite_info

Get group metadata from an invite code without joining the group.
Parameters:
  • code - Invite code or full URL
Returns:
  • GroupMetadata - Group metadata (see get_participating for fields)
Example:

set_locked

Lock or unlock the group so only admins can change group info.
Parameters:
  • jid - Group JID
  • locked - true to lock (only admins edit info), false to unlock
Example:

set_announce

Set announcement mode. When enabled, only admins can send messages.
Parameters:
  • jid - Group JID
  • announce - true to enable (only admins send), false to disable
Example:

set_ephemeral

Set the disappearing messages timer on the group.
Parameters:
  • jid - Group JID
  • expiration - Timer duration in seconds. Common values: 86400 (24 hours), 604800 (7 days), 7776000 (90 days). Pass 0 to disable.
Example:

set_membership_approval

Set membership approval mode. When enabled, new members must be approved by an admin.
Parameters:
  • jid - Group JID
  • mode - MembershipApprovalMode::On to require approval, MembershipApprovalMode::Off to disable
Example:

get_membership_requests

Get pending membership approval requests for a group.
Parameters:
  • jid - Group JID
Returns:
  • Vec<MembershipRequest> - List of pending requests
Example:

approve_membership_requests

Approve pending membership requests for a group.
Parameters:
  • jid - Group JID
  • participants - Array of JIDs to approve
Returns:
  • Vec<ParticipantChangeResponse> - Result for each participant
Example:

reject_membership_requests

Reject pending membership requests for a group.
Parameters:
  • jid - Group JID
  • participants - Array of JIDs to reject
Returns:
  • Vec<ParticipantChangeResponse> - Result for each participant
Example:

set_member_add_mode

Set who can add members to the group.
Parameters:
  • jid - Group JID
  • mode - MemberAddMode::AdminAdd to restrict to admins, MemberAddMode::AllMemberAdd to allow all members
Example:

set_no_frequently_forwarded

Restrict or allow frequently-forwarded messages in the group.
Parameters:
  • jid - Group JID
  • restrict - true to restrict frequently-forwarded messages, false to allow them
Example:

set_allow_admin_reports

Enable or disable admin reports in the group.
Parameters:
  • jid - Group JID
  • allow - true to enable admin reports, false to disable
Example:

set_group_history

Enable or disable group history sharing.
Parameters:
  • jid - Group JID
  • enabled - true to enable group history, false to disable
Example:
Set who can share invite links. This uses the MEX (Mutation Exchange) protocol.
Parameters:
  • jid - Group JID
  • mode - MemberLinkMode::AdminLink to restrict to admins, MemberLinkMode::AllMemberLink to allow all members
Example:

set_member_share_history_mode

Set who can share message history with new members. This uses the MEX protocol.
Parameters:
  • jid - Group JID
  • mode - MemberShareHistoryMode::AdminShare to restrict to admins, MemberShareHistoryMode::AllMemberShare to allow all members
Example:

set_limit_sharing

Enable or disable limit sharing in the group. This uses the MEX protocol.
Parameters:
  • jid - Group JID
  • enabled - true to enable limit sharing, false to disable
Example:

cancel_membership_requests

Cancel pending membership requests from the requesting user’s side.
Parameters:
  • jid - Group JID
  • participants - Array of JIDs whose pending requests to cancel
Returns:
  • Vec<ParticipantChangeResponse> - Result for each participant
Example:

revoke_request_code

Revoke invitation codes from specific participants. This is an admin operation.
Parameters:
  • jid - Group JID
  • participants - Array of participant JIDs whose invitation codes to revoke
Returns:
  • Vec<ParticipantChangeResponse> - Result for each participant
Example:

acknowledge

Acknowledge a group notification.
Parameters:
  • jid - Group JID
Example:

update_member_label_with_id

Set or clear the bot’s per-group member label, sent as a ProtocolMessage over the normal message path (not an IQ). Returns the sent stanza’s message ID.
Parameters:
  • group_jid - Group JID
  • label - New label text, or an empty string to clear the label
Returns:
  • String - Message ID of the sent stanza
Example:
update_member_label is a thin wrapper around update_member_label_with_id that discards the message ID and returns Result<(), GroupError>, for callers that don’t need it.

batch_get_info

Batch query group info for multiple groups at once.
Parameters:
  • jids - List of group JIDs to query (max 10,000)
Returns:
  • Vec<BatchGroupResult> - Result for each group
Example:

set_profile_picture

Set a group’s profile picture. Admin operation.
Parameters:
  • group_jid - Group JID (must end with @g.us)
  • image_data - JPEG image bytes. The caller is responsible for sizing/cropping the image (WhatsApp uses 640x640).
Returns:
  • SetProfilePictureResponse - Contains the new picture ID
Passing empty image_data routes to removal, mirroring the own-picture API. Prefer remove_profile_picture when removal is the intent. Example:
The image must be a valid JPEG. Other formats are not supported. The caller must be a group admin.

remove_profile_picture

Remove a group’s profile picture. Admin operation.
Parameters:
  • group_jid - Group JID
Returns:
  • SetProfilePictureResponse - Confirmation of removal
Example:
See SetProfilePictureResponse for the response shape.

get_profile_pictures

Batch fetch group profile pictures.
Parameters:
  • group_jids - List of group JIDs (max 1,000)
  • picture_type - PictureType::Preview for thumbnails or PictureType::Image for full-size
Returns:
  • Vec<GroupProfilePicture> - Profile picture data for each group
Example:

Types

Freshness

Selects whether an operation may return an existing cached snapshot or must consult its source before returning. Shared across the SDK wherever a cache-backed lookup accepts an explicit staleness policy — Groups::query_info_with_freshness here, and StatusSendOptions::device_freshness (see Status).
Freshness is re-exported from the crate root, so you can import it directly: use whatsapp_rust::Freshness;. When you pass Refresh, you never see a caller-visible gap — the previous snapshot stays servable until the new one is published.

GroupInfo

Cached group information returned by query_info. Contains participant list, addressing mode, and LID-to-phone mappings for privacy-addressed groups. query_info returns Arc<GroupInfo> so that repeated lookups and warm sends share the same snapshot without deep-cloning the participants list.
Methods: Example:

GroupSubject

Validated group name with 100 character limit.

GroupDescription

Validated group description with 2048 character limit.

PreviousDescription

The description a set_description call expects to replace — the server’s optimistic-concurrency token for the group’s description.
  • Resolve (default) — read the group’s current description id from the server before sending. The only variant that’s correct without knowing anything about the group, and the only one that costs a round trip.
  • Absent — the group carries no description yet (e.g. one you just created), so no token is sent.
  • Id(&str) — a description id you already hold, typically GroupMetadata::description_id from a recent get_metadata call.
From<Option<&str>> lets you turn a held GroupMetadata::description_id into a token directly: None maps to Absent (that metadata says the group has no description), Some(id) maps to Id(id). Use Resolve instead when the metadata’s age is unknown, since stale metadata that missed a description added since would otherwise surface as GroupError::DescriptionConflict.

GroupEphemeralSettings

Disappearing-message settings carried by a group’s <ephemeral> node.

MemberAddMode

ParticipantType

Participant role within a group.
Methods:
  • is_admin(&self) -> bool - Returns true if admin or super admin

GroupParticipantDetails

Less-common participant metadata. Boxed on GroupParticipant/GroupParticipantResponse and only populated when at least one field is present.
GroupParticipantDetails is #[non_exhaustive]. Field reads are unaffected; only exhaustive struct destructuring from outside the crate requires adding ...

MemberLinkMode

Controls who can use invite links to join the group.

MemberShareHistoryMode

Controls who can share message history with new members.

MembershipApprovalMode

GroupAppealStatus

Review state for an appeal on a suspended group.

GroupParticipantOptions

Options for specifying a participant when creating or modifying a group.
Constructors:
  • GroupParticipantOptions::new(jid) - Create from a JID
  • GroupParticipantOptions::from_phone(phone_number) - Create from a phone number JID
  • GroupParticipantOptions::from_lid_and_phone(lid, phone_number) - Create from a LID and phone number
Builder methods:
  • .with_phone_number(jid) - Attach a phone number JID (for LID participants)
  • .with_privacy(token) - Attach a privacy token (tc_token bytes)
You typically don’t need to set the privacy field manually. When AB props are enabled, the library automatically resolves and attaches privacy tokens during create_group and add_participants operations.
Example:

JoinGroupResult

Result of joining a group via invite code.
Methods:
  • group_jid(&self) -> &Jid - Returns the group JID regardless of result variant

MembershipRequest

A pending membership approval request.

ParticipantChangeResponse

Result of a participant change operation (add, remove, approve, reject).
ParticipantChangeResponse is #[non_exhaustive]. Field reads are unaffected; only exhaustive struct destructuring from outside the crate requires adding ...
add_request is populated when the server responds with HTTP 403 carrying an <add_request> child — that happens when a participant has privacy blocked direct adds and the inviter must send them a v4 invite link out-of-band. Since v0.6 the value is preserved instead of being dropped, so consumers can drive the v4 invite flow without parsing the raw IQ.

AddressingMode

BatchGroupResult

Result for a single group in a batch query.

GrowthLockInfo

Growth lock information (system-managed, read-only). When present, invite links are temporarily disabled by the system.

PictureType

Profile picture query type for batch fetching.

GroupProfilePicture

A single group profile picture result from a batch query.

CreateGroupResult

Result of creating a group.
CreateGroupResult is #[non_exhaustive]. Field reads are unaffected; only exhaustive struct destructuring from outside the crate requires adding ...
The metadata field carries the full group state returned by the server (same shape as get_metadata). metadata.participants is Vec<GroupParticipant> — masked-number display_name labels are reachable via participant.details.as_ref().and_then(|d| d.display_name.as_deref()), or from the event-side GroupParticipantInfo (which carries <participant> children of notification events) when handling live group-update events.
Prior to v0.6 this struct only exposed a gid: Jid. Replace result.gid with result.metadata.id when upgrading (GroupMetadata.id, not jid). The same migration applies to CreateCommunityResult.

GroupJoinError

Error codes returned when joining a group via invite fails.
Methods:
  • from_code(code: u16) -> Self - Create from a numeric status code
  • code(&self) -> u16 - Get the numeric status code

InviteInfoError

Error codes returned when fetching group info from an invite code.
Methods:
  • from_code(code: u16) -> Self - Create from a numeric status code
  • code(&self) -> u16 - Get the numeric status code

Error types

GroupError

All group methods return Result<T, GroupError>:
Variants:
  • Iq — IQ request failed (timeout, server rejection, etc.)
  • Mex — MEX protocol error (for methods using the MEX transport)
  • InvalidRequest — malformed request (expired invite, missing fields, etc.)
  • DescriptionConflictset_description’s prev token no longer matches the group’s current description (the server answered 409 conflict); another device changed it first. Kept distinct from a permission refusal so a caller can re-read the description and retry instead of giving up.
  • Internal — catch-all for other errors