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
id
field is mandatory, in most cases you want this to be the same ID you use on your database. - The
role
field is optional, by default it is set touser
but you can specify any existing role. - Custom data can be added to users in the
custom
field. name
andimage
are 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();
$response = $this->client->updateUsers(new GeneratedModels\UpdateUsersRequest(
users: [
$this->testUserId => [
'id' => $this->testUserId,
'name' => 'Test User 1',
'role' => 'user'
],
$this->testUserId2 => [
'id' => $this->testUserId2,
'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)
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();
$response = $this->client->updateUsers(new GeneratedModels\UpdateUsersRequest(
users: [
$this->testUserId => [
'id' => $this->testUserId,
'name' => 'Test User 1',
'role' => 'user'
],
$this->testUserId2 => [
'id' => $this->testUserId2,
'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)
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();
$response = $this->client->updateUsers(new GeneratedModels\UpdateUsersRequest(
users: [
$this->testUserId => [
'id' => $this->testUserId,
'name' => 'Test User 1',
'role' => 'user'
],
$this->testUserId2 => [
'id' => $this->testUserId2,
'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)
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();
$response = $this->client->updateUsers(new GeneratedModels\UpdateUsersRequest(
users: [
$this->testUserId => [
'id' => $this->testUserId,
'name' => 'Test User 1',
'role' => 'user'
],
$this->testUserId2 => [
'id' => $this->testUserId2,
'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)
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();
$response = $this->client->updateUsers(new GeneratedModels\UpdateUsersRequest(
users: [
$this->testUserId => [
'id' => $this->testUserId,
'name' => 'Test User 1',
'role' => 'user'
],
$this->testUserId2 => [
'id' => $this->testUserId2,
'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)
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();
$response = $this->client->updateUsers(new GeneratedModels\UpdateUsersRequest(
users: [
$this->testUserId => [
'id' => $this->testUserId,
'name' => 'Test User 1',
'role' => 'user'
],
$this->testUserId2 => [
'id' => $this->testUserId2,
'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)