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

# User Class

> Manage users and their sessions, memories, and messages

## Overview

The `User` class represents a user in your RecallrAI project. It provides methods for managing sessions, memories, messages, and merge conflicts.

## Properties

<ResponseField name="userId" type="string">
  Unique identifier for the user.
</ResponseField>

<ResponseField name="metadata" type="object">
  User metadata as an object.
</ResponseField>

<ResponseField name="mergeConflictEnabled" type="boolean | undefined">
  Per-user merge conflict override. `true` = always raise merge conflicts for this user. `false` = never raise. `undefined` = inherit the project-level setting.
</ResponseField>

<ResponseField name="createdAt" type="datetime">
  UTC timestamp when the user was created.
</ResponseField>

<ResponseField name="lastActiveAt" type="datetime">
  UTC timestamp of the user's last activity.
</ResponseField>

## User Management Methods

### update()

```typescript theme={null}
import { UserAlreadyExistsError } from "recallrai";

try {
  const user = await client.getUser("user123");
  await user.update({
    newMetadata: { name: "John Doe", role: "admin" },
    newUserId: "john_doe",
    mergeConflictEnabled: true, // optional: override merge conflict behaviour
  });
  console.log(`Updated user ID: ${user.userId}`);
} catch (error) {
  if (error instanceof UserAlreadyExistsError) {
    console.log(`New user ID already exists: ${error.message}`);
  }
}
```

<ParamField path="newMetadata" type="object">
  New metadata to replace the existing metadata.
</ParamField>

<ParamField path="newUserId" type="string">
  Optional new user ID. Must be unique within your project.
</ParamField>

<ParamField path="mergeConflictEnabled" type="boolean">
  Per-user merge conflict override. `true` = always raise merge conflicts for this user. `false` = never raise. Set `undefined` to reset to the project-level default (omit the field from the call).
</ParamField>

**Returns:** `void`

**Raises:** `UserNotFoundError`, `UserAlreadyExistsError`

***

### refresh()

```typescript theme={null}
const user = await client.getUser("john_doe");
await user.refresh();
console.log(`Latest metadata:`, user.metadata);
```

**Returns:** `void`

**Raises:** `UserNotFoundError`

***

### delete()

```typescript theme={null}
const user = await client.getUser("john_doe");
await user.delete();
```

<Warning>
  This permanently deletes the user and all associated sessions, memories, and messages.
</Warning>

**Returns:** `void`

**Raises:** `UserNotFoundError`

## Session Management Methods

### createSession()

```typescript theme={null}
const user = await client.getUser("user123");
const session = await user.createSession({
  autoProcessAfterSeconds: 600,
  metadata: { type: "chat", channel: "web" },
});

console.log(`Created session: ${session.sessionId}`);
```

<ParamField path="autoProcessAfterSeconds" type="number">
  Seconds of inactivity before auto-processing. Default: `600`.
</ParamField>

<ParamField path="metadata" type="object">
  Optional metadata for the session.
</ParamField>

### getSession()

```typescript theme={null}
import { SessionNotFoundError } from "recallrai";

try {
  const user = await client.getUser("user123");
  const session = await user.getSession("session-uuid");
  console.log(`Session status: ${session.status}`);
} catch (error) {
  if (error instanceof SessionNotFoundError) {
    console.log(`Error: ${error.message}`);
  }
}
```

<ParamField path="sessionId" type="string" required>
  The UUID of the session to retrieve.
</ParamField>

<ParamField path="options.validate" type="boolean" default="true">
  Whether to validate session existence via API before creating the instance. Set `false` only when `userId` and `sessionId` are already trusted.
</ParamField>

**Returns:** `Session`

**Raises:** `UserNotFoundError`, `SessionNotFoundError`

<Tip>
  Set `{ validate: false }` to skip the SDK lookup request (`GET /api/v1/users/{userId}/sessions/{sessionId}`) when IDs are already trusted.
</Tip>

<Note>
  When `{ validate: false }` is used, fields that require an API lookup (for example `status`, `createdAt`, and `metadata`) are set to `UNAVAILABLE` until you call `refresh()`.
  Import `UNAVAILABLE` from `recallrai` when checking these values.
</Note>

## Memory Management Methods

### listMemories()

List user memories with optional filtering.

```typescript theme={null}
import { UserNotFoundError, InvalidCategoriesError } from "recallrai";

try {
  const user = await client.getUser("user123");
  const memories = await user.listMemories({
    categories: ["food_preferences", "allergies"],
    sessionIdFilter: ["session-uuid-1", "session-uuid-2"],
    sessionMetadataFilter: { environment: "production" },
    offset: 0,
    limit: 20,
    includePreviousVersions: true,
    includeConnectedMemories: true,
  });

  for (const mem of memories.items) {
    console.log(`Memory: ${mem.content}`);
    console.log(`Categories: ${mem.categories}`);
    console.log(`Version: ${mem.versionNumber} of ${mem.totalVersions}`);
    console.log(`Event occurred: ${mem.eventDateStart} to ${mem.eventDateEnd}`);
    console.log(`Recorded at: ${mem.createdAt}`);
  }
} catch (error) {
  if (error instanceof InvalidCategoriesError) {
    console.log(`Invalid categories: ${error.invalidCategories}`);
  }
}
```

<ParamField path="categories" type="string[]">
  Filter by memory categories. Only memories matching these categories are returned.
</ParamField>

<ParamField path="sessionIdFilter" type="string[]">
  Filter by specific session IDs.
</ParamField>

<ParamField path="sessionMetadataFilter" type="object">
  Filter by session metadata.
</ParamField>

<ParamField path="offset" type="number">
  Number of memories to skip. Default: `0`
</ParamField>

<ParamField path="limit" type="number">
  Maximum number of memories to return. Range: 1-200. Default: `20`
</ParamField>

<ParamField path="includePreviousVersions" type="boolean">
  Include version history for each memory. Default: `true`
</ParamField>

<ParamField path="includeConnectedMemories" type="boolean">
  Include related memories. Default: `true`
</ParamField>

**Returns:** `UserMemoriesList` object

**Raises:** `UserNotFoundError`, `InvalidCategoriesError`

***

### getMemory()

Retrieve a single memory by its ID.

```typescript theme={null}
import { RecallrAIError } from "recallrai";

try {
  const user = await client.getUser("user123");
  const memory = await user.getMemory("memory-uuid", {
    includePreviousVersions: true,
    includeConnectedMemories: true,
  });
  console.log(`Content: ${memory.content}`);
  console.log(`Categories: ${memory.categories}`);
  console.log(`Version: ${memory.versionNumber} of ${memory.totalVersions}`);
} catch (error) {
  if (error instanceof RecallrAIError) {
    console.log(`Error: ${error.message}`);
  }
}
```

<ParamField path="memoryId" type="string" required>
  UUID of the memory to retrieve.
</ParamField>

<ParamField path="includePreviousVersions" type="boolean">
  Include version history for the memory. Default: `true`
</ParamField>

<ParamField path="includeConnectedMemories" type="boolean">
  Include related memories. Default: `true`
</ParamField>

**Returns:** `UserMemoryItem`

**Raises:** `RecallrAIError`

***

### deleteMemory()

Delete a specific memory version, with an option to also remove all previous versions in the chain.

```typescript theme={null}
import { RecallrAIError } from "recallrai";

try {
  const user = await client.getUser("user123");

  // Delete only the specified memory version
  await user.deleteMemory("memory-uuid");

  // Delete the specified version and all previous versions
  await user.deleteMemory("memory-uuid", true);
} catch (error) {
  if (error instanceof RecallrAIError) {
    console.log(`Error: ${error.message}`);
  }
}
```

<ParamField path="memoryId" type="string" required>
  UUID of the memory to delete. Can be any version in the version chain.
</ParamField>

<ParamField path="deletePreviousVersions" type="boolean">
  If `true`, deletes the specified version and all previous versions in the chain. If `false` (default), deletes only the specified version.
</ParamField>

<Warning>
  Deletion is permanent and cannot be undone. When `deletePreviousVersions` is `true`, the entire version history up to and including the specified version is removed.
</Warning>

**Returns:** `void`

**Raises:** `RecallrAIError`

### UserMemoryItem Fields

Each memory item contains:

* `memoryId`: Unique identifier for the current version
* `categories`: Array of category strings
* `content`: Current version's content text
* `eventDateStart`: UTC `Date` when the event started (actual event time, not when it was recorded)
* `eventDateEnd`: UTC `Date` when the event ended (actual event time, not when it was recorded)
* `createdAt`: UTC `Date` when this memory version was created (when it was recorded in the system)
* `expiredAt`: UTC `Date` when this version expired — only set when viewing an expired/previous version
* `expirationReason`: Why this version was superseded (`MERGE_CONFLICT`, `ADDITION_TO_EXISTING_MEMORY`, `TEMPORAL_CONFLICT`) — only set for expired versions
* `sessionId`: ID of the session that created this version
* `versionNumber`: Current version number
* `totalVersions`: Total number of versions
* `hasPreviousVersions`: Boolean indicating multiple versions exist
* `previousVersions`: Array of `MemoryVersionInfo` objects (optional)
* `connectedMemories`: Array of `MemoryRelationship` objects (optional)
* `mergeConflictInProgress`: Boolean indicating an active (unresolved) conflict on this memory
* `mergeConflictId`: ID of the merge conflict that caused this memory to expire — only set when `expirationReason` is `MERGE_CONFLICT` and a conflict record exists (manually resolved conflicts only)

Each `MemoryVersionInfo` object in `previousVersions` contains:

* `memoryId`: ID of that specific version (can be passed to `getMemory()` for full details)
* `versionNumber`: Version number (1 = oldest)
* `content`: Content of that version
* `eventDateStart` / `eventDateEnd`: Event timestamps for that version
* `createdAt`: When that version was created
* `expiredAt`: When that version expired
* `expirationReason`: Why it was superseded
* `mergeConflictId`: Conflict that caused expiration, if applicable

<Info>
  The difference between `eventDateStart`/`eventDateEnd` and `createdAt`:

  * **Event dates** represent when the event actually occurred in the real world (e.g., "I met John on Monday")
  * **Created at** represents when the memory was extracted and stored in the system

  This distinction allows for better temporal reasoning when extracting memories from past conversations.
</Info>
