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

# Visitors, users, and sessions

> Keep one visitor continuous while separating different conversations.

Era uses three different IDs:

| ID                 | Meaning                               | Required?   |
| ------------------ | ------------------------------------- | ----------- |
| `visitorId`        | The current browser or mobile visitor | Yes         |
| `partnerEndUserId` | Your ID for a signed-in user          | No          |
| `sessionId`        | One conversation or chat thread       | Recommended |

## Visitor ID

Create the visitor ID with the [Web SDK](/web-sdk/quickstart) or
[Flutter SDK](/flutter-sdk/quickstart). Send it to your backend with each chat
request.

```typescript theme={null}
const eraContext = await era.turnContext(messages, {
  visitorId,
  sessionId,
});
```

If no `visitorId` is available, `turnContext()` returns `""` without making an
Era request.

## Signed-in user ID

When your backend knows the signed-in user, add your own stable ID:

```typescript theme={null}
const eraContext = await era.turnContext(messages, {
  visitorId,
  partnerEndUserId: authenticatedUser.id,
  sessionId,
});
```

This connects the visitor to the account. `partnerEndUserId` does not replace
`visitorId`.

You can also include a verified `email` or `phone`. These values must come from
trusted backend data:

```typescript theme={null}
const eraContext = await era.turnContext(messages, {
  visitorId,
  partnerEndUserId: authenticatedUser.id,
  email: authenticatedUser.verifiedEmail,
  sessionId,
});
```

Never trust an email or phone value copied directly from client input.

## Session ID

Use the same `sessionId` for every turn in one conversation. Create a new one
when the user starts a new conversation.

If you omit it, the SDK derives a value from the first user message. Two
conversations that start with the same text can therefore get the same derived
value. Pass your application's conversation ID in production.

## Constructor defaults

You can set IDs on the client when one client belongs to one visitor:

```typescript theme={null}
const era = new Era({
  apiKey,
  baseUrl,
  partnerId,
  visitorId,
  sessionId,
});
```

For a shared server client, pass visitor, user, and session values to each
`turnContext()` call.

## Repeated calls

The Node SDK memoizes the latest lookup by visitor, signed-in identity,
session, and turn number. Repeated calls for the same latest turn can share one
request. Changing any of those values starts a separate lookup.
