---
title: "Conversations and end users"
description: "Keep a conversation through an API key with conversation_id, name the people who use your product with end_user, keep nothing with store false, and know how long Lookio keeps it."
canonical: "https://lookio.app/docs/guides/conversations-and-end-users"
updated: "2026-11-08"
---

# Conversations and end users

Lookio keeps every answer from an API key, the CLI or the MCP server in a conversation. Send the next question with the `conversation_id` of the previous answer. Lookio reads the history itself.

This page is for products that show an assistant to their own users. A person's chats in the app are personal. See [Chat](/docs/guides/chat).

## Continue a conversation

```mermaid title="Lookio keeps the history, you send only the new question"
sequenceDiagram
  participant P as Your product
  participant L as Lookio
  P->>L: question, end_user=user_42
  L-->>P: answer, conversation_id, message_id
  P->>L: next question, conversation_id
  Note right of L: Reads the last six messages itself
  L-->>P: answer that knows the first question
```

The first answer returns two ids. `conversation_id` continues the conversation. `message_id` identifies the answer. You need it to [send a thumb](/docs/guides/answer-feedback).

```bash title="curl"
# First question
curl https://api.lookio.app/v1/assistants/ASSISTANT_ID/query \
  -H "Authorization: Bearer $LOOKIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"question": "How much does the Pro plan cost?", "end_user": "user_42"}'

# The answer has "conversation_id": "CONVERSATION_ID" and "message_id": "MESSAGE_ID".
# Follow-up: only the new question.
curl https://api.lookio.app/v1/assistants/ASSISTANT_ID/query \
  -H "Authorization: Bearer $LOOKIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"question": "And for the annual plan?", "conversation_id": "CONVERSATION_ID", "end_user": "user_42"}'
```

```ts title="SDK"
const first = await lookio.assistants.ask("ASSISTANT_ID", {
  question: "How much does the Pro plan cost?",
  end_user: "user_42",
});
const followUp = await lookio.assistants.ask("ASSISTANT_ID", {
  question: "And for the annual plan?",
  conversationId: first.conversation_id!,
  end_user: "user_42",
});
```

```bash title="CLI"
lookio ask ASSISTANT_ID "How much does the Pro plan cost?" --end-user user_42
lookio ask ASSISTANT_ID "And for the annual plan?" --conversation CONVERSATION_ID --end-user user_42
```

The MCP tool `ask_assistant` takes the same `conversation_id`, `end_user` and `store`. The streamed answer returns both ids in its `done` event: see [Streaming](/docs/developers/streaming).

A conversation:

- belongs to the API key that started it. Another key gets `resource_not_found`, also in the same workspace.
- stays with one assistant. Another assistant with that `conversation_id` gets `resource_not_found`.
- uses the last six messages as context (three questions and their answers), like a chat in the app.

## Two ways to keep a conversation

|                         | `conversation_id` (Lookio keeps it)                          | `history` (you keep it)                                                                     |
| ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| **You send**            | The new question and the id.                                 | The new question and the previous messages, oldest first. Up to 20. Lookio uses the last 6. |
| **Memory**              | What Lookio stored.                                          | What you send. Lookio does not check it.                                                    |
| **Stored by Lookio**    | Yes, for your plan's period ([below](#how-long-it-is-kept)). | Yes, as a new conversation, unless you also send `store: false`.                            |
| **Visible in the logs** | Yes.                                                         | Yes, unless `store: false`.                                                                 |
| **Use it when**         | You want the simplest follow-up.                             | You already store the conversation, or you want nothing kept at Lookio.                     |

Sending both `conversation_id` and `history` fails with `invalid_request`.

## Name the people who use your product with end\_user

`end_user` is your own id for the person who asks, such as a user id of your product. It is optional.

- It is 1 to 200 characters: letters, digits and `. _ @ : + -`. Anything else fails with `invalid_parameter`.
- **Use an opaque id** such as `user_42`, not an email address. The id appears in the [logs](/docs/guides/logs).
- It groups that person's conversations. List them with `GET /v1/conversations?end_user=user_42`.
- **It locks the conversation to that person.** To continue, read, rename, delete or rate a conversation started with `end_user: "user_42"`, a call must send the same `end_user`. Other calls get `resource_not_found`. So one of your users cannot open the conversation of another, even if an id leaks.
- A conversation started without `end_user` is reachable only by calls without `end_user`. Use one method for your whole product.

`end_user` and `store` are for API keys only. A person's connection that sends them gets `invalid_parameter`.

## Keep nothing with store false

Send `store: false` when Lookio must keep nothing. There is no conversation and no entry in the logs. `conversation_id` and `message_id` are `null`. The price is the same. For a follow-up, send the previous messages yourself in `history`.

You cannot send `store: false` with `conversation_id`.

## How long it is kept

The plan sets how long a conversation stays readable, counted from its last message. A new message restarts the count.

| Plan    | Readable | Deleted after |
| ------- | -------- | ------------- |
| Free    | 7 days   | 60 days       |
| Starter | 90 days  | 180 days      |
| Pro     | 1 year   | 455 days      |

Between the two, the conversation is locked. It stays in the lists with its channel, assistant, cost and dates, but its messages are hidden. A plan with a longer period makes it readable again. A member's own chats in the app are never locked.

To delete a conversation earlier, call `DELETE /v1/conversations/{conversation_id}`. It also leaves the logs and their figures. To erase a user's data on request, list their conversations with `end_user` and delete each one.

Who can read a kept conversation:

- you, with the API key that started it (the endpoints below);
- the people of the workspace who may [read the logs](/docs/guides/logs).

Members' own chats are never in the logs.

## Read and tidy your key's conversations

| What                                      | Endpoint                                                                     | CLI                                    | SDK                      |
| ----------------------------------------- | ---------------------------------------------------------------------------- | -------------------------------------- | ------------------------ |
| List, optionally of one `end_user`        | [List conversations](/docs/api/conversations/list-conversations)             | `lookio conversations list --end-user` | `conversations.list`     |
| Read one with its messages and answer ids | [Get a conversation](/docs/api/conversations/get-conversation)               | `lookio conversations get`             | `conversations.get`      |
| Rename                                    | [Rename a conversation](/docs/api/conversations/rename-conversation)         | `lookio conversations rename`          | `conversations.rename`   |
| Delete                                    | [Delete a conversation](/docs/api/conversations/delete-conversation)         | `lookio conversations delete`          | `conversations.delete`   |
| Forward a thumb                           | [Send feedback on an answer](/docs/api/conversations/submit-answer-feedback) | `lookio conversations feedback`        | `conversations.feedback` |

Each row has an MCP tool with the same job. See [Standard tools](/docs/developers/mcp/standard-tools#conversations). Each conversation has a `channel`: `api` for a key through REST, the CLI or the SDK, `mcp` for a key through the MCP server, `personal` for a person's own chat. A key lists only its own conversations.

## Errors you may meet

| Error                                     | Meaning                                                                                                      |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `resource_not_found` on `conversation_id` | The conversation does not exist, was deleted or expired, or belongs to another key, assistant or `end_user`. |
| `invalid_request`                         | `conversation_id` with `history`, or `conversation_id` with `store: false`.                                  |
| `invalid_parameter` on `end_user`         | Not 1 to 200 characters of letters, digits and `. _ @ : + -`, or sent by a person's connection.              |
| `invalid_parameter` on `store`            | `store` sent by a person's connection. A person's chats are always kept.                                     |
