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
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN" \
-H 400">class="text-emerald-400">"Content-Type: application/json" \
-d '{
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Deploy the staging environment and run integration tests.",
400">class="text-emerald-400">"metadata": {
400">class="text-emerald-400">"source": 400">class="text-emerald-400">"api",
400">class="text-emerald-400">"priority": 400">class="text-emerald-400">"high"
}
}'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">"7c9e6679-7425-40de-944b-e07fc1f90ae7",
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Deploy the staging environment and run integration tests.",
400">class="text-emerald-400">"content_type": 400">class="text-emerald-400">"text",
400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"parent_message_id": null,
400">class="text-emerald-400">"metadata": {
400">class="text-emerald-400">"source": 400">class="text-emerald-400">"api",
400">class="text-emerald-400">"priority": 400">class="text-emerald-400">"high"
},
400">class="text-emerald-400">"attachments": null,
400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T15:10:22.000Z",
400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T15:10:22.000Z"
},
400">class="text-emerald-400">"meta": {
400">class="text-emerald-400">"timestamp": 400">class="text-emerald-400">"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
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/send \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN" \
-H 400">class="text-emerald-400">"Content-Type: application/json" \
-d '{
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Quick update: tests passed."
}'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">"9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Quick update: tests passed.",
400">class="text-emerald-400">"content_type": 400">class="text-emerald-400">"text",
400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T15:12:00.000Z",
400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T15:12:00.000Z"
},
400">class="text-emerald-400">"meta": {
400">class="text-emerald-400">"timestamp": 400">class="text-emerald-400">"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
400">curl -X 400">GET 400">class="text-emerald-400">"https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/history?channel_id=550e8400-e29b-41d4-a716-446655440000&limit=25&offset=0" \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN"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">"7c9e6679-7425-40de-944b-e07fc1f90ae7",
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Can you analyze the Q1 marketing data?",
400">class="text-emerald-400">"content_type": 400">class="text-emerald-400">"text",
400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"display_name": 400">class="text-emerald-400">"Matty Squarzoni",
400">class="text-emerald-400">"avatar_url": 400">class="text-emerald-400">"https:400">class="text-zinc-500">//storage.lvng.ai/avatars/a0eebc99.jpg",
400">class="text-emerald-400">"reactions": [],
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:30:00.000Z",
400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T14:30:00.000Z"
}
],
400">class="text-emerald-400">"meta": {
400">class="text-emerald-400">"total": 142,
400">class="text-emerald-400">"page": 1,
400">class="text-emerald-400">"limit": 25,
400">class="text-emerald-400">"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
400">curl -X 400">GET 400">class="text-emerald-400">"https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/search?query=deployment&channel_id=550e8400-e29b-41d4-a716-446655440000" \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN"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">"7c9e6679-7425-40de-944b-e07fc1f90ae7",
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Deploy the staging environment and run integration tests.",
400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T15:10:22.000Z"
}
],
400">class="text-emerald-400">"meta": {
400">class="text-emerald-400">"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
400">curl -X 400">GET https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN"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">"7c9e6679-7425-40de-944b-e07fc1f90ae7",
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Can you analyze the Q1 marketing data?",
400">class="text-emerald-400">"content_type": 400">class="text-emerald-400">"text",
400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"parent_message_id": null,
400">class="text-emerald-400">"metadata": {},
400">class="text-emerald-400">"reaction_count": 3,
400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T14:30:00.000Z",
400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"2026-03-19T14:30:00.000Z"
},
400">class="text-emerald-400">"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
400">curl -X 400">PUT https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN" \
-H 400">class="text-emerald-400">"Content-Type: application/json" \
-d '{
400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Can you analyze the Q1 and Q2 marketing data?"
}'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">"7c9e6679-7425-40de-944b-e07fc1f90ae7",
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Can you analyze the Q1 and Q2 marketing data?",
400">class="text-emerald-400">"content_type": 400">class="text-emerald-400">"text",
400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"metadata": {},
400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T14:30:00.000Z",
400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"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
400">curl -X 400">DELETE 400">class="text-emerald-400">"https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/7c9e6679-7425-40de-944b-e07fc1f90ae7?user_id=a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11" \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN"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">"7c9e6679-7425-40de-944b-e07fc1f90ae7",
400">class="text-emerald-400">"deleted_at": 400">class="text-emerald-400">"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
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/7c9e6679-7425-40de-944b-e07fc1f90ae7/pin \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN"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">"7c9e6679-7425-40de-944b-e07fc1f90ae7",
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Can you analyze the Q1 marketing data?",
400">class="text-emerald-400">"metadata": {
400">class="text-emerald-400">"pinned": true,
400">class="text-emerald-400">"pinned_by": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"pinned_at": 400">class="text-emerald-400">"2026-03-19T16:05:00.000Z"
},
400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"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
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/7c9e6679-7425-40de-944b-e07fc1f90ae7/react \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN" \
-H 400">class="text-emerald-400">"Content-Type: application/json" \
-d '{
400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"emoji": 400">class="text-emerald-400">"thumbsup"
}'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">"d4735e3a-265e-16d0-8b4b-b7bfa8e5b9e0",
400">class="text-emerald-400">"message_id": 400">class="text-emerald-400">"7c9e6679-7425-40de-944b-e07fc1f90ae7",
400">class="text-emerald-400">"user_id": 400">class="text-emerald-400">"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
400">class="text-emerald-400">"emoji": 400">class="text-emerald-400">"thumbsup",
400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T16:10:00.000Z"
},
400">class="text-emerald-400">"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
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/7c9e6679-7425-40de-944b-e07fc1f90ae7/thread \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN" \
-H 400">class="text-emerald-400">"Content-Type: application/json" \
-d '{
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Here is the Q1 analysis you requested.",
400">class="text-emerald-400">"ai_twin_id": 400">class="text-emerald-400">"b5b2c3d4-e5f6-7890-abcd-ef1234567890"
}'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">"e3b0c442-98fc-1c14-b39f-27bd3e8cd9a1",
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"content": 400">class="text-emerald-400">"Here is the Q1 analysis you requested.",
400">class="text-emerald-400">"content_type": 400">class="text-emerald-400">"text",
400">class="text-emerald-400">"user_id": null,
400">class="text-emerald-400">"ai_twin_id": 400">class="text-emerald-400">"b5b2c3d4-e5f6-7890-abcd-ef1234567890",
400">class="text-emerald-400">"parent_message_id": 400">class="text-emerald-400">"7c9e6679-7425-40de-944b-e07fc1f90ae7",
400">class="text-emerald-400">"metadata": {},
400">class="text-emerald-400">"created_at": 400">class="text-emerald-400">"2026-03-19T16:15:00.000Z",
400">class="text-emerald-400">"updated_at": 400">class="text-emerald-400">"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
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/upload \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN" \
-F 400">class="text-emerald-400">"files=@report.pdf" \
-F 400">class="text-emerald-400">"files=@chart.png" \
-F 400">class="text-emerald-400">"conversation_id=550e8400-e29b-41d4-a716-446655440000"Response 200
{
400">class="text-emerald-400">"success": true,
400">class="text-emerald-400">"data": {
400">class="text-emerald-400">"files": [
{
400">class="text-emerald-400">"name": 400">class="text-emerald-400">"report.pdf",
400">class="text-emerald-400">"url": 400">class="text-emerald-400">"https:400">class="text-zinc-500">//storage.lvng.ai/uploads/550e8400/report.pdf",
400">class="text-emerald-400">"size": 245760,
400">class="text-emerald-400">"400">type": 400">class="text-emerald-400">"application/pdf"
},
{
400">class="text-emerald-400">"name": 400">class="text-emerald-400">"chart.png",
400">class="text-emerald-400">"url": 400">class="text-emerald-400">"https:400">class="text-zinc-500">//storage.lvng.ai/uploads/550e8400/chart.png",
400">class="text-emerald-400">"size": 89200,
400">class="text-emerald-400">"400">type": 400">class="text-emerald-400">"image/png"
}
],
400">class="text-emerald-400">"conversation_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"conversation_type": 400">class="text-emerald-400">"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
400">curl -X 400">POST https:400">class="text-zinc-500">//api.lvng.ai/api/v2/messages/summarize \
-H 400">class="text-emerald-400">"Authorization: Bearer YOUR_JWT_TOKEN" \
-H 400">class="text-emerald-400">"Content-Type: application/json" \
-d '{
400">class="text-emerald-400">"channel_id": 400">class="text-emerald-400">"550e8400-e29b-41d4-a716-446655440000",
400">class="text-emerald-400">"messageCount": 50
}'Response 200
{
400">class="text-emerald-400">"success": true,
400">class="text-emerald-400">"data": {
400">class="text-emerald-400">"summary": 400">class="text-emerald-400">"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.",
400">class="text-emerald-400">"messageCount": 47,
400">class="text-emerald-400">"timeRange": {
400">class="text-emerald-400">"400">from": 400">class="text-emerald-400">"2026-03-18T09:00:00.000Z",
400">class="text-emerald-400">"to": 400">class="text-emerald-400">"2026-03-19T15:12:45.000Z"
}
}
}