# Export chat history for a period via API

This guide is for integrators who need to pull conversations from ConnectiveOne into their own system: a data warehouse, BI or quality analytics. It shows how to use existing API requests to get all chats for a period and the text of every message with its date and author.

## When you need this

- You need to pull conversations for a day, week or month into an external system on a schedule.
- Analysts need to label messages as "client" or "operator".
- You need a one-off sample of dialogs for a period to review quality.

## What you should know

- After authorization, the export takes **two requests**: first a list of chats for the period, then a file with the messages of each chat.
- The messages of one chat come back as a **file**: CSV (default) or XLSX. JSON is not supported for this request.
- Requests run on behalf of the user whose email and password you used. That user needs access to the `Operator panel` module. We recommend a separate technical user for the integration.
- The period in step 2 filters chats by the chat's **creation date**. Messages inside a chat can be later.
- A very wide period in step 2 can end with a `504 QUERY_TIMEOUT` error. If it does, narrow the period and fetch the data in parts.

## Before you start

- [x] You have the email and password of a user with access to the operator panel.
- [x] You know your instance address, for example `https://engine-<instance>.connectiveone.io`.
- [x] You can send HTTP requests (curl, Postman or your integration code).

## Step-by-step

### Step 1. Get an access token

```bash
curl -X POST "https://engine-<instance>.connectiveone.io/api/v1/auth/token" -H "Content-Type: application/json" -d '{"email":"integration@example.com","password":"<password>","expires_in":3600}'
```

The response contains a token. Add it to every following request in the `Authorization: Bearer <token>` header.

- `expires_in` is the token lifetime in seconds. The maximum is set by the instance configuration; if the value is too large, the request returns `400` with the allowed range.
- The token cannot be refreshed. When it expires, request a new one with the same call.

More about authorization: [How to use the API](/en/integrations/how-to/use-api.md).

### Step 2. Get the list of chats for the period

```bash
curl -G "https://engine-<instance>.connectiveone.io/kw/api/v1/OpChatRooms/list" -H "Authorization: Bearer <token>" --data-urlencode "filter[createdAt][gt]=2026-11-01T00:00:00.000Z" --data-urlencode "filter[createdAt][lt]=2026-11-08T00:00:00.000Z" --data-urlencode "order[createdAt]=asc" --data-urlencode "limit=100" --data-urlencode "offset=0"
```

| Parameter | What it sets |
| :--- | :--- |
| `filter[createdAt][gt]` | Start of the period (ISO 8601) |
| `filter[createdAt][lt]` | End of the period (ISO 8601) |
| `limit` | How many chats to return per request (default 10) |
| `offset` | How many chats to skip, to move to the next page |
| `order[createdAt]` | Sorting: `asc` or `desc` |

The response contains a `rows` array and the total `count`. From each row you need the `id` field: the chat id. Increase `offset` by `limit` until you have gone through all `count` chats.

### Step 3. Export the messages of each chat

For each `id` from step 2:

```bash
curl -G "https://engine-<instance>.connectiveone.io/kw/operator_panel/chat_room/messages/download" -H "Authorization: Bearer <token>" --data-urlencode "chat_room_id=12345" --data-urlencode "format=csv" -o chat-12345.csv
```

- `format` is `csv` (default) or `xlsx`.
- The file has one row per message. To order messages by time, sort by `send_datetime`.

## What the file contains

Each chat file has these columns:

| Column | What it holds |
| :--- | :--- |
| `id` | Message id |
| `send_datetime` | Message date and time as `YYYY-MM-DD HH:MM:SS` |
| `message_text` | Message text |
| `message_data` | Service data of the message: attachments, buttons and so on |
| `system` | `1` means a platform system message (for example, an operator joined) |
| `message_read` | Whether the message was read |
| `participant.client.full_name`, `participant.client.email`, `participant.client.phone` | Filled when the **client** wrote the message |
| `participant.user.first_name`, `participant.user.last_name` | Filled when an **operator** wrote the message |

The file has no chat id column: take it from the file name or from step 2 and add it to the rows in your system.

To label the author of a message:

- `participant.client.*` columns are filled: a client message;
- `participant.user.*` columns are filled: an operator message;
- `system` = `1`: a system message.

## How to verify it worked

- The number of processed chats equals `count` from step 2.
- For one or two chats, compare the file with the conversation in the operator panel: the message texts match.
- Compare `send_datetime` of one message with the time shown in the operator panel to know which time zone the dates come in.

## FAQ

**The request returns `422` with `token data error`. What is wrong?**
The user the token was issued for has no access to the operator panel. Give them a role with that access.

**Can I get the messages for the whole period in one request?**
No: messages are exported per chat, as in step 3.

**Can I export a conversation without the API?**
Yes, for a single dialog: the chat menu in the operator panel has a **Download** item (CSV) and [PDF export](/en/operatorline/how-to/export-chatroom-to-pdf.md).

## Related materials

- [How to use the API](/en/integrations/how-to/use-api.md)
- [API reference](/en/integrations/reference/api-reference.md)
- [Export a chat to PDF](/en/operatorline/how-to/export-chatroom-to-pdf.md)
