# Conversations

> List, read, reply to and close conversations.

A conversation is one thread between a customer and your team or the AI agent. Requests use your secret API key as a bearer token. See [authentication](https://tirver.com/help/api/authentication.md).

## The conversation object

| Field | Type | Meaning |
|---|---|---|
| `id` | string | The conversation id. |
| `status` | string | `open`, `snoozed` or `closed`. |
| `customer_id` | string | The customer in the conversation. |
| `assignee_id` | string or null | The team member who owns it, or null when unassigned. |
| `handled_by` | string | `ai` when the AI agent is handling it, otherwise `team`. |
| `channel` | string | Where it started: `widget`, `email` or `api`. |
| `subject` | string or null | The subject line, when there is one. |
| `tags` | array of strings | Tag names on the conversation. |
| `snoozed_until` | string or null | When a snoozed conversation returns to open. |
| `last_message_at` | string or null | Time of the latest message. |
| `created_at` | string | When it started. |
| `updated_at` | string | When it last changed. |

## List conversations

`GET /api/v1/conversations`

Needs the `conversations:read` scope. Newest first.

| Parameter | Type | What it does |
|---|---|---|
| `status` | string | One of `open`, `snoozed` or `closed`. |
| `assignee_id` | string | Only conversations assigned to this team member. |
| `handled_by` | string | `ai` or `team`. |
| `tag` | string | Only conversations with this tag, by name or id. |
| `customer_id` | string | Only conversations of this customer. |
| `limit` | integer | Page size, 1 to 100. Defaults to 25. |
| `cursor` | string | The `next_cursor` from the previous page. |

**curl**

```bash
curl "https://app.tirver.com/api/v1/conversations?status=open" \
  -H "Authorization: Bearer $TIRVER_API_KEY"
```

**JavaScript**

```js
const res = await fetch('https://app.tirver.com/api/v1/conversations?status=open', {
  headers: { Authorization: `Bearer ${process.env.TIRVER_API_KEY}` },
});
const { data, next_cursor, has_more } = await res.json();
```

**Python**

```python
res = requests.get(
    "https://app.tirver.com/api/v1/conversations",
    params={"status": "open"},
    headers={"Authorization": f"Bearer {os.environ['TIRVER_API_KEY']}"},
    timeout=10,
)
data = res.json()["data"]
```

```json
{
  "data": [
    {
      "id": "8c1f0d52",
      "status": "open",
      "customer_id": "3b7a91e4",
      "assignee_id": null,
      "handled_by": "ai",
      "channel": "widget",
      "subject": "Cannot log in",
      "tags": ["bug"],
      "snoozed_until": null,
      "last_message_at": "2026-11-14T09:05:00.000Z",
      "created_at": "2026-11-14T09:02:00.000Z",
      "updated_at": "2026-11-14T09:05:00.000Z"
    }
  ],
  "next_cursor": null,
  "has_more": false
}
```

## Get a conversation

`GET /api/v1/conversations/{id}`

Needs `conversations:read`. Returns the conversation fields above, plus:

- `customer`: the customer's `id`, `name` and `email`.
- `summary`: a short plain extract of the thread (the first customer message, the latest, and the number of replies). It is not an AI summary.
- `messages`: up to the first 500 messages, oldest first, internal notes included.

```bash
curl https://app.tirver.com/api/v1/conversations/8c1f0d52 \
  -H "Authorization: Bearer $TIRVER_API_KEY"
```

## List messages

`GET /api/v1/conversations/{id}/messages`

Needs `conversations:read`. Oldest first. Takes `limit` and `cursor`. Each message looks like this.

| Field | Type | Meaning |
|---|---|---|
| `id` | string | The message id. |
| `conversation_id` | string | The conversation it belongs to. |
| `type` | string | `reply` is visible to the customer. `note` is internal. |
| `sender` | string | `customer`, `agent` or `ai`. |
| `author_id` | string or null | The team member or customer id. Null for the AI agent. |
| `body` | string | The text. |
| `citations` | array | Sources the AI agent used, each with `title` and `url`. |
| `created_at` | string | When it was sent. |

## Reply to a conversation

`POST /api/v1/conversations/{id}/messages`

Needs `conversations:write`. A `reply` reaches the customer and takes the conversation off the AI agent. A `note` stays with your team. Returns `201` with the new message.

| Field | Type | What it does |
|---|---|---|
| `body` | string | Required. The message text, 1 to 4000 characters. |
| `type` | string | Required: `reply` or `note`. There is no default, so a note is never sent as a reply by leaving it out. |
| `author_id` | string | Optional. The team member the message is from. Defaults to the person who created the key. |

**curl**

```bash
curl https://app.tirver.com/api/v1/conversations/8c1f0d52/messages \
  -H "Authorization: Bearer $TIRVER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body": "Thanks, we have fixed this.", "type": "reply"}'
```

**JavaScript**

```js
await fetch('https://app.tirver.com/api/v1/conversations/8c1f0d52/messages', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.TIRVER_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ body: 'Thanks, we have fixed this.', type: 'reply' }),
});
```

**Python**

```python
requests.post(
    "https://app.tirver.com/api/v1/conversations/8c1f0d52/messages",
    headers={"Authorization": f"Bearer {os.environ['TIRVER_API_KEY']}"},
    json={"body": "Thanks, we have fixed this.", "type": "reply"},
    timeout=10,
)
```

```json
{
  "id": "5d2e7a10",
  "conversation_id": "8c1f0d52",
  "type": "reply",
  "sender": "agent",
  "author_id": "u_1",
  "body": "Thanks, we have fixed this.",
  "citations": [],
  "created_at": "2026-11-15T10:00:00.000Z"
}
```

## Close a conversation

`POST /api/v1/conversations/{id}/close`

Needs `conversations:write`. Returns the conversation with `status` set to `closed`. Closing sends no message to the customer.

A conversation the AI agent answered, that no person touched, can count as an AI resolution when it is closed. See [what counts as a resolution](https://tirver.com/help/what-counts-as-a-resolution.md).

Source: https://tirver.com/help/api/conversations
