> ## 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 Go 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).

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

```go theme={"system"}
user := suprClient.Users.GetInstance("_distinct_id_") // Unique identifier of user in your application

// Save user
_, err = user.Save()
if err != nil {
  log.Fatalln(err)
}
```

## Edit User

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

<CodeGroup>
  ```go Request theme={"system"}
  func main() {
  	// Fetch user instance
  	user := suprClient.Users.GetEditInstance("_distinct_id_")

  	// Call user update methods
  	user.SetTimezone("America/Los_Angeles")
  	user.Set("name", "John Doe")

  	// Save Changes
  	res, err := user.Save()
  	if err != nil {
  		log.Fatalln(err)
  	}

  	fmt.Println(res)
  }
  ```

  ```go Response theme={"system"}
  {
    "success": boolean,
    "status": "success"/"fail",
    "status_code": http_status_code,
    "message": "response_message"/"error_message",
  }
  ```
</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>
      ```go Request theme={"system"}

      // Add email channel
      user.AddEmail("user@example.com")

      // add SMS channel
      user.AddSms("+1444455555")

      // Add WhatsApp channel
      user.AddWhatsapp("+1444455555")

      // Add androidpush token, token providers: fcm/xiaomi
      user.AddAndroidpush("__fcm_push_token__", "fcm")

      // Add iospush token, token providers: apns
      user.AddIospush("__ios_push_token__", "apns")

      // Add webpush token (vapid)
      user.AddWebpush(map[string]interface{}{
        "keys": map[string]interface{}{
          "auth":   "",
          "p256dh": "",
        },
        "endpoint": "",
      }, "vapid")

      ```
    </CodeGroup>
  </Accordion>

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

    <CodeGroup>
      ```go Request theme={"system"}

      // remove email channel
      user.RemoveEmail("user@example.com")

      // remove SMS channel
      user.RemoveSms("+1444455555")

      // remove WhatsApp channel
      user.RemoveWhatsapp("+1444455555")

      // remove androidpush token
      user.RemoveAndroidpush("__fcm_push_token__", "fcm")

      // remove iospush token
      user.RemoveIospush("__ios_push_token__", "apns")

      // remove webpush token
      user.RemoveWebpush(map[string]interface{}{
        "keys": map[string]interface{}{
          "auth":   "",
          "p256dh": "",
        },
        "endpoint": "",
      }, "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>
      ```go theme={"system"}

      // If you need to remove all emails for this user, call user.Unset(["$email"])
      user.Unset([]string{"$email"})

      // Supported channel keys are:
      // $email, $whatsapp, $sms, $androidpush, $iospush, $webpush, $slack, $ms_teams
      ```
    </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.

    ```go theme={"system"}

    // Set user preferred language. languageCode must be in [ISO 639-1 2-letter] format
    user.SetPreferredLanguage("en")
    ```
  </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).

    ```go theme={"system"}
    user.SetTimezone("America/Los_Angeles")
    ```
  </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.

    ```go theme={"system"}
    user.Set("key", "value")
    user.Set("name","John Doe")

    user.Set(map[string]interface{}{"prop1": "val1", "prop2": "val2"})
    user.Set(map[string]interface{}{"name": "John Doe","city": "San Francisco"})
    ```
  </Accordion>

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

    ```go theme={"system"}
    user.Unset([]string{"$email"})
    ```
  </Accordion>

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

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

    user.Append(map[string]interface{}{"key1": "val1", "key2": "val2"})
    user.Append(map[string]interface{}{"played_games": "game_1", "liked_games": "game_2"})
    ```
  </Accordion>

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

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

    user.Remove(map[string]interface{}{"key1": "val1", "key2": "val2"})
    user.Remove(map[string]interface{}{"played_games": "game_1", "liked_games": "game_2"})
    ```
  </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.

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

    user.SetOnce(map[string]interface{}{ key1: value1, key2: value2 })
    user.SetOnce(map[string]interface{}{"first_login": "2021-11-02","signup_date": "2021-11-02"})
    ```
  </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.

    ```go theme={"system"}
    user.Increment("login_count", 1)

    user.Increment(map[string]interface{}{"login_count" : 1, "order_count" : 1})
    ```
  </Accordion>
</AccordionGroup>

<Warning>
  After calling `Add/Remove/Unset` methods, don't forget to call `user.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>
  ```go Request theme={"system"}
  // create bulkUsers instance
  bulkIns := suprClient.BulkUsers.NewInstance()

  // Prepare user1
  user1 := suprClient.Users.GetInstance("__distinct_id1__")
  user1.AddEmail("user1@example.com")
  user1.AddWhatsapp("+1909090900")

  // prepare user 2
  user2 := suprClient.Users.GetInstance("__distinct_id2__")
  user2.AddEmail("user2@example.com")
  user2.AddWhatsapp("+2909090900")

  // Append all users to bulk instance
  bulkIns.Append(user1, user2)

  // Call save
  bulkResponse, err := bulkIns.Save()
  if err != nil {
    log.Fatalln(err)
  }
  log.Println(bulkResponse)
  ```

  ```go Response theme={"system"}
  {
    Status : "success",
    Total : 10, // number of records sent in bulk
    Success : 10, // number of records succeeded
    Failure : 0, // number of records failed
    FailedRecords : [],
  }


  {
    Status : "fail",
    Total : 10, // number of records sent in bulk
    Success : 0, // number of records succeeded
    Failure : 10, // number of records failed
    FailedRecords : [{"record": {...}, "error": "error_str", "code": 500}]
  }
  ```
</CodeGroup>

## Get user details

<CodeGroup>
  ```go Request theme={"system"}
  func main() {
  	// Fetch user instance
  	res, err := suprClient.Users.Get("_distinct_id_")
  	if err != nil {
  		log.Fatalln(err)
  	}

  	fmt.Println(res)
  }
  ```

  ```go 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

<CodeGroup>
  ```go Request theme={"system"}
  func main() {
  	// Delete user instance
  	res, err := suprClient.Users.Delete("_distinct_id_")
  	if err != nil {
  		log.Fatalln(err)
  	}

  	fmt.Println(res)
  }
  ```

  ```go 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>
  ```go Request theme={"system"}
  func main() {
  	// Get objects the user is subscribed to
  	params := map[string]interface{}{
  		"after": "01JJW6HXXXXPB59ARDW85G0KN",
  		"limit": 1,
  	}

  	res, err := suprClient.Users.GetObjectsSubscribedTo("_distinct_id_", params)
  	if err != nil {
  		log.Fatalln(err)
  	}

  	fmt.Println(res)
  }
  ```

  ```go 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>
  ```go Request theme={"system"}
  func main() {
  	// Get lists the user is subscribed to
  	params := map[string]interface{}{
  		"after": "01JJW6HXXXXPB59ARDW85G0KN",
  		"limit": 1,
  	}

  	res, err := suprClient.Users.GetListsSubscribedTo("_distinct_id_", params)
  	if err != nil {
  		log.Fatalln(err)
  	}

  	fmt.Println(res)
  }
  ```

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