Documentation Index Fetch the complete documentation index at: https://mintlify.com/xmtp/libxmtp/llms.txt
Use this file to discover all available pages before exploring further.
Groups are the core of XMTP conversations. This guide covers creating groups, managing membership, and working with direct messages.
Creating Groups
Basic Group Creation
Create a new group with default settings:
use xmtp_mls :: groups :: MlsGroup ;
// Create an empty group
let group = client . create_group ( None , None ) ? ;
When you create a group, you are automatically:
Added as the only member
Designated as a super admin
Required to update installations before other operations
Create Group with Members
Add members at creation time using wallet addresses:
use xmtp_id :: associations :: Identifier ;
let members = vec! [
Identifier :: Address ( "0x1234..." . to_string ()),
Identifier :: Address ( "0x5678..." . to_string ()),
];
let group = client . create_group_with_identifiers (
& members ,
None , // Default permissions
None , // Default metadata
) . await ? ;
Or use inbox IDs directly:
let inbox_ids = vec! [ "inbox_1" , "inbox_2" ];
let group = client . create_group_with_members (
& inbox_ids ,
None , // permissions
None , // metadata
) . await ? ;
Set group name, description, and image:
use xmtp_mls_common :: group :: GroupMetadataOptions ;
use xmtp_mls_common :: group_mutable_metadata :: MessageDisappearingSettings ;
let metadata = GroupMetadataOptions {
name : Some ( "My Group" . to_string ()),
description : Some ( "A group for friends" . to_string ()),
image_url_square : Some ( "https://example.com/image.jpg" . to_string ()),
pinned_frame_url : None ,
message_disappearing_settings : None ,
};
let group = client . create_group ( None , Some ( metadata )) ? ;
Managing Members
Add members by wallet address:
use xmtp_id :: associations :: Identifier ;
let new_members = vec! [
Identifier :: Address ( "0xabcd..." . to_string ()),
];
let result = group . add_members_by_identity ( & new_members ) . await ? ;
println! ( "Added {} installations" , result . added_members . len ());
let inbox_ids = vec! [ "inbox_id_here" ];
let result = group . add_members ( & inbox_ids ) . await ? ;
Remove members by wallet address:
let members_to_remove = vec! [
Identifier :: Address ( "0x1234..." . to_string ()),
];
group . remove_members_by_identity ( & members_to_remove ) . await ? ;
group . remove_members ( & [ "inbox_id" ]) . await ? ;
Get all current group members:
let members = group . members () . await ? ;
for member in members {
println! ( "Inbox: {}" , member . inbox_id);
println! ( " Installations: {}" , member . installation_ids . len ());
println! ( " Permission: {:?}" , member . permission_level);
}
Direct Messages (DMs)
DMs are a special type of group limited to two participants.
Find or Create DM
The recommended approach automatically handles duplicate DMs:
use xmtp_id :: associations :: Identifier ;
// By wallet address
let dm = client . find_or_create_dm_by_identity (
Identifier :: Address ( "0x5678..." . to_string ()),
None , // metadata options
) . await ? ;
// By inbox ID
let dm = client . find_or_create_dm (
"inbox_id_here" ,
None ,
) . await ? ;
find_or_create_dm prevents duplicate DMs by:
Checking for existing active DMs with the target inbox
Returning the existing DM if found
Creating a new DM only if none exists
Customize DM settings:
use xmtp_mls_common :: group :: DMMetadataOptions ;
let dm_metadata = DMMetadataOptions {
name : Some ( "Chat with Alice" . to_string ()),
image_url_square : Some ( "https://example.com/alice.jpg" . to_string ()),
message_disappearing_settings : None ,
};
let dm = client . find_or_create_dm (
target_inbox_id ,
Some ( dm_metadata ),
) . await ? ;
Syncing Groups
Sync Welcomes
Fetch groups you’ve been added to:
// Download and process welcome messages
let new_groups = client . sync_welcomes () . await ? ;
println! ( "Joined {} new groups" , new_groups . len ());
Sync Group Messages
Update a specific group:
// Fetch new messages and membership updates
group . sync () . await ? ;
Sync all groups:
let groups = client . find_groups ( GroupQueryArgs :: default ()) ? ;
let summary = client . sync_all_groups ( groups ) . await ? ;
println! ( "Synced {} groups" , summary . num_groups_synced);
Combined Sync
Sync welcomes and all groups in one call:
use xmtp_db :: consent_record :: ConsentState ;
// Only sync allowed/unknown groups
let summary = client . sync_all_welcomes_and_groups (
Some ( vec! [ ConsentState :: Allowed , ConsentState :: Unknown ])
) . await ? ;
println! ( "Total groups synced: {}" , summary . num_groups_synced);
Querying Groups
Find Groups
Query with filters:
use xmtp_db :: group :: { GroupQueryArgs , GroupMembershipState , ConversationType };
let args = GroupQueryArgs :: default ()
. allowed_states ( vec! [ GroupMembershipState :: Allowed ])
. conversation_types ( vec! [ ConversationType :: Group ]) // Exclude DMs
. created_after_ns ( Some ( start_time ))
. limit ( Some ( 50 ));
let groups = client . find_groups ( args ) ? ;
Get Specific Group
Look up by group ID:
let group = client . group ( & group_id ) ? ;
Get DM by target inbox:
let dm = client . dm_group_from_target_inbox ( target_inbox_id ) ? ;
List Conversations
Get conversations with last message:
use xmtp_db :: group :: GroupQueryOrderBy ;
let args = GroupQueryArgs :: default ()
. order_by ( Some ( GroupQueryOrderBy :: LastActivity ));
let conversations = client . list_conversations ( args ) ? ;
for conv in conversations {
println! ( "Group: {:?}" , conv . group . group_id);
if let Some ( msg ) = conv . last_message {
println! ( " Last message at: {}" , msg . sent_at_ns);
}
}
Group admins can update metadata:
// Update group name
group . update_group_name ( "New Name" . to_string ()) . await ? ;
// Update description
group . update_group_description ( "New description" . to_string ()) . await ? ;
// Update image
group . update_group_image_url_square ( "https://new-image.jpg" . to_string ()) . await ? ;
Group Properties
// Basic properties
let group_id = group . group_id . clone ();
let created_at = group . created_at_ns;
let conversation_type = group . conversation_type;
// Check if DM
if conversation_type == ConversationType :: Dm {
println! ( "This is a direct message" );
}
// Get metadata
let metadata = group . metadata () ? ;
println! ( "Name: {:?}" , metadata . group_name);
println! ( "Description: {:?}" , metadata . description);
Error Handling
Common group management errors:
use xmtp_mls :: groups :: GroupError ;
match group . add_members ( & inbox_ids ) . await {
Ok ( result ) => {
println! ( "Added {} members" , result . added_members . len ());
}
Err ( GroupError :: UserLimitExceeded ) => {
eprintln! ( "Group is full (max {} members)" , MAX_GROUP_SIZE );
}
Err ( GroupError :: NotFound ( NotFound :: InboxIdForAddress ( addr ))) => {
eprintln! ( "Address {} not found on network" , addr );
}
Err ( GroupError :: InvalidPermission ) => {
eprintln! ( "You don't have permission to add members" );
}
Err ( e ) => {
eprintln! ( "Failed to add members: {}" , e );
}
}
Best Practices
Regularly sync to get updates:
// Before important operations
group . sync () . await ? ;
// Or use periodic background sync
let summary = client . sync_all_welcomes_and_groups ( None ) . await ? ;
Group members may add new installations:
// Update group to include new installations
group . update_installations () . await ? ;
Use find_or_create for DMs
Always use find_or_create_dm to prevent duplicates:
// Good - prevents duplicates
let dm = client . find_or_create_dm ( inbox_id , None ) . await ? ;
// Avoid - can create duplicates
// let dm = client.create_dm_by_inbox_id(inbox_id, None).await?;
Check if addresses can receive messages:
let identifiers = vec! [
Identifier :: Address ( "0x1234..." . to_string ()),
];
let can_message = client . can_message ( & identifiers ) . await ? ;
for ( identifier , can_msg ) in can_message {
if ! can_msg {
println! ( "Cannot message {}" , identifier );
}
}
Next Steps
Sending Messages Send and receive messages in groups
Permissions and Policies Configure who can perform actions in groups