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

# Users, identifiers and attributes

> Who a decision is made for: your user_id, the identifiers, attributes and context buckets, anonymous users, and how identify links them.

Decisions are made for a **user**, identified by the `user_id` you send. The id is yours: a database id, a session id, an anonymous visitor id. Curious stores what you tell it about the user and nothing it infers.

## One id across decide and events

Rewards attribute to decisions by user: an event reported for `user_123` credits the decision made for `user_123`. Use the same id on `decide` and `events`, and when a person's id changes, say so with [`identify`](https://docs.trycurious.ai/guides/identify).

## The three buckets

Three explicit objects may travel with a decision. You pick the bucket; nothing is routed by key name.

| Bucket | What belongs in it | Stored on the user? | Used for personalization? |
| - | - | - | - |
| `identifiers` | Durable identity: `email`, `first_name`, `phone`. | Yes, merged on every call. | No. Usable in content through [variables](https://docs.trycurious.ai/concepts/variables.md), never a model feature. |
| `attributes` | Durable state: `plan`, `company_size`, `country`. | Yes, merged on every call. | Yes. |
| `context` | Situational facts about this one decision: `device`, `page`, `locale`. | No. | Yes, for this decision only. |

```json theme={null}
{
  "user_id": "user_123",
  "identifiers": { "email": "alice@example.com", "first_name": "Alice" },
  "attributes": { "plan": "pro", "company_size": 150 },
  "context": { "device": "mobile", "page": "/pricing" }
}
```

Personalization reads the union of the stored `attributes` and the call's `context`. On a key present in both, the context value wins for this decision: the fresh fact beats the stored one. Event `properties` are facts about the event and are never written to the user.

## Anonymous and known users

A visitor who has not logged in gets an anonymous id from you (the browser SDK mints `anon_<uuid>` in a first-party cookie). Decisions and events accrue under it. When the person logs in or signs up, your server calls `identify` with `anonymous_id` and `user_id`, and from then on decisions and events on either id attribute to the same person: a purchase under `user_123` credits a decision made under `anon_456`. Many anonymous ids may link into one known user; a retry of the same link is a no-op; a link that contradicts an existing one is a `409`. Identify needs a secret key, because the browser never holds the authority to merge identities. See [Identify users](https://docs.trycurious.ai/guides/identify.md).

## Environments keep users apart

A test key's `user_123` and a live key's `user_123` are different users. Test traffic can never read or change live user state, and test decisions never affect live ones. See [Keys and environments](https://docs.trycurious.ai/guides/keys.md).


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