Skip to navigation

Chat & Messaging

1:1 DMs, group chat, reactions, and message history

Overview

The Chat resource provides real-time messaging with support for 1:1 direct messages, group conversations, message reactions, editing, threading, and read receipts.

All chat methods are available on r.chat.

Methods

MethodDescription
conversations(params?)List the authenticated user’s conversations.
conversation(id)Get a conversation by ID with member details.
communityConversation(communityId)Get a community’s conversation.
messages(conversationId, params?)List messages in a conversation (newest first).
send(input)Send a message to a conversation.
dm(input)Get or create a DM conversation with a user.
createGroup(input)Create a group conversation.
deleteConversation(id)Delete a conversation.
reactToMessage(messageId, input)React to a message (toggles on/off).
editMessage(messageId, input)Edit a message.
deleteMessage(messageId)Delete a message.
markAsRead(conversationId, input)Mark a conversation as read up to a message.
unreadCount(conversationId)Get unread message count for a conversation.

List conversations

const { data: conversations, meta } = await r.chat.conversations({ limit: 20 });
for (const conv of conversations) {
const names = conv.members.map((m) => m.name).join(', ');
const lastMsg = conv.last_message
? `${conv.last_message.sender_name}: ${conv.last_message.content.slice(0, 50)}`
: 'No messages';
console.log(`[${conv.type}] ${conv.name ?? names}`);
console.log(` Last: ${lastMsg}`);
}

Returns: PaginatedResponse<Conversation>

interface Conversation {
id: string;
type: string; // 'dm' | 'group' | 'community'
name: string | null; // null for DMs, set for groups
community_id: string | null;
members: ConversationMember[];
last_message: {
id: string;
content: string;
sender_name: string;
created_at: string;
} | null;
created_at: string;
}

Get a conversation

const { data: conv } = await r.chat.conversation('conv_123');
console.log(conv.type);
console.log(conv.name);
console.log(conv.members.map((m) => `@${m.username} (joined ${m.joined_at})`));

Get community conversation

const { data: conv } = await r.chat.communityConversation('comm_123');
console.log(conv.id);

Start a DM

Get or create a direct message conversation with another user. If a DM already exists, it returns the existing conversation.

const { data: dm } = await r.chat.dm({ user_id: 'user_456' });
console.log(dm.id); // Conversation ID
console.log(dm.type); // 'dm'
console.log(dm.created); // true if newly created, false if existing
// Send a message in the DM
await r.chat.send({
conversation_id: dm.id,
content: 'Hey! How is the project going?',
});

Create a group

const { data: group } = await r.chat.createGroup({
name: 'Project Alpha Team',
member_ids: ['user_1', 'user_2', 'user_3'],
});
console.log(group.id);
console.log(group.name); // 'Project Alpha Team'
console.log(group.members);

Send a message

const { data: msg } = await r.chat.send({
conversation_id: 'conv_123',
content: 'The deployment succeeded!',
});
console.log(msg.id);
console.log(msg.conversation_id);
console.log(msg.content);
console.log(msg.created_at);

Input fields:

FieldTypeRequiredDescription
conversation_idstringYesThe conversation to send the message in.
contentstringYesMessage content.
reply_to_idstring?NoReply to a specific message (creates a thread).

Reply to a message

await r.chat.send({
conversation_id: 'conv_123',
content: 'Thanks for the update!',
reply_to_id: 'msg_456',
});

List messages

Messages are returned newest first.

const { data: messages, meta } = await r.chat.messages('conv_123', {
limit: 50,
});
for (const msg of messages) {
console.log(`@${msg.sender.username}: ${msg.content}`);
if (msg.reactions.length > 0) {
console.log(` Reactions: ${msg.reactions.map((r) => r.type).join(' ')}`);
}
if (msg.reply_to_id) {
console.log(` (reply to ${msg.reply_to_id})`);
}
}

Returns: PaginatedResponse<Message>

interface Message {
id: string;
content: string;
sender: UserSummary;
reply_to_id: string | null;
media: MessageMedia[];
reactions: MessageReaction[];
created_at: string;
}
interface MessageReaction {
type: string;
user_id: string;
user_name: string;
}
interface MessageMedia {
id: string;
type: string;
url: string;
mime_type: string | null;
file_name: string | null;
}

React to a message

Reactions toggle: if you already reacted with the same type, it is removed. If you reacted with a different type, it is replaced.

const { data: result } = await r.chat.reactToMessage('msg_123', {
type: 'heart',
});
console.log(result.action); // 'added' or 'removed'
if (result.reaction) {
console.log(result.reaction.type); // 'heart'
}

Edit a message

Only the sender can edit their own messages.

const { data: edited } = await r.chat.editMessage('msg_123', {
content: 'Updated message content',
});
console.log(edited.content);

Delete a message

Only the sender can delete their own messages.

await r.chat.deleteMessage('msg_123');

Delete a conversation

Only the creator can delete a conversation.

await r.chat.deleteConversation('conv_123');

Read receipts

Mark as read

Mark a conversation as read up to a specific message:

await r.chat.markAsRead('conv_123', {
message_id: 'msg_789',
});

Get unread count

const { data: { unread_count } } = await r.chat.unreadCount('conv_123');
console.log(`${unread_count} unread messages`);

Full example

import { Recursiv } from '@recursiv/sdk';
const r = new Recursiv();
// 1. Start a DM
const { data: dm } = await r.chat.dm({ user_id: 'user_456' });
console.log(`DM conversation: ${dm.id} (new: ${dm.created})`);
// 2. Send messages
await r.chat.send({
conversation_id: dm.id,
content: 'Hey! Just pushed the new SDK release.',
});
await r.chat.send({
conversation_id: dm.id,
content: 'Can you review the breaking changes doc?',
});
// 3. Create a group for the team
const { data: group } = await r.chat.createGroup({
name: 'SDK Release Team',
member_ids: ['user_456', 'user_789'],
});
// 4. Send a message to the group
const { data: groupMsg } = await r.chat.send({
conversation_id: group.id,
content: 'SDK v2.0 is ready for release. Please review the changelog.',
});
// 5. React to a message
await r.chat.reactToMessage(groupMsg.id, { type: 'fire' });
// 6. List conversations
const { data: conversations } = await r.chat.conversations();
console.log(`You have ${conversations.length} conversations`);
// 7. Load message history
const { data: messages } = await r.chat.messages(group.id, { limit: 50 });
console.log(`${messages.length} messages in group`);
// 8. Mark as read
if (messages.length > 0) {
await r.chat.markAsRead(group.id, {
message_id: messages[0].id,
});
}
// 9. Check unread
const { data: { unread_count } } = await r.chat.unreadCount(group.id);
console.log(`${unread_count} unread`);