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 and authentication

All endpoints use the base path /api/v2/conversations. Requires a valid JWT in the Authorization: Bearer header. Rate limit: 60 requests per minute.

Conversation CRUD

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

GET/api/v2/conversationsAuthenticated

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

Query Parameters

typestring

Filter by conversation type (e.g. direct, group, project).

unreadboolean

If true, return only conversations with unread messages.

archivedboolean

If true, include archived conversations.

limitinteger
Default: 20

Maximum number of conversations to return.

offsetinteger
Default: 0

Number of conversations to skip for pagination.

Request

cURL
400">curl -X 400">GET 400">class="text-emerald-400">"https:400">class="text-zinc-500">//api.lvng.ai/api/v2/conversations?400">type=group&limit=10" \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"data": [
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      400">class="text-emerald-400">"name": 400">class="text-emerald-400">"Project Alpha Discussion",
      400">class="text-emerald-400">"conversation_type": 400">class="text-emerald-400">"group",
      400">class="text-emerald-400">"description": 400">class="text-emerald-400">"Planning thread for Project Alpha",
      400">class="text-emerald-400">"project_id": 400">class="text-emerald-400">"proj_b2c3d4e5-f6a7-8901-bcde-f23456789012",
      400">class="text-emerald-400">"is_archived": false,
      400">class="text-emerald-400">"member_count": 4,
      400">class="text-emerald-400">"created_by": 400">class="text-emerald-400">"usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-02-15T10:00:00.000Z",
      400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T14:22:00.000Z"
    },
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"conv_d4e5f6a7-8901-bcde-f234-567890abcdef",
      400">class="text-emerald-400">"name": null,
      400">class="text-emerald-400">"conversation_type": 400">class="text-emerald-400">"direct",
      400">class="text-emerald-400">"description": null,
      400">class="text-emerald-400">"project_id": null,
      400">class="text-emerald-400">"is_archived": false,
      400">class="text-emerald-400">"member_count": 2,
      400">class="text-emerald-400">"created_by": 400">class="text-emerald-400">"usr_2a3b4c5d-6e7f-8901-abcd-ef2345678901",
      400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-01T09:30:00.000Z",
      400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T12:15:00.000Z"
    }
  ],
  400">class="text-emerald-400">"pagination": {
    400">class="text-emerald-400">"limit": 10,
    400">class="text-emerald-400">"offset": 0,
    400">class="text-emerald-400">"total": 2
  }
}
POST/api/v2/conversationsAuthenticated

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

conversation_typestringrequired

Type of conversation: direct, group, or project.

member_idsstring[]required

Array of user IDs to add as initial members.

namestring

Display name for the conversation. Typically used for group and project conversations.

descriptionstring

Short description of the conversation purpose.

project_idstring

Associate the conversation with a project.

parent_message_idstring

Create as a threaded reply to an existing message.

member_typesobject

Map of member_id to member type (e.g. user, twin, agent).

settingsobject

Conversation-level settings (notifications, pinning, etc.).

Request

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

Response 201

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"data": {
    400">class="text-emerald-400">"id": 400">class="text-emerald-400">"conv_e5f6a7b8-9012-cdef-3456-7890abcdef12",
    400">class="text-emerald-400">"name": 400">class="text-emerald-400">"Sprint Planning",
    400">class="text-emerald-400">"conversation_type": 400">class="text-emerald-400">"group",
    400">class="text-emerald-400">"description": 400">class="text-emerald-400">"Weekly sprint planning thread",
    400">class="text-emerald-400">"project_id": 400">class="text-emerald-400">"proj_b2c3d4e5-f6a7-8901-bcde-f23456789012",
    400">class="text-emerald-400">"is_archived": false,
    400">class="text-emerald-400">"member_count": 3,
    400">class="text-emerald-400">"created_by": 400">class="text-emerald-400">"usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T15:30:00.000Z",
    400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T15:30:00.000Z"
  }
}
GET/api/v2/conversations/:idAuthenticated

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

Path Parameters

idstringrequired

The conversation ID.

Request

cURL
400">curl -X 400">GET https:400">class="text-zinc-500">//api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"data": {
    400">class="text-emerald-400">"id": 400">class="text-emerald-400">"conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    400">class="text-emerald-400">"name": 400">class="text-emerald-400">"Project Alpha Discussion",
    400">class="text-emerald-400">"conversation_type": 400">class="text-emerald-400">"group",
    400">class="text-emerald-400">"description": 400">class="text-emerald-400">"Planning thread for Project Alpha",
    400">class="text-emerald-400">"project_id": 400">class="text-emerald-400">"proj_b2c3d4e5-f6a7-8901-bcde-f23456789012",
    400">class="text-emerald-400">"is_archived": false,
    400">class="text-emerald-400">"settings": {},
    400">class="text-emerald-400">"created_by": 400">class="text-emerald-400">"usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-02-15T10:00:00.000Z",
    400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T14:22:00.000Z",
    400">class="text-emerald-400">"members": [
      {
        400">class="text-emerald-400">"id": 400">class="text-emerald-400">"usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
        400">class="text-emerald-400">"display_name": 400">class="text-emerald-400">"Matty Squarzoni",
        400">class="text-emerald-400">"role": 400">class="text-emerald-400">"admin",
        400">class="text-emerald-400">"member_type": 400">class="text-emerald-400">"user",
        400">class="text-emerald-400">"joined_at": 400">class="text-emerald-400">"2026-02-15T10:00:00.000Z"
      },
      {
        400">class="text-emerald-400">"id": 400">class="text-emerald-400">"usr_2a3b4c5d-6e7f-8901-abcd-ef2345678901",
        400">class="text-emerald-400">"display_name": 400">class="text-emerald-400">"Sarah Chen",
        400">class="text-emerald-400">"role": 400">class="text-emerald-400">"member",
        400">class="text-emerald-400">"member_type": 400">class="text-emerald-400">"user",
        400">class="text-emerald-400">"joined_at": 400">class="text-emerald-400">"2026-02-15T10:00:00.000Z"
      },
      {
        400">class="text-emerald-400">"id": 400">class="text-emerald-400">"twn_c4d5e6f7-8901-abcd-ef23-456789012345",
        400">class="text-emerald-400">"display_name": 400">class="text-emerald-400">"Research Assistant",
        400">class="text-emerald-400">"role": 400">class="text-emerald-400">"member",
        400">class="text-emerald-400">"member_type": 400">class="text-emerald-400">"twin",
        400">class="text-emerald-400">"joined_at": 400">class="text-emerald-400">"2026-02-16T08:00:00.000Z"
      }
    ]
  }
}
PATCH/api/v2/conversations/:idAuthenticated

Update conversation properties. Only conversation admins can update.

Path Parameters

idstringrequired

The conversation ID.

Body Parameters

namestring

Updated conversation name.

descriptionstring

Updated description.

is_archivedboolean

Set to true to archive, false to unarchive.

settingsobject

Updated conversation settings.

Request

cURL
400">curl -X 400">PATCH https:400">class="text-zinc-500">//api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY" \
  -H 400">class="text-emerald-400">"Content-Type: application/json" \
  -d '{
    400">class="text-emerald-400">"name": 400">class="text-emerald-400">"Project Alpha - Archived",
    400">class="text-emerald-400">"is_archived": true
  }'

Response 200

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"data": {
    400">class="text-emerald-400">"id": 400">class="text-emerald-400">"conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    400">class="text-emerald-400">"name": 400">class="text-emerald-400">"Project Alpha - Archived",
    400">class="text-emerald-400">"conversation_type": 400">class="text-emerald-400">"group",
    400">class="text-emerald-400">"description": 400">class="text-emerald-400">"Planning thread for Project Alpha",
    400">class="text-emerald-400">"project_id": 400">class="text-emerald-400">"proj_b2c3d4e5-f6a7-8901-bcde-f23456789012",
    400">class="text-emerald-400">"is_archived": true,
    400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-02-15T10:00:00.000Z",
    400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T15:45:00.000Z"
  }
}
DELETE/api/v2/conversations/:idAuthenticated

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 the conversation instead.

Path Parameters

idstringrequired

The conversation ID.

Request

cURL
400">curl -X 400">DELETE https:400">class="text-zinc-500">//api.lvng.ai/api/v2/conversations/conv_e5f6a7b8-9012-cdef-3456-7890abcdef12 \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"deleted": true
}

Note: When a non-admin member calls DELETE, the response returns {"success": true, "left": true} instead of "deleted": true. 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. Sending a message also updates the conversation's updated_at timestamp and emits a real-time socket event to all connected members.

GET/api/v2/conversations/:id/messagesAuthenticated

List messages in a conversation with cursor-based pagination. Messages are returned in reverse chronological order (newest first).

Path Parameters

idstringrequired

The conversation ID.

Query Parameters

cursorstring

Cursor from a previous response to fetch the next page. Omit for the first page.

limitinteger
Default: 50

Number of messages to return per page.

Request

cURL
400">curl -X 400">GET 400">class="text-emerald-400">"https:400">class="text-zinc-500">//api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890/messages?limit=20" \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"data": [
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"msg_f7e6d5c4-b3a2-1098-7654-321fedcba098",
      400">class="text-emerald-400">"conversation_id": 400">class="text-emerald-400">"conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"usr_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Let us finalize the Q2 roadmap today.",
      400">class="text-emerald-400">"message_type": 400">class="text-emerald-400">"user",
      400">class="text-emerald-400">"parent_message_id": null,
      400">class="text-emerald-400">"metadata": {},
      400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T14:22:00.000Z",
      400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T14:22:00.000Z"
    },
    {
      400">class="text-emerald-400">"id": 400">class="text-emerald-400">"msg_e6d5c4b3-a210-9876-5432-1fedcba09876",
      400">class="text-emerald-400">"conversation_id": 400">class="text-emerald-400">"conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"usr_2a3b4c5d-6e7f-8901-abcd-ef2345678901",
      400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Sounds good. I will pull up the backlog.",
      400">class="text-emerald-400">"message_type": 400">class="text-emerald-400">"user",
      400">class="text-emerald-400">"parent_message_id": null,
      400">class="text-emerald-400">"metadata": {},
      400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T14:20:00.000Z",
      400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T14:20:00.000Z"
    }
  ],
  400">class="text-emerald-400">"pagination": {
    400">class="text-emerald-400">"cursor": 400">class="text-emerald-400">"msg_e6d5c4b3-a210-9876-5432-1fedcba09876",
    400">class="text-emerald-400">"hasMore": true,
    400">class="text-emerald-400">"total": 128
  }
}
POST/api/v2/conversations/:id/messagesAuthenticated

Send a message in a conversation. Updates the conversation's updated_at timestamp and emits a real-time socket event to connected members.

Path Parameters

idstringrequired

The conversation ID.

Body Parameters

contentstringrequired

The message text content.

message_typestring
Default: user

Message type (e.g. user, system, twin).

parent_message_idstring

ID of the parent message for threaded replies.

metadataobject

Arbitrary metadata to attach to the message.

Request

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

Response 201

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

Members

Add and remove members from a conversation. Adding a member uses UPSERT semantics -- if the member already exists, the operation succeeds without error. Only admins can remove other members.

POST/api/v2/conversations/:id/membersAuthenticated

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

Path Parameters

idstringrequired

The conversation ID.

Body Parameters

member_idstringrequired

The user or twin ID to add.

member_typestring
Default: user

Type of member: user or twin.

Request

cURL
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890/members \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY" \
  -H 400">class="text-emerald-400">"Content-Type: application/json" \
  -d '{
    400">class="text-emerald-400">"member_id": 400">class="text-emerald-400">"usr_3b4c5d6e-7f80-9012-bcde-f34567890123",
    400">class="text-emerald-400">"member_type": 400">class="text-emerald-400">"user"
  }'

Response 201

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"added": true,
  400">class="text-emerald-400">"member_id": 400">class="text-emerald-400">"usr_3b4c5d6e-7f80-9012-bcde-f34567890123"
}
DELETE/api/v2/conversations/:id/members/:memberIdAuthenticated

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

Path Parameters

idstringrequired

The conversation ID.

memberIdstringrequired

The member ID to remove.

Request

cURL
400">curl -X 400">DELETE https:400">class="text-zinc-500">//api.lvng.ai/api/v2/conversations/conv_a1b2c3d4-e5f6-7890-abcd-ef1234567890/members/usr_3b4c5d6e-7f80-9012-bcde-f34567890123 \
  -H 400">class="text-emerald-400">"Authorization: Bearer YOUR_API_KEY"

Response 200

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"removed": true,
  400">class="text-emerald-400">"member_id": 400">class="text-emerald-400">"usr_3b4c5d6e-7f80-9012-bcde-f34567890123"
}

Read Receipts

Mark messages as read in bulk. Uses UPSERT on the read_receipts table, so marking an already-read message is idempotent.

POST/api/v2/conversations/:id/read-receiptsAuthenticated

Mark one or more messages as read. Uses UPSERT so calling this with already-read message IDs is safe and idempotent.

Path Parameters

idstringrequired

The conversation ID.

Body Parameters

message_idsstring[]required

Array of message IDs to mark as read.

Request

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

Response 200

{
  400">class="text-emerald-400">"success": true,
  400">class="text-emerald-400">"marked_read": 2
}