const newUser: UserRequest = { id: 'user-id', role: 'user', custom: { color: 'red', }, name: 'This is a test user', image: 'link/to/profile/image', }; await client.upsertUsers([newUser]);User management
The operations performed on users, such as updating and deleting, have an effect on all products (chat, feeds and video).
Creating users
When creating users, there are a few important things to keep in mind:
- The
idfield is mandatory, in most cases you want this to be the same ID you use on your database. - The
rolefield is optional, by default it is set touserbut you can specify any existing role. - Custom data can be added to users in the
customfield. nameandimageare optional and handled by all SDKs automatically to render users.
users := map[string]getstream.UserRequest{ "user1": { ID: "user1", Name: getstream.PtrTo("Test User 1"), Role: getstream.PtrTo("user"), }, "user2": { ID: "user2", Name: getstream.PtrTo("Test User 2"), Role: getstream.PtrTo("user"), }, } request := &getstream.UpdateUsersRequest{ Users: users, } response, err := client.UpdateUsers(context.Background(), request) if err != nil { log.Fatal("Error updating users:", err) } log.Printf("Users updated successfully: %+v\n", response)Map<String, UserRequest> usersMap = new HashMap<>(); usersMap.put( testUserId, UserRequest.builder().id(testUserId).name("Test User 1").role("user").build()); usersMap.put( testUserId2, UserRequest.builder().id(testUserId2).name("Test User 2").role("user").build()); UpdateUsersRequest updateUsersRequest = UpdateUsersRequest.builder().users(usersMap).build(); client.updateUsers(updateUsersRequest).execute();use GetStream\ClientBuilder; use GetStream\GeneratedModels; $client = (new ClientBuilder()) ->apiKey($apiKey) ->apiSecret($apiSecret) ->build(); $response = $client->updateUsers(new GeneratedModels\UpdateUsersRequest( users: [ 'user-id-1' => [ 'id' => 'user-id-1', 'name' => 'Test User 1', 'role' => 'user', 'custom' => (object)[ 'color' => 'red' ] ], 'user-id-2' => [ 'id' => 'user-id-2', 'name' => 'Test User 2', 'role' => 'user' ] ] ));var updateUsersRequest = new UpdateUsersRequest { Users = new Dictionary<string, UserRequest> { [_testUserId] = new UserRequest { ID = _testUserId, Name = "Test User 1", Role = "user" }, [_testUserId2] = new UserRequest { ID = _testUserId2, Name = "Test User 2", Role = "user" }, [_testUserId3] = new UserRequest { ID = _testUserId3, Name = "Test User 3", Role = "user" } } }; var userResponse = await _client.UpdateUsersAsync(updateUsersRequest);users = { self.test_user_id: UserRequest( id=self.test_user_id, name="Test User 1", role="user" ), self.test_user_id_2: UserRequest( id=self.test_user_id_2, name="Test User 2", role="user" ), } response = self.client.update_users(users=users)# Create/update users in batch update_request = GetStream::Generated::Models::UpdateUsersRequest.new( users: { 'user1' => { 'id' => 'user1', 'name' => 'Test User 1', 'role' => 'user', }, 'user2' => { 'id' => 'user2', 'name' => 'Test User 2', 'role' => 'user', }, }, ) response = client.common.update_users(update_request)Updating users
You can update users in two ways:
- Replace updates: replace the entire user object with the one provided to the API call
- Partial update: choose which fields you want to change
const user: UserRequest = { id: 'userid', role: 'user', custom: { color: 'blue', }, name: 'This is a test user', image: 'link/to/profile/image', }; client.upsertUsers([user]); // or client.updateUsersPartial({ users: [ { id: user.id, set: { 'new-field': 'value', }, unset: ['name'], }, ], });// Example 1: Upsert users user := getstream.UserRequest{ ID: "userid", Role: getstream.PtrTo("user"), Custom: map[string]any{ "color": "blue", }, Name: getstream.PtrTo("This is a test user"), Image: getstream.PtrTo("link/to/profile/image"), } upsertRequest := &getstream.UpdateUsersRequest{ Users: map[string]getstream.UserRequest{ user.ID: user, }, } upsertResponse, err := client.UpdateUsers(context.Background(), upsertRequest) if err != nil { log.Fatal("Error upserting users:", err) } log.Printf("Users upserted successfully: %+v\n", upsertResponse) // Example 2: Partial update users partialUpdateRequest := &getstream.UpdateUsersPartialRequest{ Users: []getstream.UpdateUserPartialRequest{ { ID: user.ID, Set: map[string]any{ "new-field": "value", }, Unset: []string{"name"}, }, }, } partialResponse, err := client.UpdateUsersPartial(context.Background(), partialUpdateRequest) if err != nil { log.Fatal("Error partially updating users:", err) } log.Printf("Users partially updated successfully: %+v\n", partialResponse)Map<String, UserRequest> usersMap = new HashMap<>(); usersMap.put( testUserId, UserRequest.builder().id(testUserId).name("Test User 1").role("user").build()); usersMap.put( testUserId2, UserRequest.builder().id(testUserId2).name("Test User 2").role("user").build()); UpdateUsersRequest updateUsersRequest = UpdateUsersRequest.builder().users(usersMap).build(); client.updateUsers(updateUsersRequest).execute();// Example 1: Upsert users (replace update) $client->updateUsers(new GeneratedModels\UpdateUsersRequest( users: [ 'userid' => [ 'id' => 'userid', 'name' => 'This is a test user', 'role' => 'user', 'custom' => (object)[ 'color' => 'blue' ], 'image' => 'link/to/profile/image' ] ] )); // Example 2: Partial update users $client->updateUsersPartial(new GeneratedModels\UpdateUsersPartialRequest( users: [ [ 'id' => 'userid', 'set' => (object)[ 'new-field' => 'value' ], 'unset' => ['name'] ] ] ));var updateUsersRequest = new UpdateUsersRequest { Users = new Dictionary<string, UserRequest> { [_testUserId] = new UserRequest { ID = _testUserId, Name = "Test User 1", Role = "user" }, [_testUserId2] = new UserRequest { ID = _testUserId2, Name = "Test User 2", Role = "user" }, [_testUserId3] = new UserRequest { ID = _testUserId3, Name = "Test User 3", Role = "user" } } }; var userResponse = await _client.UpdateUsersAsync(updateUsersRequest);users = { self.test_user_id: UserRequest( id=self.test_user_id, name="Test User 1", role="user" ), self.test_user_id_2: UserRequest( id=self.test_user_id_2, name="Test User 2", role="user" ), } response = self.client.update_users(users=users)# Partially update user partial_request = GetStream::Generated::Models::UpdateUsersPartialRequest.new( users: [ { 'id' => 'userid', 'set' => { 'name' => 'Updated Name', }, }, ], ) response = client.common.update_users_partial(partial_request)Anonymous users
Anonymous users are users that are not authenticated. It’s common to use this for watching a livestream or similar where you aren’t authenticated. Anonymous users can be connected using client-side SDKs. Anonymous users are not counted toward your MAU.
Guest users
Guest users are temporary user accounts. You can use it to temporarily give someone a name and image when joining a call. Guest users can be created client-side. Guest users are counted towards your MAU usage.
Deactivating and deleting users
Depending on your use-case, you can choose to delete users or de-activating them. There are some differences between these two approach.
Deactivating users:
- the user will not be allowed to perform API requests / connect
- user data is retained on Stream’s side and returned from API
- deactivated users can be re-activated
Deleting users:
- the user will no longer be able to perform API requests / connect
- the user is deleted and by default not returned from API
- all data from the user is marked as deleted
- by default the data is retained and “soft” deleted, you can optionally request hard deletion
- deletion is not reversible
Note: Both deletion and deactivation are performed asynchronously by Stream API. A task ID is returned and you can use that to check the status of its processing.
Deactivating users
client.deactivateUser({ user_id: '<id>', }); // reactivate client.reactivateUsers({ user_ids: ['<id>'], }); // deactivating users in bulk is performed asynchronously const deactivateResponse = client.deactivateUsers({ user_ids: ['<id1>', '<id2>'...], });// Deactivating a single user _, err = client.DeactivateUser(context.Background(), "user1", &getstream.DeactivateUserRequest{}) if err != nil { log.Fatal("Error deactivating user:", err) } log.Printf("User deactivated successfully") // Deactivating users in bulk is performed asynchronously _, err = client.DeactivateUsers(context.Background(), &getstream.DeactivateUsersRequest{ UserIds: []string{"user2"}, }) if err != nil { log.Fatal("Error deactivating users:", err) } log.Printf("Users deactivated successfully") // Reactivate users reactivateRequest := &getstream.ReactivateUsersRequest{ UserIds: []string{"user1", "user2"}, } _, err = client.ReactivateUsers(context.Background(), reactivateRequest) if err != nil { log.Fatal("Error reactivating users:", err) } log.Printf("Users reactivated successfully")Map<String, UserRequest> usersMap = new HashMap<>(); usersMap.put( testUserId, UserRequest.builder().id(testUserId).name("Test User 1").role("user").build()); usersMap.put( testUserId2, UserRequest.builder().id(testUserId2).name("Test User 2").role("user").build()); UpdateUsersRequest updateUsersRequest = UpdateUsersRequest.builder().users(usersMap).build(); client.updateUsers(updateUsersRequest).execute();// Deactivating a single user $client->deactivateUser( 'user1', new GeneratedModels\DeactivateUserRequest() ); // Deactivating users in bulk is performed asynchronously $response = $client->deactivateUsers( new GeneratedModels\DeactivateUsersRequest( userIds: ['user1', 'user2'] ) ); // Reactivate users $client->reactivateUsers( new GeneratedModels\ReactivateUsersRequest( userIds: ['user1', 'user2'] ) );var updateUsersRequest = new UpdateUsersRequest { Users = new Dictionary<string, UserRequest> { [_testUserId] = new UserRequest { ID = _testUserId, Name = "Test User 1", Role = "user" }, [_testUserId2] = new UserRequest { ID = _testUserId2, Name = "Test User 2", Role = "user" }, [_testUserId3] = new UserRequest { ID = _testUserId3, Name = "Test User 3", Role = "user" } } }; var userResponse = await _client.UpdateUsersAsync(updateUsersRequest);users = { self.test_user_id: UserRequest( id=self.test_user_id, name="Test User 1", role="user" ), self.test_user_id_2: UserRequest( id=self.test_user_id_2, name="Test User 2", role="user" ), } response = self.client.update_users(users=users)Deactivating users in bulk can take some time, this is how you can check the progress:
// Example of monitoring the status of an async task // The logic is same for all async tasks const response = await client.exportUsers({ user_ids: ["<user id1>", "<user id1>"], }); // you need to poll this endpoint const taskResponse = await client.getTask({ id: response.task_id }); console.log(taskResponse.status === "completed");// Example of monitoring the status of an async task // The logic is same for all async tasks response, err := client.ExportUsers(context.Background(), &getstream.ExportUsersRequest{ UserIds: []string{"<user id1>", "<user id2>"}, }) if err != nil { log.Fatal(err) } // you need to poll this endpoint taskResponse, err := client.GetTask(context.Background(), response.Data.TaskID, &getstream.GetTaskRequest{}) if err != nil { log.Fatal(err) } fmt.Println(taskResponse.Data.Status == "completed")Map<String, UserRequest> usersMap = new HashMap<>(); usersMap.put( testUserId, UserRequest.builder().id(testUserId).name("Test User 1").role("user").build()); usersMap.put( testUserId2, UserRequest.builder().id(testUserId2).name("Test User 2").role("user").build()); UpdateUsersRequest updateUsersRequest = UpdateUsersRequest.builder().users(usersMap).build(); client.updateUsers(updateUsersRequest).execute();// Example of monitoring the status of an async task // The logic is same for all async tasks $response = $client->exportUsers( new GeneratedModels\ExportUsersRequest( userIds: ['<user id1>', '<user id2>'] ) ); $responseData = $response->getData(); $taskId = $responseData->taskID; // you need to poll this endpoint $taskResponse = $client->getTask($taskId); $taskData = $taskResponse->getData(); echo $taskData->status === 'completed';var updateUsersRequest = new UpdateUsersRequest { Users = new Dictionary<string, UserRequest> { [_testUserId] = new UserRequest { ID = _testUserId, Name = "Test User 1", Role = "user" }, [_testUserId2] = new UserRequest { ID = _testUserId2, Name = "Test User 2", Role = "user" }, [_testUserId3] = new UserRequest { ID = _testUserId3, Name = "Test User 3", Role = "user" } } }; var userResponse = await _client.UpdateUsersAsync(updateUsersRequest);users = { self.test_user_id: UserRequest( id=self.test_user_id, name="Test User 1", role="user" ), self.test_user_id_2: UserRequest( id=self.test_user_id_2, name="Test User 2", role="user" ), } response = self.client.update_users(users=users)Deleting users
client.deleteUsers({ user_ids: ["<id>"] }); //restore client.restoreUsers({ user_ids: ["<id>"] });// Delete users deleteRequest := &getstream.DeleteUsersRequest{ UserIds: []string{"<id>"}, } _, err = client.DeleteUsers(context.Background(), deleteRequest) // Restore users restoreRequest := &getstream.RestoreUsersRequest{ UserIds: []string{"<id>"}, } _, err = client.RestoreUsers(context.Background(), restoreRequest)Map<String, UserRequest> usersMap = new HashMap<>(); usersMap.put( testUserId, UserRequest.builder().id(testUserId).name("Test User 1").role("user").build()); usersMap.put( testUserId2, UserRequest.builder().id(testUserId2).name("Test User 2").role("user").build()); UpdateUsersRequest updateUsersRequest = UpdateUsersRequest.builder().users(usersMap).build(); client.updateUsers(updateUsersRequest).execute();// Delete users (soft delete by default) $client->deleteUsers( new GeneratedModels\DeleteUsersRequest( userIds: ['<id>'] ) ); // Delete users with options (hard delete) $client->deleteUsers( new GeneratedModels\DeleteUsersRequest( userIds: ['<id>'], user: 'hard', messages: 'hard', conversations: 'hard', newChannelOwnerID: 'new-owner-id' ) ); // Restore users $client->restoreUsers( new GeneratedModels\RestoreUsersRequest( userIds: ['<id>'] ) );var updateUsersRequest = new UpdateUsersRequest { Users = new Dictionary<string, UserRequest> { [_testUserId] = new UserRequest { ID = _testUserId, Name = "Test User 1", Role = "user" }, [_testUserId2] = new UserRequest { ID = _testUserId2, Name = "Test User 2", Role = "user" }, [_testUserId3] = new UserRequest { ID = _testUserId3, Name = "Test User 3", Role = "user" } } }; var userResponse = await _client.UpdateUsersAsync(updateUsersRequest);users = { self.test_user_id: UserRequest( id=self.test_user_id, name="Test User 1", role="user" ), self.test_user_id_2: UserRequest( id=self.test_user_id_2, name="Test User 2", role="user" ), } response = self.client.update_users(users=users)# Delete users in batch delete_request = GetStream::Generated::Models::DeleteUsersRequest.new( user_ids: ['user1', 'user2'], user: 'hard', ) response = client.common.delete_users(delete_request)The delete users endpoints supports the following parameters to control which data needs to be deleted and how. By default users and their data are soft-deleted.
| Name | Type | Description | Optional |
|---|---|---|---|
user | Enum (soft, pruning, hard) | - Soft: marks user as deleted and retains all user data. - Pruning: marks user as deleted and nullifies user information. - Hard: deletes user completely - this requires hard option for messages and conversation as well. | Yes |
conversations | Enum (soft, hard) | - Soft: marks all conversation channels as deleted (same effect as Delete Channels with ‘hard’ option disabled). - Hard: deletes channel and all its data completely including messages (same effect as Delete Channels with ‘hard’ option enabled). | Yes |
messages | Enum (soft, pruning, hard) | - Soft: marks all user messages as deleted without removing any related message data. - Pruning: marks all user messages as deleted, nullifies message information and removes some message data such as reactions and flags. - Hard: deletes messages completely with all related information. | Yes |
new_channel_owner_id | string | Channels owned by hard-deleted users will be transferred to this userID. If you doesn’t provide a value, the channel owner will have a system generated ID like delete-user-8219f6578a7395g | Yes |
calls | Enum (soft, hard) | - Soft: marks calls and related data as deleted. - Hard: deletes calls and related data completely Note that this applies only to 1:1 calls, not group calls | Yes |
Deleting users in bulk can take some time, this is how you can check the progress:
// Example of monitoring the status of an async task // The logic is same for all async tasks const response = await client.exportUsers({ user_ids: ["<user id1>", "<user id1>"], }); // you need to poll this endpoint const taskResponse = await client.getTask({ id: response.task_id }); console.log(taskResponse.status === "completed");// Example of monitoring the status of an async task // The logic is same for all async tasks response, err := client.ExportUsers(context.Background(), &getstream.ExportUsersRequest{ UserIds: []string{"<user id1>", "<user id2>"}, }) if err != nil { log.Fatal(err) } // you need to poll this endpoint taskResponse, err := client.GetTask(context.Background(), response.Data.TaskID, &getstream.GetTaskRequest{}) if err != nil { log.Fatal(err) } fmt.Println(taskResponse.Data.Status == "completed")Map<String, UserRequest> usersMap = new HashMap<>(); usersMap.put( testUserId, UserRequest.builder().id(testUserId).name("Test User 1").role("user").build()); usersMap.put( testUserId2, UserRequest.builder().id(testUserId2).name("Test User 2").role("user").build()); UpdateUsersRequest updateUsersRequest = UpdateUsersRequest.builder().users(usersMap).build(); client.updateUsers(updateUsersRequest).execute();// Example of monitoring the status of an async task // The logic is same for all async tasks $response = $client->exportUsers( new GeneratedModels\ExportUsersRequest( userIds: ['<user id1>', '<user id2>'] ) ); $responseData = $response->getData(); $taskId = $responseData->taskID; // you need to poll this endpoint $taskResponse = $client->getTask($taskId); $taskData = $taskResponse->getData(); echo $taskData->status === 'completed';var updateUsersRequest = new UpdateUsersRequest { Users = new Dictionary<string, UserRequest> { [_testUserId] = new UserRequest { ID = _testUserId, Name = "Test User 1", Role = "user" }, [_testUserId2] = new UserRequest { ID = _testUserId2, Name = "Test User 2", Role = "user" }, [_testUserId3] = new UserRequest { ID = _testUserId3, Name = "Test User 3", Role = "user" } } }; var userResponse = await _client.UpdateUsersAsync(updateUsersRequest);users = { self.test_user_id: UserRequest( id=self.test_user_id, name="Test User 1", role="user" ), self.test_user_id_2: UserRequest( id=self.test_user_id_2, name="Test User 2", role="user" ), } response = self.client.update_users(users=users)