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

# Era client

> Create the Node SDK client and request context for each user turn.

## Create a client

```typescript theme={null}
import { Era } from "@seasonlabs/era-node";

const era = new Era({
  apiKey: process.env.ERA_API_KEY!,
  baseUrl: process.env.ERA_URL!,
  partnerId: process.env.ERA_PARTNER_ID!,
});
```

The API key is secret. Create this client only on a trusted backend.

See [all constructor options](/sdk/types#eraoptions).

## `turnContext(messages, options?)`

Returns the context block for a conversation.

```typescript theme={null}
async turnContext(
  messages: EraMessage[],
  options?: TurnContextOptions,
): Promise<string>
```

### Arguments

<ParamField path="messages" type="EraMessage[]" required>
  Conversation history through the latest user message.
</ParamField>

<ParamField path="options.visitorId" type="string">
  Visitor ID from the Web or Flutter SDK. It can also be set on the client.
</ParamField>

<ParamField path="options.partnerEndUserId" type="string">
  Your stable ID for a signed-in user.
</ParamField>

<ParamField path="options.email" type="string">
  A backend-verified email address. Requires `partnerEndUserId`.
</ParamField>

<ParamField path="options.phone" type="string">
  A backend-verified phone number. Requires `partnerEndUserId`.
</ParamField>

<ParamField path="options.sessionId" type="string">
  Your stable ID for this conversation.
</ParamField>

`visitorId` must be available on the call or client. `partnerEndUserId` is
optional and does not replace it.

### Result

The promise resolves to a plain string. Add it to your system prompt:

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

if (eraContext) {
  systemPrompt += `\n\n${eraContext}`;
}
```

It resolves to `""` without making a request when:

* No `visitorId` is available.
* The normalized conversation is empty.
* The last normalized message is not from the user.

Expected network, timeout, and API failures also resolve to `""`. See
[Fail-open design](/concepts/fail-open).

## HTTP request

```text theme={null}
POST {baseUrl}/v1/era/turn
X-API-Key: {apiKey}
Content-Type: application/json
```

The SDK normalizes `messages` into user and assistant turns, adds identity and
session values, and sends the request for you.

## Repeated calls

The latest result is memoized by identity, session, and turn number. Repeated
calls for the same latest turn can share one HTTP request.
