Messages API

Full CRUD for messages within channels, plus threads, reactions, file uploads, and AI-powered summarization. All endpoints require JWT authentication and are rate-limited to 60 requests per minute.

Base path: /api/v2/messages

Create Message

Create a new message in a channel. The message is validated, inserted into the database, broadcast to all channel members via WebSocket, and forwarded to any assigned digital twins.

POST/api/v2/messagesAuthenticated

Create a new message in a channel and broadcast to all members.

Body Parameters

channel_idstringrequired

UUID of the channel to post in.

contentstringrequired

Message content. Supports markdown.

content_typestring
Default: text

Content type identifier.

parent_message_idstring

UUID of parent message for threading.

metadataobject

Arbitrary metadata object attached to the message.

attachmentsobject[]

Array of attachment objects.

conversation_idstring

UUID of the conversation context.

user_idstring

Explicit user ID. Falls back to JWT user.

ai_twin_idstring

UUID of an AI twin sending this message.

Request

cURL
curl -X POST https://api.lvng.ai/api/v2/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel_id": "ch_01HMPJ4WX9R6N8K5T3F0V7QB1Z",
    "content": "Heads up: deploy starts in 10 minutes.",
    "content_type": "text"
  }'

Response 201

{
  "success": true,
  "data": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "channel_id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "Deploy the staging environment and run integration tests.",
    "content_type": "text",
    "user_id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
    "parent_message_id": null,
    "metadata": {
      "source": "api",
      "priority": "high"
    },
    "attachments": null,
    "created_at": "2026-03-19T15:10:22.000Z",
    "updated_at": "2026-03-19T15:10:22.000Z"
  },
  "meta": {
    "timestamp": "2026-03-19T15:10:22.000Z"
  }
}

Send Message (Alias)

Alias for the create endpoint. Accepts the same body and returns the same response.

POST/api/v2/messages/sendAuthenticated

Alias for POST /api/v2/messages. Same body and response.

Body Parameters

channel_idstringrequired

UUID of the channel.

contentstringrequired

Message content.

Request

cURL
curl -X POST "https://api.lvng.ai/api/v2/messages/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "content": "string",
  "attachments": "[]",
  "channel_id": "00000000-0000-0000-0000-000000000000",
  "conversation_id": "00000000-0000-0000-0000-000000000000",
  "user_id": "00000000-0000-0000-0000-000000000000",
  "ai_twin_id": "00000000-0000-0000-0000-000000000000"
}'

Response 201

{
  "success": true,
  "data": {
    "id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
    "channel_id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "Quick update: tests passed.",
    "content_type": "text",
    "user_id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
    "created_at": "2026-03-19T15:12:00.000Z",
    "updated_at": "2026-03-19T15:12:00.000Z"
  },
  "meta": {
    "timestamp": "2026-03-19T15:12:00.000Z"
  }
}

List Messages

Retrieve message history for a channel with offset-based pagination. Messages are returned with LEFT JOIN data from user_profiles and reaction counts.

GET/api/v2/messages/historyAuthenticated

List messages in a channel with pagination. Includes user profiles and reactions.

Query Parameters

channel_idstringrequired

UUID of the channel to fetch messages from.

thread_idstring

Filter to messages in a specific thread.

limitinteger
Default: 50

Maximum number of messages to return.

offsetinteger
Default: 0

Number of messages to skip.

Request

cURL
curl -X GET "https://api.lvng.ai/api/v2/messages/history?channel_id=ch_01HMPJ4WX9R6N8K5T3F0V7QB1Z&limit=50" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 200

{
  "success": true,
  "data": [
    {
      "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "channel_id": "550e8400-e29b-41d4-a716-446655440000",
      "content": "Can you analyze the Q1 marketing data?",
      "content_type": "text",
      "user_id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
      "display_name": "Matty Squarzoni",
      "avatar_url": "https://storage.lvng.ai/avatars/a0eebc99.jpg",
      "reactions": [],
      "parent_message_id": null,
      "metadata": {},
      "created_at": "2026-03-19T14:30:00.000Z",
      "updated_at": "2026-03-19T14:30:00.000Z"
    }
  ],
  "meta": {
    "total": 142,
    "page": 1,
    "limit": 25,
    "offset": 0
  }
}

Search Messages

Full-text search on message content. Optionally scope to a specific channel.

GET/api/v2/messages/searchAuthenticated

Full-text search across messages. Searches the content column.

Query Parameters

querystringrequired

Search term. Matched against messages.content.

channel_idstring

Scope search to a specific channel.

limitinteger

Maximum results to return.

Request

cURL
curl -X GET "https://api.lvng.ai/api/v2/messages/search" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 200

{
  "success": true,
  "data": [
    {
      "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "channel_id": "550e8400-e29b-41d4-a716-446655440000",
      "content": "Deploy the staging environment and run integration tests.",
      "user_id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
      "created_at": "2026-03-19T15:10:22.000Z"
    }
  ],
  "meta": {
    "total": 1
  }
}

Get Message

Retrieve a single message by ID. Includes reaction count.

GET/api/v2/messages/:idAuthenticated

Get a single message by UUID. Includes reaction count.

Path Parameters

idstringrequired

UUID of the message.

Request

cURL
curl -X GET "https://api.lvng.ai/api/v2/messages/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 200

{
  "success": true,
  "data": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "channel_id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "Can you analyze the Q1 marketing data?",
    "content_type": "text",
    "user_id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
    "parent_message_id": null,
    "metadata": {},
    "reaction_count": 3,
    "created_at": "2026-03-19T14:30:00.000Z",
    "updated_at": "2026-03-19T14:30:00.000Z"
  },
  "meta": {}
}

Edit Message

Update the content of an existing message. Ownership is checked — only the original author can edit.

PUT/api/v2/messages/:idAuthenticated

Edit a message. Checks ownership before updating.

Path Parameters

idstringrequired

UUID of the message to edit.

Body Parameters

user_idstringrequired

UUID of the user making the edit. Must match original author.

contentstringrequired

Updated message content.

Request

cURL
curl -X PUT "https://api.lvng.ai/api/v2/messages/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "user_id": "usr_01HMPJ800K2N7P6T4Q1W3F8C9X",
  "content": "Heads up: deploy starts in 5 minutes (moved up)."
}'

Response 200

{
  "success": true,
  "data": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "channel_id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "Can you analyze the Q1 and Q2 marketing data?",
    "content_type": "text",
    "user_id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
    "metadata": {},
    "created_at": "2026-03-19T14:30:00.000Z",
    "updated_at": "2026-03-19T15:45:00.000Z"
  }
}

Delete Message

Soft-delete a message by setting its deleted_at timestamp. Admins can delete any message; regular users can only delete their own.

DELETE/api/v2/messages/:idAuthenticated

Soft delete a message. Sets deleted_at timestamp rather than removing the row.

Path Parameters

idstringrequired

UUID of the message to delete.

Query Parameters

user_idstringrequired

UUID of the user requesting deletion.

adminboolean

Set to true to bypass ownership check (requires admin role).

Request

cURL
curl -X DELETE "https://api.lvng.ai/api/v2/messages/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 200

{
  "success": true,
  "data": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "deleted_at": "2026-03-19T16:00:00.000Z"
  }
}

Pin Message

Pin a message within its channel. Broadcasts a WebSocket event to all channel members.

POST/api/v2/messages/:id/pinAuthenticated

Pin a message. Broadcasts pin event via WebSocket.

Path Parameters

idstringrequired

UUID of the message to pin.

Body Parameters

user_idstring

UUID of the user pinning. Falls back to JWT user.

Request

cURL
curl -X POST "https://api.lvng.ai/api/v2/messages/{id}/pin" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response 200

{
  "success": true,
  "data": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "channel_id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "Can you analyze the Q1 marketing data?",
    "metadata": {
      "pinned": true,
      "pinned_by": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
      "pinned_at": "2026-03-19T16:05:00.000Z"
    },
    "updated_at": "2026-03-19T16:05:00.000Z"
  }
}

Toggle Reaction

Add or remove a reaction on a message. If the user already has the same emoji reaction, it is removed (toggle behavior).

POST/api/v2/messages/:id/reactAuthenticated

Toggle a reaction on a message. Adds if not present, removes if already exists.

Path Parameters

idstringrequired

UUID of the message to react to.

Body Parameters

user_idstringrequired

UUID of the user reacting.

emojistringrequired

Emoji string for the reaction (e.g. "thumbsup", "fire").

Request

cURL
curl -X POST "https://api.lvng.ai/api/v2/messages/{id}/react" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "user_id": "00000000-0000-0000-0000-000000000000",
  "emoji": "string"
}'

Response 200

{
  "success": true,
  "data": {
    "id": "d4735e3a-265e-16d0-8b4b-b7bfa8e5b9e0",
    "message_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "user_id": "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
    "emoji": "thumbsup",
    "created_at": "2026-03-19T16:10:00.000Z"
  },
  "meta": {}
}

Reply in Thread

Create a reply in a message thread. Sets parent_message_id to the target message, creating a threaded conversation.

POST/api/v2/messages/:id/threadAuthenticated

Reply in a thread. Creates a message with parent_message_id set to :id.

Path Parameters

idstringrequired

UUID of the parent message to reply to.

Body Parameters

contentstringrequired

Reply content.

content_typestring

Content type identifier.

user_idstring

UUID of the replying user. Falls back to JWT user.

ai_twin_idstring

UUID of an AI twin sending this reply.

metadataobject

Arbitrary metadata for the reply.

Request

cURL
curl -X POST "https://api.lvng.ai/api/v2/messages/{id}/thread" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "content": "string",
  "user_id": "00000000-0000-0000-0000-000000000000",
  "ai_twin_id": "00000000-0000-0000-0000-000000000000",
  "content_type": "text",
  "metadata": {}
}'

Response 201

{
  "success": true,
  "data": {
    "id": "e3b0c442-98fc-1c14-b39f-27bd3e8cd9a1",
    "channel_id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "Here is the Q1 analysis you requested.",
    "content_type": "text",
    "user_id": null,
    "ai_twin_id": "b5b2c3d4-e5f6-7890-abcd-ef1234567890",
    "parent_message_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "metadata": {},
    "created_at": "2026-03-19T16:15:00.000Z",
    "updated_at": "2026-03-19T16:15:00.000Z"
  }
}

Upload Files

Upload one or more files as multipart form data. Files are stored in Supabase Storage and returned with public URLs.

POST/api/v2/messages/uploadAuthenticated

Upload files via multipart form data. Stores in Supabase Storage.

Body Parameters

filesFile[]required

One or more files (multipart form field).

conversation_idstringrequired

UUID of the conversation to attach files to.

workspace_idstring

UUID of the workspace.

conversation_typestring

Type of conversation (e.g. channel, dm).

Request

cURL
curl -X POST "https://api.lvng.ai/api/v2/messages/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response 200

{
  "success": true,
  "data": {
    "files": [
      {
        "name": "report.pdf",
        "url": "https://storage.lvng.ai/uploads/550e8400/report.pdf",
        "size": 245760,
        "type": "application/pdf"
      },
      {
        "name": "chart.png",
        "url": "https://storage.lvng.ai/uploads/550e8400/chart.png",
        "size": 89200,
        "type": "image/png"
      }
    ],
    "conversation_id": "550e8400-e29b-41d4-a716-446655440000",
    "conversation_type": "channel"
  }
}

Summarize Conversation

Generate an AI summary of recent messages in a channel using Claude Haiku. Returns the summary text, message count covered, and time range.

POST/api/v2/messages/summarizeAuthenticated

Generate an AI summary of channel messages using Claude Haiku.

Body Parameters

channel_idstringrequired

UUID of the channel to summarize.

messageCountinteger

Number of recent messages to include. Defaults to all recent messages.

Request

cURL
curl -X POST "https://api.lvng.ai/api/v2/messages/summarize" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response 200

{
  "success": true,
  "data": {
    "summary": "The team discussed the Q1 marketing report and deployment plans. Key decisions: marketing budget will increase 15% for Q2 targeting enterprise accounts, staging deployment scheduled for Friday with full integration tests, and Slack notifications will be added to the CI/CD pipeline.",
    "messageCount": 47,
    "timeRange": {
      "from": "2026-03-18T09:00:00.000Z",
      "to": "2026-03-19T15:12:45.000Z"
    }
  }
}