# Identify users

> How Camelus recognizes the person behind each message: verified ids from your server or a signed widget identity, emails, claims, merges and deletion.

Camelus ranks themes by **people**, not messages: someone who writes five times counts once. To do that, it needs to know who sent each message. This page explains how people are recognized, and how to make sure your signed-in users are.

## How Camelus recognizes a person

Each message can carry a user id, an email and a name. Camelus matches them to a person in this order:

1. A **verified user id**: sent by your server with an API key, or by the widget with a valid signature.
2. An **email address**.
3. An **unverified user id**: a claim from a browser that Camelus can't check.

Without an id or an email, the message is anonymous: it counts as its own requester. An unverified claim never attaches feedback to a person someone else verified, so nobody can borrow a paying customer's weight by typing their id.

How a person is known also changes how much they weigh when themes are ranked: unknown 0.8, claimed 1.0, verified 1.2, and more for paying customers when [Polar](/docs/polar) is connected.

## From your server (REST API)

Requests with an API key come from your server, so the user id is trusted as is:

```bash
curl https://api.camelus.si/v1/feedback \
  -H "Authorization: Bearer ck_live_…" -H "Content-Type: application/json" \
  -d '{"product": "habits", "text": "Export to CSV please", "person": {"id": "u_123", "email": "ana@example.com", "name": "Ana"}}'
```

Use the same id your app uses for that user, every time. See the [REST API reference](/docs/api).

## From the widget

The widget runs in the browser, where anyone can call `identify` from the console. So Camelus only trusts an identity that comes with a signature from your server:

1. In the product's widget settings, create an **identity secret**. It's shown once: store it on your server.
2. On your server, sign the user id with it (HMAC-SHA256, hex):

```js
// Node.js
import crypto from "node:crypto";
const hash = crypto.createHmac("sha256", process.env.CAMELUS_IDENTITY_SECRET).update(user.id).digest("hex");
```

```python
# Python
import hmac, hashlib, os
hash = hmac.new(os.environ["CAMELUS_IDENTITY_SECRET"].encode(), user_id.encode(), hashlib.sha256).hexdigest()
```

```php
// PHP
$hash = hash_hmac('sha256', $user->id, getenv('CAMELUS_IDENTITY_SECRET'));
```

3. Pass it to the page and call:

```js
camelus('identify', { id: 'u_123', email: 'ana@example.com', name: 'Ana', hash: 'HASH_FROM_YOUR_SERVER' });
```

With a valid hash, the person is verified. Without one (or with a wrong one), the id is kept as an unverified claim. Never put the secret itself in the page.

## Email and forwarded emails

Emails sent to a product's forwarding address are linked to the sender's address. For a forwarded support email, Camelus uses the original sender, not you. See [Email forwarding](/docs/email).

## Duplicates and merges

The same person can show up twice, for example with a personal and a work email. In **People**, open one and **Merge** the other into it: their feedback, counts and themes combine, and future messages from either address find the merged person.

## Deleting a person

On a person's page, **Delete** removes their personal data, either keeping anonymized summaries for the counts or removing their feedback entirely. Use it when someone asks you to delete their data.
