# Conversations API

Conversations are multi-tenant messaging threads that support direct messages, group chats, and project-scoped discussions. Unlike channels, conversations are scoped to specific participants and support cursor-based message pagination, member management with UPSERT semantics, and bulk read receipts.

> **Base path:** `/api/v2/conversations` | **Auth:** JWT (Bearer) | **Rate limit:** 60 req/min

## Conversation CRUD

Create, list, update, and delete conversations. The authenticated user is automatically added as a member when creating a conversation.

### GET /api/v2/conversations

List Conversations -- List all conversations the authenticated user is a member of. Supports filtering by type, unread status, and archive state.

#### Query Parameters

| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| type | string | No | -- | Filter by conversation type (e.g. direct, group, project). |
| unread | boolean | No | -- | If true, return only conversations with unread messages. |
| archived | boolean | No | -- | If true, include archived conversations. |
| limit | integer | No | 20 | Maximum number of conversations to return. |
| offset | integer | No | 0 | Number of conversations to skip for pagination. |

#### Example Request

```bash
curl -X GET "https://api.lvng.ai/api/v2/conversations?type=group&limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Response (200)

```json
{
  "success": true,
  "data": [
    {
      "id": "conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Project Alpha Discussion",
      "conversation_type": "group",
      "description": "Planning thread for Project Alpha",
      "project_id": "proj_b2c3d4e5-f6a7-8901-bcde-f23456789012",
      "is_archived": false,
      "member_count": 4,
      "created_by": "usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      "created_at": "2026-02-15T10:00:00.000Z",
      "updated_at": "2026-03-19T14:22:00.000Z"
    }
  ],
  "pagination": { "limit": 10, "offset": 0, "total": 1 }
}
```

### POST /api/v2/conversations

Create Conversation -- Create a new conversation. The authenticated user is automatically added as a member. At least one other member must be specified in member_ids.

#### Body Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| conversation_type | string | Yes | Type of conversation: direct, group, or project. |
| member_ids | string[] | Yes | Array of user IDs to add as initial members. |
| name | string | No | Display name for the conversation. |
| description | string | No | Short description of the conversation purpose. |
| project_id | string | No | Associate the conversation with a project. |
| parent_message_id | string | No | Create as a threaded reply to an existing message. |
| member_types | object | No | Map of member_id to member type (e.g. user, twin, agent). |
| settings | object | No | Conversation-level settings (notifications, pinning, etc.). |

#### Example Request

```bash
curl -X POST https://api.lvng.ai/api/v2/conversations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "conversation_type": "group",
    "name": "Sprint Planning",
    "description": "Weekly sprint planning thread",
    "member_ids": [
      "usr_2a3b4c5d-6e7f-8901-abcd-ef2345678901",
      "usr_3b4c5d6e-7f80-9012-bcde-f34567890123"
    ],
    "project_id": "proj_b2c3d4e5-f6a7-8901-bcde-f23456789012"
  }'
```

#### Response (201)

```json
{
  "success": true,
  "data": {
    "id": "conv_e5f6a7b8-9012-cdef-3456-7890abcdef12",
    "name": "Sprint Planning",
    "conversation_type": "group",
    "description": "Weekly sprint planning thread",
    "project_id": "proj_b2c3d4e5-f6a7-8901-bcde-f23456789012",
    "is_archived": false,
    "member_count": 3,
    "created_by": "usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "created_at": "2026-03-19T15:30:00.000Z",
    "updated_at": "2026-03-19T15:30:00.000Z"
  }
}
```

### GET /api/v2/conversations/:id

Get Conversation -- Get detailed information about a specific conversation, including its full member list.

#### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string | Yes | The conversation ID. |

#### Example Request

```bash
curl -X GET https://api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Response (200)

```json
{
  "success": true,
  "data": {
    "id": "conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Project Alpha Discussion",
    "conversation_type": "group",
    "description": "Planning thread for Project Alpha",
    "members": [
      { "id": "usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "display_name": "Matty Squarzoni", "role": "admin", "member_type": "user", "joined_at": "2026-02-15T10:00:00.000Z" },
      { "id": "twn_c4d5e6f7-8901-abcd-ef23-456789012345", "display_name": "Research Assistant", "role": "member", "member_type": "twin", "joined_at": "2026-02-16T08:00:00.000Z" }
    ]
  }
}
```

### PATCH /api/v2/conversations/:id

Update Conversation -- Update conversation properties. Only conversation admins can update.

#### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string | Yes | The conversation ID. |

#### Body Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| name | string | No | Updated conversation name. |
| description | string | No | Updated description. |
| is_archived | boolean | No | Set to true to archive, false to unarchive. |
| settings | object | No | Updated conversation settings. |

#### Example Request

```bash
curl -X PATCH https://api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Project Alpha - Archived",
    "is_archived": true
  }'
```

#### Response (200)

```json
{
  "success": true,
  "data": {
    "id": "conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Project Alpha - Archived",
    "is_archived": true,
    "updated_at": "2026-03-19T15:45:00.000Z"
  }
}
```

### DELETE /api/v2/conversations/:id

Delete / Leave Conversation -- Delete or leave a conversation. If the authenticated user is an admin, the entire conversation is deleted. If they are a regular member, they leave instead.

#### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string | Yes | The conversation ID. |

#### Example Request

```bash
curl -X DELETE https://api.lvng.ai/api/v2/conversations/conv_e5f6a7b8-9012-cdef-3456-7890abcdef12 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Response (200)

```json
{
  "success": true,
  "deleted": true
}
```

> **Note:** When a non-admin member calls DELETE, the response returns `{"success": true, "left": true}` instead. The conversation continues to exist for other members.

## Messages

Send and retrieve messages within a conversation. Messages use cursor-based pagination in reverse chronological order.

### GET /api/v2/conversations/:id/messages

List Messages -- List messages in a conversation with cursor-based pagination. Messages are returned newest first.

#### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string | Yes | The conversation ID. |

#### Query Parameters

| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| cursor | string | No | -- | Cursor from a previous response to fetch the next page. |
| limit | integer | No | 50 | Number of messages to return per page. |

#### Example Request

```bash
curl -X GET "https://api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890/messages?limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Response (200)

```json
{
  "success": true,
  "data": [
    {
      "id": "msg_f7e6d5c4-b3a2-1098-7654-321fedcba098",
      "conversation_id": "conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "user_id": "usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      "content": "Let us finalize the Q2 roadmap today.",
      "message_type": "user",
      "parent_message_id": null,
      "metadata": {},
      "created_at": "2026-03-19T14:22:00.000Z"
    }
  ],
  "pagination": { "cursor": "msg_e6d5c4b3-a210-9876-5432-1fedcba09876", "hasMore": true, "total": 128 }
}
```

### POST /api/v2/conversations/:id/messages

Send Message -- Send a message in a conversation. Updates the conversation's updated_at and emits a real-time socket event.

#### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string | Yes | The conversation ID. |

#### Body Parameters

| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| content | string | Yes | -- | The message text content. |
| message_type | string | No | user | Message type (e.g. user, system, twin). |
| parent_message_id | string | No | -- | ID of the parent message for threaded replies. |
| metadata | object | No | -- | Arbitrary metadata to attach to the message. |

#### Example Request

```bash
curl -X POST https://api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "The revised timeline looks good. Shipping next Tuesday.",
    "metadata": { "mentions": ["usr_2a3b4c5d-6e7f-8901-abcd-ef2345678901"] }
  }'
```

#### Response (201)

```json
{
  "success": true,
  "data": {
    "id": "msg_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "conversation_id": "conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "user_id": "usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "content": "The revised timeline looks good. Shipping next Tuesday.",
    "message_type": "user",
    "metadata": { "mentions": ["usr_2a3b4c5d-6e7f-8901-abcd-ef2345678901"] },
    "created_at": "2026-03-19T15:50:00.000Z"
  }
}
```

## Members

Add and remove members from a conversation. Adding uses UPSERT semantics. Only admins can remove other members.

### POST /api/v2/conversations/:id/members

Add Member -- Add a member to the conversation. Uses UPSERT semantics, so adding an existing member is a no-op.

#### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string | Yes | The conversation ID. |

#### Body Parameters

| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| member_id | string | Yes | -- | The user or twin ID to add. |
| member_type | string | No | user | Type of member: user or twin. |

#### Example Request

```bash
curl -X POST https://api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890/members \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "member_id": "usr_3b4c5d6e-7f80-9012-bcde-f34567890123", "member_type": "user" }'
```

#### Response (201)

```json
{
  "success": true,
  "added": true,
  "member_id": "usr_3b4c5d6e-7f80-9012-bcde-f34567890123"
}
```

### DELETE /api/v2/conversations/:id/members/:memberId

Remove Member -- Remove a member from the conversation. Only conversation admins can remove other members.

#### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string | Yes | The conversation ID. |
| memberId | string | Yes | The member ID to remove. |

#### Example Request

```bash
curl -X DELETE https://api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890/members/usr_3b4c5d6e-7f80-9012-bcde-f34567890123 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

#### Response (200)

```json
{
  "success": true,
  "removed": true,
  "member_id": "usr_3b4c5d6e-7f80-9012-bcde-f34567890123"
}
```

## Read Receipts

Mark messages as read in bulk. Uses UPSERT so marking already-read messages is idempotent.

### POST /api/v2/conversations/:id/read-receipts

Mark Messages as Read -- Mark one or more messages as read.

#### Path Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| id | string | Yes | The conversation ID. |

#### Body Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| message_ids | string[] | Yes | Array of message IDs to mark as read. |

#### Example Request

```bash
curl -X POST https://api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890/read-receipts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message_ids": [
      "msg_f7e6d5c4-b3a2-1098-7654-321fedcba098",
      "msg_e6d5c4b3-a210-9876-5432-1fedcba09876"
    ]
  }'
```

#### Response (200)

```json
{
  "success": true,
  "marked_read": 2
}
```
