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

# Visitors

> Endpoints to manage visitor profiles and memory

Endpoints to manage visitor profiles and their persistent memory (key-value facts stored across conversations).

## GET /tenants/{slug}/visitors

List all visitor profiles for a tenant.

**Required scope:** `visitors:read`

### Request

```bash theme={null}
curl https://api.animam.ai/tenants/my-company/visitors \
  -H "Authorization: Bearer ak_your_token"
```

### Query Parameters

| Param    | Type   | Description                                 |
| -------- | ------ | ------------------------------------------- |
| `limit`  | number | Results per page (default: 50, max: 200)    |
| `offset` | number | Pagination offset (default: 0)              |
| `search` | string | Search by email, displayName, or externalId |

### Response

```json theme={null}
{
  "visitors": [
    {
      "id": "vis_abc123",
      "email": "alice@example.com",
      "displayName": "Alice Martin",
      "phone": null,
      "authProvider": "email",
      "externalId": "user_42",
      "metadata": { "plan": "pro" },
      "createdAt": "2024-01-15T10:30:00Z",
      "updatedAt": "2024-01-20T14:00:00Z"
    }
  ],
  "total": 312,
  "limit": 50,
  "offset": 0
}
```

## POST /tenants/{slug}/visitors

Create a new visitor profile.

**Required scope:** `visitors:write`

### Request

```bash theme={null}
curl -X POST https://api.animam.ai/tenants/my-company/visitors \
  -H "Authorization: Bearer ak_your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alice@example.com",
    "displayName": "Alice Martin",
    "externalId": "user_42",
    "metadata": { "plan": "pro" }
  }'
```

### Body

| Field          | Type   | Required    | Description                                       |
| -------------- | ------ | ----------- | ------------------------------------------------- |
| `email`        | string | Conditional | Visitor email address                             |
| `displayName`  | string | No          | Display name                                      |
| `phone`        | string | No          | Phone number                                      |
| `authProvider` | string | No          | Auth provider identifier (e.g. `email`, `google`) |
| `externalId`   | string | Conditional | Your internal user ID                             |
| `metadata`     | object | No          | Arbitrary JSON metadata attached to the visitor   |

<Note>
  At least one of `email` or `externalId` is required to create a visitor profile.
</Note>

### Response

```json theme={null}
{
  "id": "vis_xyz789",
  "email": "alice@example.com",
  "displayName": "Alice Martin",
  "phone": null,
  "authProvider": null,
  "externalId": "user_42",
  "metadata": { "plan": "pro" },
  "createdAt": "2024-01-25T10:30:00Z",
  "updatedAt": "2024-01-25T10:30:00Z"
}
```

## GET /tenants/{slug}/visitors/{visitorId}

Retrieve a specific visitor with their conversation count and memory fact count.

**Required scope:** `visitors:read`

```bash theme={null}
curl https://api.animam.ai/tenants/my-company/visitors/vis_abc123 \
  -H "Authorization: Bearer ak_your_token"
```

### Response

```json theme={null}
{
  "id": "vis_abc123",
  "email": "alice@example.com",
  "displayName": "Alice Martin",
  "phone": null,
  "authProvider": "email",
  "externalId": "user_42",
  "metadata": { "plan": "pro" },
  "conversationCount": 7,
  "memoryCount": 3,
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-20T14:00:00Z"
}
```

## PATCH /tenants/{slug}/visitors/{visitorId}

Update a visitor profile. Only provided fields are modified.

**Required scope:** `visitors:write`

```bash theme={null}
curl -X PATCH https://api.animam.ai/tenants/my-company/visitors/vis_abc123 \
  -H "Authorization: Bearer ak_your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "displayName": "Alice M.",
    "metadata": { "plan": "agency" }
  }'
```

## DELETE /tenants/{slug}/visitors/{visitorId}

Delete a visitor and all associated data (conversations, memory facts).

**Required scope:** `visitors:write`

```bash theme={null}
curl -X DELETE https://api.animam.ai/tenants/my-company/visitors/vis_abc123 \
  -H "Authorization: Bearer ak_your_token"
```

### Response

```json theme={null}
{
  "deleted": true,
  "id": "vis_abc123"
}
```

<Warning>
  Deletion is permanent and cascades to all conversations and memory facts associated with this visitor.
</Warning>

***

## Memory

Each visitor can store persistent key-value facts collected during conversations via the `REMEMBER_FACT` tool. Memory facts are injected into future conversations to give the agent context about returning visitors.

### GET /tenants/{slug}/visitors/{visitorId}/memory

List all memory facts for a visitor.

**Required scope:** `visitors:read`

```bash theme={null}
curl https://api.animam.ai/tenants/my-company/visitors/vis_abc123/memory \
  -H "Authorization: Bearer ak_your_token"
```

### Response

```json theme={null}
[
  { "key": "preferred_language", "value": "French", "updatedAt": "2024-01-20T14:00:00Z" },
  { "key": "budget",             "value": "5000",   "updatedAt": "2024-01-18T09:15:00Z" },
  { "key": "industry",           "value": "retail",  "updatedAt": "2024-01-15T11:30:00Z" }
]
```

### POST /tenants/{slug}/visitors/{visitorId}/memory

Create or update a memory fact (upsert by key).

**Required scope:** `visitors:write`

```bash theme={null}
curl -X POST https://api.animam.ai/tenants/my-company/visitors/vis_abc123/memory \
  -H "Authorization: Bearer ak_your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "preferred_language",
    "value": "French"
  }'
```

### Body

| Field   | Type   | Required | Description                               |
| ------- | ------ | -------- | ----------------------------------------- |
| `key`   | string | Yes      | Fact identifier (snake\_case recommended) |
| `value` | string | Yes      | Fact value (stored as string)             |

### Response

```json theme={null}
{
  "key": "preferred_language",
  "value": "French",
  "updatedAt": "2024-01-25T10:30:00Z"
}
```

### GET /tenants/{slug}/visitors/{visitorId}/memory/{key}

Retrieve a specific memory fact.

**Required scope:** `visitors:read`

```bash theme={null}
curl https://api.animam.ai/tenants/my-company/visitors/vis_abc123/memory/preferred_language \
  -H "Authorization: Bearer ak_your_token"
```

### Response

```json theme={null}
{
  "key": "preferred_language",
  "value": "French",
  "updatedAt": "2024-01-20T14:00:00Z"
}
```

### DELETE /tenants/{slug}/visitors/{visitorId}/memory/{key}

Delete a specific memory fact.

**Required scope:** `visitors:write`

```bash theme={null}
curl -X DELETE https://api.animam.ai/tenants/my-company/visitors/vis_abc123/memory/preferred_language \
  -H "Authorization: Bearer ak_your_token"
```

### Response

```json theme={null}
{
  "deleted": true,
  "key": "preferred_language"
}
```

***

## Visitor Resolution

When a visitor sends a message to the chat endpoint, Animam resolves their profile using the following lookup order:

1. **`X-Visitor-Id` header** — pass the visitor ID explicitly from your backend.
2. **`visitorId` body field** — include in the JSON body of the chat request.
3. **Session cookie / anonymous** — if no identifier is provided, the visitor is treated as anonymous for that session.

Once resolved, the visitor's memory facts are automatically injected into the agent's system prompt, giving the agent context about returning visitors without any additional configuration.

The `REMEMBER_FACT` tool works alongside this system: when the agent decides to remember something, it calls the tool during the conversation, and the fact is persisted immediately and available from the next message onwards.

***

## Visitor Authentication

Animam supports multiple authentication modes for visitors, configured per-tenant via the `visitorAuthMode` field. This controls how the agent verifies visitor identity before granting access to sensitive actions.

| Mode      | `visitorAuthMode` value | Description                                                                                                                 |
| --------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| None      | `null`                  | No authentication required (anonymous visitors allowed)                                                                     |
| JWT       | `"jwt"`                 | Visitor presents a signed JWT; the agent validates the signature using the tenant's public key                              |
| OTP email | `"otp"`                 | Agent sends a one-time code to the visitor's email via `SEND_VERIFICATION_CODE`, then verifies it via `VERIFY_VISITOR_CODE` |
| Both      | `"all"`                 | Agent accepts either JWT or OTP                                                                                             |

### Context webhook (HMAC)

For use cases where identity is established by your own backend, you can configure a context webhook. Your server signs a payload with a shared HMAC secret; the agent verifies it via the `VERIFY_EXTERNAL_CHALLENGE` synthetic tool. This enables delegated 2FA flows where Animam acts as the conversation layer but your backend remains the authority on identity.

<Note>
  Visitor auth mode and webhook configuration are set on the tenant object. See the [Tenant endpoints](/api-reference/endpoints/tenant) for configuration details.
</Note>
