> ## Documentation Index
> Fetch the complete documentation index at: https://docs.suprsend.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Users

> Manage user profiles and communication channels programmatically with the Java SDK.

## How Suprsend identifies a user

SuprSend identifies users with immutable `distinct_id`. It's best to map the same identifier in your DB with `distinct_id` in SuprSend. Do not use identifiers that can be changed like email or phone number. You can view synced users by searching `distinct_id` on [Users page](https://app.suprsend.com/en/production/users).

<Note>
  **Please note:** you cannot change a user's id once it has been set, so we recommend you use a non-transient id like a primary key rather than a phone number or email address.
</Note>

## Create User

To create a new user or to update an existing user, you'll have to fetch user instance. Call `supr_client.user.get_instance` to instantiate user object.

<CodeGroup>
  ```java Request theme={"system"}
  import org.json.JSONObject;
  import suprsend.Suprsend;
  import suprsend.Subscriber;

  public class UserEdit {
    public static void main(String[] args) throws Exception {
      getInstance();
    }

    private static Subscriber getSuprClient() throws SuprsendException {
      Suprsend suprsendClient = new Suprsend("_workspace_key_", "_workspace_secret_");
      return suprsendClient;
    }

    private static Subscriber getInstance() throws SuprsendException {
      Suprsend suprsendClient = getSuprClient();
      // Instiantiate user
      String distinctId = "_distinct_id_";

      Subscriber user = suprClient.user.getInstance(distinctId);
      return user;
    }
  }
  ```

  ```java Response theme={"system"}
  // Response structure
  {
      "success": true, // if true, request was accepted.
      "status": "success",
      "status_code": 202, // http status code
      "message": "OK",
  }

  {
      "success": false, // error will be present in message
      "status": "fail",
      "status_code": 500, // http status code
      "message": "error message",
  }
  ```
</CodeGroup>

## Edit User

To Edit user, you need to first fetch user instance, call all the update methods and save changes using `user.save` method.

<CodeGroup>
  ```java Request theme={"system"}
  import org.json.JSONObject;
  import suprsend.Suprsend;
  import suprsend.Subscriber;

  public class UserEdit {

    public static void updateProfile() throws Exception {
      Suprsend suprsendClient = getSuprClient();
      // User Edit Instance
      String distinctID = "_distinct_id_";
      Subscriber user = suprsendClient.user.getInstance(distinctID);

      // Edit Helper methods
      user.addEmail("example@example.com");
      user.setTimezone("America/New_York");

      // Save
      JSONObject response = user.save();
      System.out.println(response);
    }
  }
  ```
</CodeGroup>

Here's a list of all edit methods:

<AccordionGroup>
  <Accordion title="Add User Channels">
    Add communication channels on which you want to notify user. Push sand Inbox tokens are automatically tracked on user identification when the corresponding frontend SDK is integrated. Other channels (Email, SMS, Slack, MS teams, Whatsapp) need to be explicitly set in user profile.

    Use `user.add_*` method(s) to add user channels.

    <CodeGroup>
      ```java Request theme={"system"}
      // User Edit Instance
      String distinctID = "_distinct_id_";
      Subscriber user = suprsendClient.user.getInstance(distinctID);

      // Add Email
      user.addEmail("example@example.com");

      //Add SMS
      user.addSms("+919999999999");

      //Add Whatsapp
      user.addWhatsapp("+919999999999");

      // Add Androidpush token.Pass the vendor as 2nd param.
      user.addAndroidpush("androidpush_fcm_token__", "fcm");

      // Add iospush token
      user.addIospush("__iospush_apns_token__");

      // Add Slack using user email id
      JSONObject slackIdent = new JSONObject()
        .put("access_token", "xoxb-XXXXXXXX")
        .put("email", "user@example.com");
      user.addSlack(slackIdent);

      // Add Slack using member_id of the user if known
      JSONObject slackIdent = new JSONObject()
        .put("access_token", "xoxb-XXXXXXXX")
        .put("user_id", "U03XXXXXXXX");
      user.addSlack(slackIdent);

      // Add Slack channel_id
      JSONObject slackIdent = new JSONObject()
        .put("access_token", "xoxb-XXXXXXXX")
        .put("channel_id", "C04XXXXXXXX");
      user.addSlack(slackIdent);

      // Add Slack incoming webhook
      JSONObject slackIdent = new JSONObject()
        .put("incoming_webhook", new JSONObject().put("url", "https://hooks.slack.com/services/TXXXX/BXXXX/XXXXXXX"))
      user.addSlack(slackIdent);

      // Add Webpush token json (VAPID)
      JSONObject webpush = new JSONObject()
        .put("endpoint", "__end_point__")
        .put("expirationTime", "")
        .put("keys", new JSONObject()
          .put("p256dh", "__p256dh__")
          .put("auth", "__auth_key__"));
      user.addWebpush(webpush, "vapid");
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Remove User Channels">
    Use `user.remove_*` method(s) to remove channels.

    <CodeGroup>
      ```java Request theme={"system"}
      // Remove Email
      user.removeEmail("example@example.com");

      //Remove SMS
      user.removeSms("+919999999999");

      //Remove Whatsapp
      user.removeWhatsapp("+919999999999");

      // Remove Androidpush token.Pass the vendor as 2nd param.
      user.removeAndroidpush("androidpush_fcm_token__", "fcm");

      // Remove iospush token
      user.removeIospush("__iospush_apns_token__");

      // Remove Slack using user email id
      JSONObject slackIdent = new JSONObject()
        .put("access_token", "xoxb-XXXXXXXX")
        .put("email", "user@example.com");
      user.removeSlack(slackIdent);

      // Remove Slack using member_id of the user if known
      JSONObject slackIdent = new JSONObject()
        .put("access_token", "xoxb-XXXXXXXX")
        .put("user_id", "U03XXXXXXXX");
      user.removeSlack(slackIdent);

      // Remove Slack channel_id
      JSONObject slackIdent = new JSONObject()
        .put("access_token", "xoxb-XXXXXXXX")
        .put("channel_id", "C04XXXXXXXX");
      user.removeSlack(slackIdent);

      // Remove Slack incoming webhook
      JSONObject slackIdent = new JSONObject()
        .put("incoming_webhook", new JSONObject().put("url", "https://hooks.slack.com/services/TXXXX/BXXXX/XXXXXXX"))
      user.removeSlack(slackIdent);

      // Remove Webpush token json (VAPID)
      JSONObject webpush = new JSONObject()
        .put("endpoint", "__end_point__")
        .put("expirationTime", "")
        .put("keys", new JSONObject()
          .put("p256dh", "__p256dh__")
          .put("auth", "__auth_key__"));
      user.removeWebpush(webpush, "vapid");
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Remove Channel Types">
    This method will delete/unset all values in specified channel for user (ex: remove all emails attached to user).

    <CodeGroup>
      ```java Request theme={"system"}
      // --- To unset one channel, e.g. to delete all emails associated with user
      // -- Channel keys - ("$email","$whatsapp","$sms," $androidpush","$iospush","$webpush","$slack")
      user.unset("$email");

      // --- multiple channels can also be deleted in one call by passing argument as a list
      ArrayList < String > channels = new ArrayList < > (Arrays.asList("$email", "$slack", "$androidpush", "$iospush", "$webpush", "$whatsapp"));
      user.unset(channels);
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Set Preferred language">
    If you want to send notification in user's preferred language, you can set it by passing [language code](https://github.com/suprsend/suprsend-py-sdk/blob/v0.12.0/src/suprsend/language_codes.py) in this method. This is useful especially for the applications which offer vernacular or multi-lingual support.

    <CodeGroup>
      ```java Request theme={"system"}
      // User Edit Instance
      String distinctID = "_distinct_id_";
      Subscriber user = suprsendClient.user.getInstance(distinctID);

      // Pass language in ISO 639-1 code
      user.setPreferredLanguage("es");
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Set preferred timezone">
    You can set timezone of user using this method. Value for timezone must be from amongst the [IANA timezones](https://data.iana.org/time-zones/tzdb-2024a/zonenow.tab).

    <CodeGroup>
      ```java Request theme={"system"}
      // User Edit Instance
      String distinctID = "_distinct_id_";
      Subscriber user = suprsendClient.user.getInstance(distinctID);

      // Pass IANA timezone
      user.setTimezone("America/New_York");
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Set">
    Set is used to add custom user properties. It is an upsert function, meaning any existing property value with the same key will be overwritten on subsequent updates.

    <CodeGroup>
      ```java Request theme={"system"}
      user.set(key, value)
      user.set("name","John Doe")

      user.set({ key1: value1, key2: value2 })
      user.set({"name": "John Doe","city": "San Francisco"})
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Set Once">
    Works just like user.set, except it will not override already existing property values. This is useful for properties like first\_login\_date.

    ```java theme={"system"}
    user.set_once(key, value)
    user.set_once("first_login","2021-11-02")

    user.set_once({ key1: value1, key2: value2 })
    user.set_once({"first_login": "2021-11-02","signup_date": "2021-11-02"})
    ```
  </Accordion>

  <Accordion title="Unset">
    Unset is used to remove a property key.

    ```java theme={"system"}
    user.unset(key)
    user.unset("name")

    user.unset([key1, key2])
    user.unset(["name","city"])
    ```
  </Accordion>

  <Accordion title="Append">
    This method will append a value to the array list.

    ```java theme={"system"}
    user.append(key, value)
    user.append("played_games", "game_1")

    user.append({ key1: value1, key2: value2 })
    user.append({"played_games": "game_1", "liked_games": "game_2"})
    ```
  </Accordion>

  <Accordion title="Remove">
    This method will remove a value from the array list.

    ```java theme={"system"}
    user.remove(key, value)
    user.remove("played_games", "game_1")

    user.remove({ key1: value1, key2: value2 })
    user.remove({"played_games": "game_1", "liked_games": "game_2"})
    ```
  </Accordion>

  <Accordion title="Increment">
    Increase or decrease integer values on consecutive action, like login count. To reduce a property, provide a negative number for the value.

    ```java theme={"system"}
    user.increment(key, value)
    user.increment("login_count", 1)

    user.increment({ key1: value1, key2: value2 })
    user.increment({"login_count" : 1, "order_count" : 1})
    ```
  </Accordion>
</AccordionGroup>

<Warning>
  After calling `add_*/remove_*/unset` methods, don't forget to call `users.save()` since user edit is async update and the changes will be sent to SuprSend only after calling this method.
</Warning>

## Bulk Update Users

Bulk operations use **UPSERT** to create or update users.
There isn't any limit on number-of-records that can be added to `bulk_users` instance. Use `.append()` on bulk\_users instance to add however-many-records to call in bulk.

<Tip>
  **Rate limit:** 1000 requests per second. The SDK automatically chunks requests based on the size of the payload. So, you don't need to worry about these rate limits while using bulk operations.
</Tip>

<CodeGroup>
  ```java Request theme={"system"}
  //Creating bulk instance
  BulkSubscribers bulkIns = suprClient.bulkUsers.newInstance();

  // Prepare multiple users
  String distinctID1 = "__distinct_id1__"; // User 1
  User u1 = suprsendClient.user.getInstance(distinctID1);
  u1.addEmail("u1@example.com");

  String distinctID2 = "__distinct_id2__"; // User 2
  User u2 = suprsendClient.user.getInstance(distinctID2);
  u2.addEmail("u2@example.com");

  // --- use .append on bulk instance to add one or more records
  bulkIns.append(u1);
  bulkIns.append(u2);
  // OR
  bulkIns.append(u1, u2);

  // Save
  JSONObject response = bulkIns.save();
  System.out.println(response);
  ```

  ```java Response theme={"system"}
  // Response structure
  import suprsend.BulkResponse;

  BulkResponse{status: 'success' | total: 2 | success: 2 | failure: 0 | warnings: 0}

  BulkResponse{status: 'fail' | total: 2 | success: 0 | failure: 2 | warnings: 0}

  BulkResponse{status: 'partial' | total: 2 | success: 1 | failure: 1 | warnings: 0}
  ```
</CodeGroup>

<Warning>
  **Bulk API supported in SDK version 0.2.0 and above:**

  Bulk API is supported in SuprSend java-sdk version 0.2.0 and above. If you are using an older version, please upgrade to the latest SDK version.
</Warning>

## Get user details

Fetch User by passing `distinct_id`

<CodeGroup>
  ```java Request theme={"system"}
  String distinctId = "_distinct_id_";

  JSONObject res = suprClient.users.get(distinctId);
  System.out.println(response);
  ```

  ```java Response theme={"system"}
  {
    "distinct_id": "_distinct_id_",
    "properties": {
      "name": "John Doe",
      "email": ["johndoe@example.com"],
      "created_at": "2024-01-01T12:00:00Z"
    },
    "status": "active"
  }
  ```
</CodeGroup>

## Delete user

Delete User by passing `distinct_id`. Delete action will take into immediate effect.

<CodeGroup>
  ```java Request theme={"system"}
  String distinctId = "_distinct_id_";

  JSONObject res = suprClient.users.delete(distinctId);
  System.out.println(response);
  ```

  ```java Response theme={"system"}
   {
   "success": True,
   "status_code": 204
   }
  ```
</CodeGroup>

## Get list of objects subscribed by user

You can pass optional query parameters -`limit`,`before`,`after`

<CodeGroup>
  ```java Request theme={"system"}
  String distinctId = "_distinct_id_";

  // optional params to pass limit (default=10) and cursor pointer for fetching the next set of results
  HashMap < String, Object > opts = new HashMap < String, Object > () {
    {
      put("limit", 10);
      put("after", "01HFS04E4J29KHPYRK7HT3YQQ5");
    }
  };

  JSONObject res = suprClient.users.getObjectsSubscribedTo(distinctId, opts);
  System.out.println(response);
  ```

  ```java Response theme={"system"}
  {
      "objects": [
        {
          "object_id": "Frontend",
          "type": "Developers",
          "subscribed_at": "2024-02-20T10:15:30Z"
        }
      ],
      "paging": {
        "after": "01JJW6HXXXXPB59ARDW85G0KN",
        "has_more": false
      }
    }
  ```
</CodeGroup>

## Get lists subscribed by user

You can pass optional query parameters -`limit`, `before`, `after`

<CodeGroup>
  ```java Request theme={"system"}
  String distinctId = "_distinct_id_";

  // optional params to pass limit (default=10) and cursor pointer for fetching the next set of results
  HashMap < String, Object > opts = new HashMap < String, Object > () {
    {
      put("limit", 10);
      put("after", "01HFS04E4J29KHPYRK7HT3YQQ5");
    }
  };

  JSONObject res = suprClient.users.getListsSubscribedTo(distinctId, opts);
  System.out.println(response);
  ```

  ```java Response theme={"system"}
  {
    "lists": [
      {
        "list_id": "product_updates",
        "subscribed_at": "2024-02-20T12:00:00Z",
        "status": "subscribed"
      }
    ],
    "paging": {
      "after": "01JJW6HXXXXPB59ARDW85G0KN",
      "has_more": true
    }
  }
  ```
</CodeGroup>
