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

# Identities

> Manage user profiles and attributes.

Identities allow you to attach permanent traits to a `user_id`. When you send events with that `user_id`, SeerStack automatically associates the event with these traits.

## Identifying Users

Call `users.identify` when a user signs up or updates their profile. You only need to send the fields that have changed.

> [tab] TypeScript
>
> ```typescript theme={null}
> import Seerstack from 'seerstack';
>
> const client = new Seerstack({
>   apiKey: process.env['SEERSTACK_API_KEY'],
> });
>
> await client.users.identify({
>   user_id: 'user_123', // Your internal ID
>   email: 'grace@hopper.com',
>   name: 'Grace Hopper',
>   attributes: {
>     plan: 'enterprise',
>     team_size: 15,
>     is_admin: true
>   }
> });
> ```

> [tab] Ruby
>
> ```ruby theme={null}
> require "seerstack"
>
> seerstack = Seerstack::Client.new(
>   api_key: ENV["SEERSTACK_API_KEY"]
> )
>
> seerstack.users.identify(
>   user_id: "user_123", # Your internal ID
>   email: "grace@hopper.com",
>   name: "Grace Hopper",
>   attributes: {
>     plan: "enterprise",
>     team_size: 15,
>     is_admin: true
>   }
> )
> ```

> [tab] cURL
>
> ```bash theme={null}
> curl -X POST https://api.seerstack.com/identify \
>   -H "Authorization: Bearer $SEERSTACK_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "user_id": "user_123",
>     "email": "grace@hopper.com",
>     "name": "Grace Hopper",
>     "attributes": {
>       "plan": "enterprise",
>       "team_size": 15,
>       "is_admin": true
>     }
>   }'
> ```

## Identity Fields

| Field | Type | Required | Description |
| :- | :- | :- | :- |
| `user_id` | string | **Yes** | Your internal user ID (database primary key). |
| `email` | string | No\* | The user's email address. |
| `name` | string | No\* | The user's display name. |
| `attributes` | object | No | Custom attributes for filtering and segmentation. |

> [!NOTE]
>
> Either `email` or `name` must be provided when identifying a user.

## Automatic Enrichment

Once a user is identified, you can use their attributes in your dashboard filters.

> [!NOTE]
>
> If you filter by `attributes.plan = 'enterprise'`, SeerStack will find all events triggered by users with that plan, even if the event payload itself didn't contain the plan name.

## Updating User Attributes

You can call `identify` multiple times. Each call merges new attributes with existing ones.

> [tab] TypeScript
>
> ```typescript theme={null}
> // Initial identification
> await client.users.identify({
>   user_id: 'user_123',
>   email: 'grace@hopper.com',
>   attributes: { plan: 'free' }
> });
>
> // Later, when user upgrades
> await client.users.identify({
>   user_id: 'user_123',
>   attributes: { plan: 'enterprise', upgraded_at: new Date().toISOString() }
> });
> ```

> [tab] Ruby
>
> ```ruby theme={null}
> # Initial identification
> seerstack.users.identify(
>   user_id: "user_123",
>   email: "grace@hopper.com",
>   attributes: { plan: "free" }
> )
>
> # Later, when user upgrades
> seerstack.users.identify(
>   user_id: "user_123",
>   attributes: { plan: "enterprise", upgraded_at: Time.now.iso8601 }
> )
> ```

## Best Practices

> [card] Use Stable IDs
>
> Use your database's primary key (e.g., UUID) as the `user_id`, not an email address or username which might change.

> [card] Identify Early
>
> Call `identify` as soon as your user logs in to ensure subsequent events are correctly attributed.

> [card] Keep Attributes Clean
>
> Use consistent naming for attributes across your codebase. Prefer `snake_case` for attribute keys.

> [card] Don't Over-Identify
>
> You don't need to call `identify` on every request. Once is enough until attributes change.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.