# User management

<admonition type="info">

The operations performed on users, such as updating and deleting, have an effect on all products (chat, feeds and video).

</admonition>

## 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 to `user` but you can specify any existing role.
- Custom data can be added to users in the `custom` field.
- `name` and `image` are optional and handled by all SDKs automatically to render users.

<codetabs>

<codetabs-item value="nodejs" label="Node">

```js
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]);
```

</codetabs-item>

<codetabs-item value="go-golang" label="Go">

```go
package main

import (
    "context"
    "log"

    "github.com/GetStream/getstream-go/v3"
)

func main() {
    client, err := getstream.NewClient("<your_api_key>", "<your_api_secret>")
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Create/upsert a new user
    response, err := client.UpsertUsers(ctx, &getstream.UpsertUsersRequest{
        Users: []getstream.UserRequest{
            {
                ID:   "user-id",
                Role: getstream.PtrTo("user"),
                Custom: map[string]interface{}{
                    "color": "red",
                },
                Name:  getstream.PtrTo("This is a test user"),
                Image: getstream.PtrTo("link/to/profile/image"),
            },
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("User created successfully: %+v", response.Data.Users)
}
```

</codetabs-item>

</codetabs>

## 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

<codetabs>

<codetabs-item value="nodejs" label="Node">

```js
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'],
    },
  ],
});
```

</codetabs-item>

<codetabs-item value="go-golang" label="Go">

```go
package main

import (
    "context"
    "log"

    "github.com/GetStream/getstream-go/v3"
)

func main() {
    client, err := getstream.NewClient("<your_api_key>", "<your_api_secret>")
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Replace update: replace the entire user object
    response, err := client.UpsertUsers(ctx, &getstream.UpsertUsersRequest{
        Users: []getstream.UserRequest{
            {
                ID:   "userid",
                Role: getstream.PtrTo("user"),
                Custom: map[string]interface{}{
                    "color": "blue",
                },
                Name:  getstream.PtrTo("This is a test user"),
                Image: getstream.PtrTo("link/to/profile/image"),
            },
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("User updated successfully: %+v", response.Data.Users)

    // Partial update: choose which fields to change
    partialResponse, err := client.UpdateUsersPartial(ctx, &getstream.UpdateUsersPartialRequest{
        Users: []getstream.UpdateUserPartialRequest{
            {
                ID: "userid",
                Set: map[string]interface{}{
                    "new-field": "value",
                },
                Unset: []string{"name"},
            },
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("User partially updated: %+v", partialResponse.Data.Users)
}
```

</codetabs-item>

</codetabs>

## 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

<codetabs>

<codetabs-item value="nodejs" label="Node">

```js
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>'...],
});
```

</codetabs-item>

<codetabs-item value="go-golang" label="Go">

```go
package main

import (
    "context"
    "log"

    "github.com/GetStream/getstream-go/v3"
)

func main() {
    client, err := getstream.NewClient("<your_api_key>", "<your_api_secret>")
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Deactivate a single user
    deactivateResponse, err := client.DeactivateUser(ctx, &getstream.DeactivateUserRequest{
        UserID: "<id>",
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("User deactivated: %+v", deactivateResponse)

    // Reactivate users
    reactivateResponse, err := client.ReactivateUsers(ctx, &getstream.ReactivateUsersRequest{
        UserIds: []string{"<id>"},
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Users reactivated: %+v", reactivateResponse)

    // Deactivating users in bulk (asynchronous)
    bulkDeactivateResponse, err := client.DeactivateUsers(ctx, &getstream.DeactivateUsersRequest{
        UserIds: []string{"<id1>", "<id2>"},
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Bulk deactivation task ID: %s", bulkDeactivateResponse.Data.TaskID)
}
```

</codetabs-item>

</codetabs>

Deactivating users in bulk can take some time, this is how you can check the progress:

<codetabs>

<codetabs-item value="nodejs" label="Node">

```js
// 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");
```

</codetabs-item>

<codetabs-item value="go-golang" label="Go">

```go
package main

import (
    "context"
    "log"
    "time"

    "github.com/GetStream/getstream-go/v3"
)

func main() {
    client, err := getstream.NewClient("<your_api_key>", "<your_api_secret>")
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Example of monitoring the status of an async task
    // The logic is same for all async tasks
    response, err := client.ExportUsers(ctx, &getstream.ExportUsersRequest{
        UserIds: []string{"<user id1>", "<user id2>"},
    })
    if err != nil {
        log.Fatal(err)
    }

    // Poll the task status
    for {
        taskResponse, err := client.GetTask(ctx, &getstream.GetTaskRequest{
            ID: response.Data.TaskID,
        })
        if err != nil {
            log.Fatal(err)
        }

        log.Printf("Task status: %s", taskResponse.Data.Status)

        if taskResponse.Data.Status == "completed" {
            log.Println("Task completed successfully!")
            break
        } else if taskResponse.Data.Status == "failed" {
            log.Println("Task failed!")
            break
        }

        // Wait before polling again
        time.Sleep(2 * time.Second)
    }
}
```

</codetabs-item>

</codetabs>

### Deleting users

<codetabs>

<codetabs-item value="nodejs" label="Node">

```js
client.deleteUsers({ user_ids: ["<id>"] });

//restore
client.restoreUsers({ user_ids: ["<id>"] });
```

</codetabs-item>

<codetabs-item value="go-golang" label="Go">

```go
package main

import (
    "context"
    "log"

    "github.com/GetStream/getstream-go/v3"
)

func main() {
    client, err := getstream.NewClient("<your_api_key>", "<your_api_secret>")
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Delete users (soft delete by default)
    deleteResponse, err := client.DeleteUsers(ctx, &getstream.DeleteUsersRequest{
        UserIds: []string{"<id>"},
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Users deleted: %+v", deleteResponse)

    // Delete users with specific options
    deleteWithOptionsResponse, err := client.DeleteUsers(ctx, &getstream.DeleteUsersRequest{
        UserIds: []string{"<id>"},
        User:    getstream.PtrTo("hard"), // soft, pruning, or hard
        Messages: getstream.PtrTo("pruning"), // soft, pruning, or hard
        Conversations: getstream.PtrTo("soft"), // soft or hard
        NewChannelOwnerID: getstream.PtrTo("new-owner-id"),
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Users deleted with options: %+v", deleteWithOptionsResponse)

    // Restore users
    restoreResponse, err := client.RestoreUsers(ctx, &getstream.RestoreUsersRequest{
        UserIds: []string{"<id>"},
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Users restored: %+v", restoreResponse)
}
```

</codetabs-item>

</codetabs>

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. <br /> - Pruning: marks user as deleted and nullifies user information. <br /> - 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). <br /> - 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. <br /> - Pruning: marks all user messages as deleted, nullifies message information and removes some message data such as reactions and flags. <br /> - 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. <br /> - Hard: deletes calls and related data completely <br /> 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:

<codetabs>

<codetabs-item value="nodejs" label="Node">

```js
// 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");
```

</codetabs-item>

</codetabs>

---

This page was last updated at 2025-08-15T14:14:09.465Z.

For the most recent version of this documentation, visit [https://getstream.io/activity-feeds/docs/react-native/user-management/](https://getstream.io/activity-feeds/docs/react-native/user-management/).