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

# Conversations

> Read, manage, and clean up conversations and messages across every channel — chat, voice, text, email, and forms

Conversations capture every back-and-forth your agents have with people — chat sessions on your site, phone calls, SMS threads, inbound emails, and form submissions. Each conversation belongs to an agent (`bot_id`) and may be linked to a [Contact](/api-reference/contacts) and/or an anonymous [Visitor](/features/traffic/visitors).

You can read transcripts, update inbox state (assignment, archive, takeover, internal notes), and soft-delete conversations from the API. Creating conversations is **not** supported — they originate from real channel events (the chat widget, voice/SMS webhooks, inbound email, form submissions) so that routing, billing, and analytics stay accurate.

<Tip>
  Looking for the full transcript of a single conversation? Fetch the conversation, then call [List messages](#list-messages-in-a-conversation) with `order=asc`.
</Tip>

## The Conversation object

<ResponseField name="id" type="string">
  Unique conversation identifier.
</ResponseField>

<ResponseField name="bot_id" type="string">
  The agent this conversation belongs to.
</ResponseField>

<ResponseField name="contact_id" type="string | null">
  The CRM contact linked to this conversation, if one has been resolved.
</ResponseField>

<ResponseField name="type" type="integer">
  Channel the conversation happened on. See [Conversation types](#conversation-types) below.
</ResponseField>

<ResponseField name="email" type="string | null">
  Best-known email for the participant (may be `null` for anonymous chats).
</ResponseField>

<ResponseField name="phone_number" type="string | null">
  E.164 phone number for the participant on voice / text conversations.
</ResponseField>

<ResponseField name="human" type="string | null">
  Display name of the human, when known.
</ResponseField>

<ResponseField name="human_takeover" type="boolean">
  `true` when a human teammate has taken over the conversation from the agent.
</ResponseField>

<ResponseField name="assigned_to" type="string | null">
  User ID of the teammate the conversation is assigned to.
</ResponseField>

<ResponseField name="assigned_at" type="string | null">
  ISO 8601 timestamp of the most recent assignment.
</ResponseField>

<ResponseField name="active" type="boolean">
  `true` while the conversation is in progress; flips to `false` after a period of inactivity.
</ResponseField>

<ResponseField name="archived" type="boolean | null" />

<ResponseField name="archived_at" type="string | null" />

<ResponseField name="deleted" type="boolean | null">
  Soft-delete flag. Deleted conversations are excluded from list responses unless you pass `include_deleted=true`.
</ResponseField>

<ResponseField name="deleted_at" type="string | null" />

<ResponseField name="internal" type="boolean">
  `true` for conversations between teammates (e.g. asking your internal agent), `false` for customer-facing conversations.
</ResponseField>

<ResponseField name="internal_notes" type="string | null">
  Free-text notes added by your team. Never shared with the participant.
</ResponseField>

<ResponseField name="last_message" type="string | null">
  Snippet of the most recent message — useful for inbox-style list views.
</ResponseField>

<ResponseField name="last_message_at" type="string | null">
  ISO 8601 timestamp of the most recent message.
</ResponseField>

<ResponseField name="last_active_at" type="string | null">
  ISO 8601 timestamp of the participant's most recent activity (typing, page change, etc.).
</ResponseField>

<ResponseField name="sentiment_positive" type="boolean | null">
  `true` if Clarky's sentiment analysis judged the conversation as net-positive, `false` if negative, `null` if not yet analyzed.
</ResponseField>

<ResponseField name="sentiment_score" type="number | null">
  Sentiment score in the range `[-1, 1]`.
</ResponseField>

<ResponseField name="sentiment_summary" type="string | null">
  One-sentence summary of the participant's mood and intent.
</ResponseField>

<ResponseField name="audio_url" type="string | null">
  Storage path for the call recording on voice conversations. Use the dashboard or a workspace-authenticated session to download.
</ResponseField>

<ResponseField name="minutes" type="number | null">
  Duration of voice / phone calls, in minutes.
</ResponseField>

<ResponseField name="visitor_id" type="string | null">
  Linked anonymous [Visitor](/features/traffic/visitors), when the conversation came from an unauthenticated chat.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 timestamp.
</ResponseField>

### Conversation types

The `type` field is a numeric ID. The list endpoint also accepts the names below as a convenience.

| `type` | Name                         | Channel                         |
| ------ | ---------------------------- | ------------------------------- |
| `1`    | `chat`                       | Web chat widget                 |
| `2`    | `phone` (or `voice`, `call`) | Inbound or outbound voice calls |
| `3`    | `text` (or `sms`)            | SMS / text-message threads      |
| `4`    | `email`                      | Inbound email threads           |
| `5`    | `form`                       | Form submissions                |

## The Message object

<ResponseField name="id" type="string" />

<ResponseField name="conversation_id" type="string" />

<ResponseField name="role" type="string">
  Who sent the message. Common roles: `user` (participant), `assistant` (the agent), `system`, `tool`, `human` (a human teammate during takeover).
</ResponseField>

<ResponseField name="content" type="string">
  The text payload of the message. May be empty for tool-only messages.
</ResponseField>

<ResponseField name="content_type" type="string | null">
  MIME hint for the content (e.g. `text/plain`, `text/markdown`).
</ResponseField>

<ResponseField name="status" type="string | null">
  Delivery status, when available — e.g. `sent`, `delivered`, `failed`.
</ResponseField>

<ResponseField name="tool_used" type="string | null">
  Name of the tool the assistant called, when this message represents a tool invocation.
</ResponseField>

<ResponseField name="tool_arguments" type="object | null">
  JSON arguments passed to the tool.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 timestamp.
</ResponseField>

***

## List conversations

<ParamField path="method" type="GET">
  `GET /api/v1/conversations`
</ParamField>

Returns a paginated list of conversations across all agents in your workspace. Sorted by `created_at` descending by default.

### Query parameters

| Param                 | Type              | Description                                                                      |
| --------------------- | ----------------- | -------------------------------------------------------------------------------- |
| `bot_id`              | string            | Filter to a single agent                                                         |
| `contact_id`          | string            | Filter to conversations linked to a specific contact                             |
| `visitor_id`          | string            | Filter to conversations linked to a specific anonymous visitor                   |
| `assigned_to`         | string            | Filter by the user ID of the assigned teammate                                   |
| `type`                | string \| integer | Filter by channel — `chat`, `phone`, `text`, `email`, `form`, or numeric `1`–`5` |
| `active`              | boolean           | `true` for in-progress conversations, `false` for inactive                       |
| `archived`            | boolean           | Filter on the archived flag (omit to include both)                               |
| `human_takeover`      | boolean           | `true` for conversations currently being handled by a human                      |
| `include_deleted`     | boolean           | Pass `true` to include soft-deleted conversations                                |
| `created_after`       | string (ISO 8601) | Created at or after this timestamp                                               |
| `created_before`      | string (ISO 8601) | Created at or before this timestamp                                              |
| `last_message_after`  | string (ISO 8601) | Most-recent message at or after this timestamp                                   |
| `last_message_before` | string (ISO 8601) | Most-recent message at or before this timestamp                                  |
| `search`              | string            | Substring match against the latest message snippet, email, phone, or human name  |
| `sort`                | string            | `created_at` (default) or `last_message_at`                                      |
| `order`               | string            | `desc` (default) or `asc`                                                        |
| `page`                | integer           | See [Pagination](/api-reference/pagination)                                      |
| `page_size`           | integer           | See [Pagination](/api-reference/pagination)                                      |

### Example

```bash theme={null}
curl "https://clarky.ai/api/v1/conversations?type=chat&active=true&page_size=10" \
  -H "Authorization: Bearer ck_live_example"
```

```json theme={null}
{
  "data": [
    {
      "id": "conv_01HXYZ...",
      "bot_id": "b_01HDEF...",
      "contact_id": "c_01HABC...",
      "type": 1,
      "email": "ada@example.com",
      "phone_number": null,
      "human": "Ada Lovelace",
      "human_takeover": false,
      "assigned_to": null,
      "assigned_at": null,
      "active": true,
      "archived": false,
      "archived_at": null,
      "deleted": false,
      "deleted_at": null,
      "internal": false,
      "internal_notes": null,
      "last_message": "Sounds good, talk soon!",
      "last_message_at": "2026-04-30T14:21:00.000Z",
      "last_active_at": "2026-04-30T14:21:30.000Z",
      "sentiment_positive": true,
      "sentiment_score": 0.74,
      "sentiment_summary": "Customer is excited about the upcoming demo.",
      "audio_url": null,
      "minutes": null,
      "visitor_id": "v_01HVIS...",
      "created_at": "2026-04-30T14:00:00.000Z"
    }
  ],
  "pagination": { "page": 1, "page_size": 10, "total": 1, "total_pages": 1 }
}
```

***

## Get a conversation

<ParamField path="method" type="GET">
  `GET /api/v1/conversations/{id}`
</ParamField>

Fetches a single conversation by ID. Returns `404 not_found` if the conversation does not exist or belongs to another workspace.

### Example

```bash theme={null}
curl https://clarky.ai/api/v1/conversations/conv_01HXYZ \
  -H "Authorization: Bearer ck_live_example"
```

```json theme={null}
{
  "data": {
    "id": "conv_01HXYZ...",
    "bot_id": "b_01HDEF...",
    "contact_id": "c_01HABC...",
    "type": 1,
    "human": "Ada Lovelace",
    "human_takeover": false,
    "active": true,
    "last_message": "Sounds good, talk soon!",
    "last_message_at": "2026-04-30T14:21:00.000Z",
    "sentiment_positive": true,
    "sentiment_score": 0.74,
    "created_at": "2026-04-30T14:00:00.000Z"
  }
}
```

***

## Update a conversation

<ParamField path="method" type="PATCH">
  `PATCH /api/v1/conversations/{id}`
</ParamField>

Requires a key with the `write` scope. Updates the listed fields and leaves everything else untouched. Use this to manage inbox state — assigning conversations to teammates, archiving, taking over from the agent, or adding private notes.

### Body fields

| Field            | Type           | Description                                                                        |
| ---------------- | -------------- | ---------------------------------------------------------------------------------- |
| `internal_notes` | string \| null | Private notes for your team. Never shared with the participant.                    |
| `assigned_to`    | string \| null | User ID of the teammate who should own this conversation. Pass `null` to unassign. |
| `archived`       | boolean        | `true` to archive, `false` to unarchive.                                           |
| `human_takeover` | boolean        | `true` to mute the agent and let a human reply.                                    |
| `active`         | boolean        | Mark the conversation in-progress (`true`) or closed (`false`).                    |

<Note>
  Setting `assigned_to` automatically updates `assigned_at`. Setting `archived` automatically updates `archived_at`. You don't need to send those fields yourself.
</Note>

### Example: assign a conversation

```bash theme={null}
curl -X PATCH https://clarky.ai/api/v1/conversations/conv_01HXYZ \
  -H "Authorization: Bearer ck_live_example" \
  -H "Content-Type: application/json" \
  -d '{
    "assigned_to": "u_01HUSER",
    "internal_notes": "Hot lead — follow up by EOD."
  }'
```

```json theme={null}
{
  "data": {
    "id": "conv_01HXYZ...",
    "bot_id": "b_01HDEF...",
    "contact_id": "c_01HABC...",
    "assigned_to": "u_01HUSER...",
    "assigned_at": "2026-04-30T19:10:00.000Z",
    "internal_notes": "Hot lead — follow up by EOD.",
    "archived": false,
    "active": true,
    "created_at": "2026-04-30T14:00:00.000Z"
  }
}
```

### Example: archive

```bash theme={null}
curl -X PATCH https://clarky.ai/api/v1/conversations/conv_01HXYZ \
  -H "Authorization: Bearer ck_live_example" \
  -H "Content-Type: application/json" \
  -d '{ "archived": true }'
```

### Example: take over from the agent

```bash theme={null}
curl -X PATCH https://clarky.ai/api/v1/conversations/conv_01HXYZ \
  -H "Authorization: Bearer ck_live_example" \
  -H "Content-Type: application/json" \
  -d '{ "human_takeover": true }'
```

<Tip>
  Updating `human_takeover` only flips the flag — sending the actual reply still happens through the agent's channel (chat widget, SMS, etc.). Use takeover to silence the agent while a human responds in the dashboard.
</Tip>

***

## Delete a conversation

<ParamField path="method" type="DELETE">
  `DELETE /api/v1/conversations/{id}`
</ParamField>

Requires a key with the `write` scope. Returns `204 No Content` with an empty body on success.

This is a **soft delete** — the conversation is hidden from list responses (and from the dashboard inbox) but transcripts, recordings, and analytics are preserved. Pass `include_deleted=true` on [List conversations](#list-conversations) to surface deleted records, and `PATCH` with `deleted: false` is **not** supported via the API; restoration is dashboard-only.

### Example

```bash theme={null}
curl -X DELETE https://clarky.ai/api/v1/conversations/conv_01HXYZ \
  -H "Authorization: Bearer ck_live_example"
```

<Warning>
  Deleting a conversation removes it from your inbox and all dashboard views. The underlying transcript is retained for compliance and analytics, but cannot be re-surfaced through the public API.
</Warning>

***

## List messages in a conversation

<ParamField path="method" type="GET">
  `GET /api/v1/conversations/{id}/messages`
</ParamField>

Returns the messages in a single conversation, paginated. Defaults to **chronological order** (`order=asc`) — the natural read order for a transcript.

### Query parameters

| Param            | Type              | Description                                                                       |
| ---------------- | ----------------- | --------------------------------------------------------------------------------- |
| `role`           | string            | Filter to messages from a single role — e.g. `user`, `assistant`, `human`, `tool` |
| `created_after`  | string (ISO 8601) | Created at or after this timestamp                                                |
| `created_before` | string (ISO 8601) | Created at or before this timestamp                                               |
| `order`          | string            | `asc` (default) or `desc`                                                         |
| `page`           | integer           | See [Pagination](/api-reference/pagination)                                       |
| `page_size`      | integer           | See [Pagination](/api-reference/pagination)                                       |

### Example

```bash theme={null}
curl "https://clarky.ai/api/v1/conversations/conv_01HXYZ/messages?page_size=50" \
  -H "Authorization: Bearer ck_live_example"
```

```json theme={null}
{
  "data": [
    {
      "id": "msg_01HMSG1...",
      "conversation_id": "conv_01HXYZ...",
      "role": "user",
      "content": "Hi! Do you support importing from HubSpot?",
      "content_type": "text/plain",
      "status": null,
      "tool_used": null,
      "tool_arguments": null,
      "created_at": "2026-04-30T14:00:05.000Z"
    },
    {
      "id": "msg_01HMSG2...",
      "conversation_id": "conv_01HXYZ...",
      "role": "assistant",
      "content": "Yes — we have a one-click HubSpot importer. Want me to walk you through it?",
      "content_type": "text/markdown",
      "status": "delivered",
      "tool_used": null,
      "tool_arguments": null,
      "created_at": "2026-04-30T14:00:08.000Z"
    }
  ],
  "pagination": { "page": 1, "page_size": 50, "total": 2, "total_pages": 1 }
}
```

<Tip>
  For long transcripts, page through with `page_size=100` (the maximum) to minimize round-trips. The total message count is in `pagination.total`.
</Tip>

***

## List a contact's conversations

<ParamField path="method" type="GET">
  `GET /api/v1/contacts/{contact_id}/conversations`
</ParamField>

Convenience endpoint that returns every conversation linked to a single contact, across all agents and channels.

### Query parameters

| Param             | Type    | Description                                       |
| ----------------- | ------- | ------------------------------------------------- |
| `include_deleted` | boolean | Pass `true` to include soft-deleted conversations |
| `page`            | integer | See [Pagination](/api-reference/pagination)       |
| `page_size`       | integer | See [Pagination](/api-reference/pagination)       |

### Example

```bash theme={null}
curl https://clarky.ai/api/v1/contacts/c_01HABC/conversations \
  -H "Authorization: Bearer ck_live_example"
```

```json theme={null}
{
  "data": [
    {
      "id": "conv_01HXYZ...",
      "bot_id": "b_01HDEF...",
      "contact_id": "c_01HABC...",
      "type": 1,
      "last_message": "Sounds good, talk soon!",
      "last_message_at": "2026-04-30T14:21:00.000Z",
      "created_at": "2026-04-30T14:00:00.000Z"
    },
    {
      "id": "conv_01HOLD...",
      "bot_id": "b_01HDEF...",
      "contact_id": "c_01HABC...",
      "type": 2,
      "minutes": 12,
      "last_message_at": "2026-04-15T10:05:00.000Z",
      "created_at": "2026-04-15T09:53:00.000Z"
    }
  ],
  "pagination": { "page": 1, "page_size": 25, "total": 2, "total_pages": 1 }
}
```

***

## Common patterns

### Sync new conversations to a data warehouse

Poll for conversations that have started since your last sync.

```bash theme={null}
curl "https://clarky.ai/api/v1/conversations?created_after=2026-04-30T00:00:00Z&sort=created_at&order=asc" \
  -H "Authorization: Bearer ck_live_example"
```

### Pull a full transcript

```bash theme={null}
# 1. Fetch the conversation (for metadata).
curl https://clarky.ai/api/v1/conversations/conv_01HXYZ \
  -H "Authorization: Bearer ck_live_example"

# 2. Page through its messages in order.
curl "https://clarky.ai/api/v1/conversations/conv_01HXYZ/messages?page_size=100&order=asc" \
  -H "Authorization: Bearer ck_live_example"
```

### Find every chat a customer has had with you

```bash theme={null}
curl https://clarky.ai/api/v1/contacts/c_01HABC/conversations \
  -H "Authorization: Bearer ck_live_example"
```

### Auto-assign new conversations from your CRM

Combine [List conversations](#list-conversations) with [Update a conversation](#update-a-conversation) to route inbound chats to the right rep. Filter for unassigned, in-progress conversations and PATCH each one with the right `assigned_to`.

```bash theme={null}
curl "https://clarky.ai/api/v1/conversations?active=true&type=chat" \
  -H "Authorization: Bearer ck_live_example"

curl -X PATCH https://clarky.ai/api/v1/conversations/conv_01HXYZ \
  -H "Authorization: Bearer ck_live_example" \
  -H "Content-Type: application/json" \
  -d '{ "assigned_to": "u_01HUSER" }'
```
