Skip to main content

Core SDK API Reference

The @chatsdk/core package provides the foundation for building chat applications.

ChatClient

The main entry point for the SDK.

Constructor

import { ChatClient } from '@chatsdk/core';

const client = new ChatClient(options: ChatClientOptions);

ChatClientOptions

PropertyTypeRequiredDefaultDescription
apiKeystringYes-Your API key
apiUrlstringNohttp://localhost:5500API server URL
wsUrlstringNows://localhost:8000/...WebSocket URL
debugbooleanNofalseEnable debug logging
enableOfflineSupportbooleanNotrueEnable offline queue
reconnectIntervalsnumber[]No[1000,2000,4000,8000,16000]Backoff intervals

Properties

user

get user(): User | null

Returns the currently connected user, or null if not connected.

state

get state(): ConnectionState

Returns the current connection state: 'connecting' | 'connected' | 'disconnected' | 'reconnecting'.

apiUrl

get apiUrl(): string

Returns the configured API URL.

Connection Methods

connectUser()

async connectUser(
user: ConnectUserOptions,
token: string
): Promise<User>

Connect a user to the chat service.

const user = await client.connectUser(
{ id: 'user-123', name: 'Alice', image: 'https://...' },
'jwt-token'
);

disconnect()

async disconnect(): Promise<void>

Disconnect from the chat service and clean up resources.

Event Methods

on()

on<K extends keyof EventMap>(
event: K,
callback: EventCallback<K>
): () => void

Subscribe to an event. Returns an unsubscribe function.

const unsub = client.on('message.new', ({ channelId, message }) => {
console.log('New message:', message.text);
});

// Later: unsubscribe
unsub();

once()

once<K extends keyof EventMap>(
event: K,
callback: EventCallback<K>
): () => void

Subscribe to an event once. Automatically unsubscribes after first emit.

off()

off<K extends keyof EventMap>(
event: K,
callback: EventCallback<K>
): void

Unsubscribe a specific callback from an event.

Channel Methods

queryChannels()

async queryChannels(options?: {
type?: string;
limit?: number;
offset?: number;
}): Promise<Channel[]>

Query channels the user is a member of.

const channels = await client.queryChannels({ limit: 20 });

getChannel()

async getChannel(channelId: string): Promise<Channel>

Get a specific channel by ID.

createChannel()

async createChannel(data: {
type?: string;
name?: string;
memberIds: string[];
}): Promise<Channel>

Create a new channel.

const channel = await client.createChannel({
name: 'Project Discussion',
memberIds: ['user-1', 'user-2'],
});

subscribeToChannel()

async subscribeToChannel(channelId: string): Promise<Subscription>

Subscribe to real-time updates for a channel.

unsubscribeFromChannel()

async unsubscribeFromChannel(channelId: string): Promise<void>

Unsubscribe from a channel.

Message Methods

queryMessages()

async queryMessages(
channelId: string,
options?: {
sinceSeq?: number;
limit?: number;
before?: string;
after?: string;
}
): Promise<{
messages: MessageWithSeq[];
maxSeq: number;
hasMore: boolean;
}>

Query messages in a channel.

const { messages, hasMore } = await client.queryMessages('channel-123', {
limit: 50,
});

sendMessage()

async sendMessage(
channelId: string,
data: {
text: string;
clientMsgId?: string;
attachments?: Attachment[];
parentId?: string;
}
): Promise<MessageWithSeq>

Send a message to a channel.

const message = await client.sendMessage('channel-123', {
text: 'Hello!',
attachments: [{ type: 'image', url: 'https://...' }],
});

updateMessage()

async updateMessage(
channelId: string,
messageId: string,
data: { text: string }
): Promise<MessageWithSeq>

Update a message.

deleteMessage()

async deleteMessage(
channelId: string,
messageId: string
): Promise<void>

Delete a message (soft delete).

Reaction Methods

addReaction()

async addReaction(
channelId: string,
messageId: string,
emoji: string
): Promise<void>

Add a reaction to a message.

await client.addReaction('channel-123', 'msg-456', '👍');

removeReaction()

async removeReaction(
channelId: string,
messageId: string,
emoji: string
): Promise<void>

Remove a reaction from a message.

Typing Methods

sendTypingStart()

async sendTypingStart(channelId: string): Promise<void>

Send a typing indicator.

sendTypingStop()

async sendTypingStop(channelId: string): Promise<void>

Stop the typing indicator.

Read State Methods

markRead()

async markRead(
channelId: string,
messageId?: string
): Promise<void>

Mark messages as read in a channel.

API Request Method

fetch()

async fetch<T>(
endpoint: string,
options?: RequestInit
): Promise<T>

Make an authenticated API request. Automatically adds authentication headers.

const data = await client.fetch<MyResponse>('/api/custom-endpoint', {
method: 'POST',
body: JSON.stringify({ key: 'value' }),
});

Events

Event Types

EventPayloadDescription
connection.connectingvoidConnecting to server
connection.connectedvoidSuccessfully connected
connection.disconnected{ reason: string }Disconnected
connection.error{ error: Error }Connection error
message.new{ channelId, message }New message received
message.updated{ channelId, message }Message updated
message.deleted{ channelId, messageId }Message deleted
typing.start{ channelId, user }User started typing
typing.stop{ channelId, user }User stopped typing
reaction.added{ channelId, messageId, reaction }Reaction added
reaction.removed{ channelId, messageId, reaction }Reaction removed
channel.updated{ channel }Channel updated
read.updated{ channelId, userId, lastReadSeq }Read state updated
presence.online{ userId }User came online
presence.offline{ userId, lastSeen }User went offline
sync.start{ channelId?, isInitial }Sync started
sync.progress{ channelId?, progress }Sync progress
sync.complete{ channelId?, messageCount }Sync complete
sync.error{ channelId?, error }Sync error

Types

User

interface User {
id: string;
name: string;
image?: string;
online?: boolean;
last_active?: string;
custom?: Record<string, unknown>;
}

Channel

interface Channel {
id: string;
cid: string;
type: 'messaging' | 'livestream' | 'team' | 'commerce';
name?: string;
image?: string;
member_count: number;
message_count?: number;
unread_count?: number;
last_message?: Message;
created_at: string;
updated_at?: string;
}

Message

interface Message {
id: string;
cid: string;
type: 'regular' | 'system' | 'error' | 'deleted';
text?: string;
user?: User;
attachments?: Attachment[];
reactions?: ReactionGroup[];
reply_count?: number;
parent_id?: string;
status?: 'sending' | 'sent' | 'delivered' | 'read' | 'failed';
created_at: string;
updated_at?: string;
}

MessageWithSeq

interface MessageWithSeq extends Message {
seq: number;
clientMsgId?: string;
}

Attachment

interface Attachment {
type: 'image' | 'video' | 'audio' | 'file' | 'giphy' | 'voicenote';
url?: string;
thumb_url?: string;
title?: string;
mime_type?: string;
file_size?: number;
width?: number;
height?: number;
}

Reaction

interface Reaction {
type: string;
user_id: string;
message_id: string;
created_at: string;
}

ReactionGroup

interface ReactionGroup {
type: string;
count: number;
own: boolean;
users: User[];
}

EventBus

Low-level event emitter used internally.

import { EventBus } from '@chatsdk/core';

const bus = new EventBus({ debug: true });

// Subscribe
const unsub = bus.on('message.new', (data) => { ... });

// Emit
bus.emit('message.new', { channelId: '...', message: { ... } });

// Wait for event
const data = await bus.waitFor('connection.connected', { timeout: 5000 });

MessageSyncer

Handles sequence-based message synchronization with gap detection.

import { MessageSyncer } from '@chatsdk/core';

const syncer = new MessageSyncer({
client,
eventBus,
storage, // SyncStorage implementation
batchSize: 100,
debug: true,
});

// Sync a channel
const { synced, gaps } = await syncer.syncChannel('channel-123');

// Handle incoming message (validates sequence)
await syncer.handleNewMessage('channel-123', message);

// Sync all channels
await syncer.syncAllChannels();