Users
June 16, 2026 ยท View on GitHub
This guide shows how to migrate user operations from stream-chat-net to getstream-net.
Upsert a Single User
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var userClient = clientFactory.GetUserClient();
var user = new UserRequest
{
Id = "bob-1",
Role = Role.Admin,
Teams = new[] { "red", "blue" }
};
user.SetData("age", 27);
var response = await userClient.UpsertAsync(user);
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var response = await client.UpdateUsersAsync(new UpdateUsersRequest
{
Users = new Dictionary<string, UserRequest>
{
["bob-1"] = new UserRequest
{
ID = "bob-1",
Role = "admin",
Teams = new List<string> { "red", "blue" },
Custom = new Dictionary<string, object> { { "age", 27 } }
}
}
});
Key changes:
UpsertAsync()onIUserClientbecomesUpdateUsersAsync()onStreamClientwith a dictionary-based request- Custom data uses the
Customdictionary instead ofSetData() - Roles are plain strings instead of
Role.*constants. The built-in user roles areadmin,user,moderator,guest, andanonymous(all lowercase). Custom roles defined in your app are also valid.
Batch Upsert Users
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var userClient = clientFactory.GetUserClient();
var jane = new UserRequest { Id = "jane" };
var june = new UserRequest { Id = "june" };
var users = await userClient.UpsertManyAsync(new[] { jane, june });
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var response = await client.UpdateUsersAsync(new UpdateUsersRequest
{
Users = new Dictionary<string, UserRequest>
{
["jane"] = new UserRequest { ID = "jane" },
["june"] = new UserRequest { ID = "june" }
}
});
Key changes:
UpsertManyAsync()with an array becomesUpdateUsersAsync()with a dictionary keyed by user ID- The same method handles both single and batch upserts
Query Users
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var userClient = clientFactory.GetUserClient();
var response = await userClient.QueryAsync(new QueryUserOptions
{
Filter = new Dictionary<string, object>
{
{ "role", new Dictionary<string, object> { { "$eq", "admin" } } }
},
Sort = new[] { new SortParameter { Field = "created_at", Direction = SortDirection.Descending } },
Offset = 0,
Limit = 10
});
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var response = await client.QueryUsersAsync(new QueryUsersPayload
{
FilterConditions = new Dictionary<string, object>
{
{ "role", new Dictionary<string, object> { { "$eq", "admin" } } }
},
Sort = new List<SortParamRequest>
{
new SortParamRequest { Field = "created_at", Direction = -1 }
},
Offset = 0,
Limit = 10
});
Key changes:
QueryAsync()onIUserClientbecomesQueryUsersAsync()onStreamClient- Pass a typed
QueryUsersPayload; the SDK serializes it to thepayloadquery parameter for you - Sort uses
SortParamRequestwithDirection = -1(descending) or1(ascending)
Partial Update User
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var userClient = clientFactory.GetUserClient();
await userClient.UpdatePartialAsync(new UserPartialRequest
{
Id = "bob-1",
Set = new Dictionary<string, object> { { "age", 28 }, { "city", "Amsterdam" } },
Unset = new[] { "nickname" }
});
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
await client.UpdateUsersPartialAsync(new UpdateUsersPartialRequest
{
Users = new List<UpdateUserPartialRequest>
{
new UpdateUserPartialRequest
{
ID = "bob-1",
Set = new Dictionary<string, object> { { "age", 28 }, { "city", "Amsterdam" } },
Unset = new List<string> { "nickname" }
}
}
});
Key changes:
UpdatePartialAsync()onIUserClientbecomesUpdateUsersPartialAsync()onStreamClient- Request wraps partials in a
Userslist, enabling batch partial updates in one call
Deactivate User
Before (stream-chat-net):
using StreamChat.Clients;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var userClient = clientFactory.GetUserClient();
await userClient.DeactivateAsync("bob-1", markMessagesDeleted: true, createdById: "admin-user");
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
await client.DeactivateUserAsync("bob-1", new DeactivateUserRequest
{
MarkMessagesDeleted = true,
CreatedByID = "admin-user"
});
Key changes:
- Positional parameters become a
DeactivateUserRequestobject - User ID is a separate path parameter
Reactivate User
Before (stream-chat-net):
using StreamChat.Clients;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var userClient = clientFactory.GetUserClient();
await userClient.ReactivateAsync("bob-1", restoreMessages: true, name: "Bob", createdById: "admin-user");
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
await client.ReactivateUserAsync("bob-1", new ReactivateUserRequest
{
RestoreMessages = true,
Name = "Bob",
CreatedByID = "admin-user"
});
Key changes:
- Positional parameters become a
ReactivateUserRequestobject
Delete Users
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var userClient = clientFactory.GetUserClient();
// Single user delete
await userClient.DeleteAsync("bob-1", markMessagesDeleted: true, hardDelete: false);
// Batch delete
await userClient.DeleteManyAsync(new DeleteUsersRequest
{
UserIds = new[] { "bob-1", "jane" },
User = DeleteStrategy.SoftDelete,
Messages = DeleteStrategy.HardDelete
});
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
// Batch delete (all deletions use the batch endpoint)
await client.DeleteUsersAsync(new DeleteUsersRequest
{
UserIds = new List<string> { "bob-1", "jane" },
User = "soft", // "soft" or "hard"
Messages = "hard" // "soft" or "hard"
});
Key changes:
- Single and batch deletes both use
DeleteUsersAsync()with aDeleteUsersRequest - Delete strategies are plain strings (
"soft","hard") instead of enum values