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.
/api/v2/messagesAuthenticatedCreate a new message in a channel and broadcast to all members.
Body Parameters
channel_idstringrequiredUUID of the channel to post in.
contentstringrequiredMessage content. Supports markdown.
content_typestringtextContent type identifier.
parent_message_idstringUUID of parent message for threading.
metadataobjectArbitrary metadata object attached to the message.
attachmentsobject[]Array of attachment objects.
conversation_idstringUUID of the conversation context.
user_idstringExplicit user ID. Falls back to JWT user.
ai_twin_idstringUUID of an AI twin sending this message.
Request
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.
/api/v2/messages/sendAuthenticatedAlias for POST /api/v2/messages. Same body and response.
Body Parameters
channel_idstringrequiredUUID of the channel.
contentstringrequiredMessage content.
Request
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.
/api/v2/messages/historyAuthenticatedList messages in a channel with pagination. Includes user profiles and reactions.
Query Parameters
channel_idstringrequiredUUID of the channel to fetch messages from.
thread_idstringFilter to messages in a specific thread.
limitinteger50Maximum number of messages to return.
offsetinteger0Number of messages to skip.
Request
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.
/api/v2/messages/searchAuthenticatedFull-text search across messages. Searches the content column.
Query Parameters
querystringrequiredSearch term. Matched against messages.content.
channel_idstringScope search to a specific channel.
limitintegerMaximum results to return.
Request
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.
/api/v2/messages/:idAuthenticatedGet a single message by UUID. Includes reaction count.
Path Parameters
idstringrequiredUUID of the message.
Request
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.
/api/v2/messages/:idAuthenticatedEdit a message. Checks ownership before updating.
Path Parameters
idstringrequiredUUID of the message to edit.
Body Parameters
user_idstringrequiredUUID of the user making the edit. Must match original author.
contentstringrequiredUpdated message content.
Request
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.
/api/v2/messages/:idAuthenticatedSoft delete a message. Sets deleted_at timestamp rather than removing the row.
Path Parameters
idstringrequiredUUID of the message to delete.
Query Parameters
user_idstringrequiredUUID of the user requesting deletion.
adminbooleanSet to true to bypass ownership check (requires admin role).
Request
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.
/api/v2/messages/:id/pinAuthenticatedPin a message. Broadcasts pin event via WebSocket.
Path Parameters
idstringrequiredUUID of the message to pin.
Body Parameters
user_idstringUUID of the user pinning. Falls back to JWT user.
Request
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).
/api/v2/messages/:id/reactAuthenticatedToggle a reaction on a message. Adds if not present, removes if already exists.
Path Parameters
idstringrequiredUUID of the message to react to.
Body Parameters
user_idstringrequiredUUID of the user reacting.
emojistringrequiredEmoji string for the reaction (e.g. "thumbsup", "fire").
Request
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.
/api/v2/messages/:id/threadAuthenticatedReply in a thread. Creates a message with parent_message_id set to :id.
Path Parameters
idstringrequiredUUID of the parent message to reply to.
Body Parameters
contentstringrequiredReply content.
content_typestringContent type identifier.
user_idstringUUID of the replying user. Falls back to JWT user.
ai_twin_idstringUUID of an AI twin sending this reply.
metadataobjectArbitrary metadata for the reply.
Request
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.
/api/v2/messages/uploadAuthenticatedUpload files via multipart form data. Stores in Supabase Storage.
Body Parameters
filesFile[]requiredOne or more files (multipart form field).
conversation_idstringrequiredUUID of the conversation to attach files to.
workspace_idstringUUID of the workspace.
conversation_typestringType of conversation (e.g. channel, dm).
Request
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.
/api/v2/messages/summarizeAuthenticatedGenerate an AI summary of channel messages using Claude Haiku.
Body Parameters
channel_idstringrequiredUUID of the channel to summarize.
messageCountintegerNumber of recent messages to include. Defaults to all recent messages.
Request
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"
}
}
}