Covers 100% of the non E2EE Matrix API endpoints!
Lightweight Matrix protocol client. Pure ES module, no dependencies.
npm install @litruv/mxjs-lite
or import directly into your website
<script src="https://unpkg.com/@litruv/mxjs-lite/dist/mxjs-lite.min.js"></script>import MxjsClient, { ClientEvents } from '@litruv/mxjs-lite';
const mx = new MxjsClient({ homeserver: 'https://matrix.org' });
await mx.login('alice', 's3cr3t');
await mx.joinRoom('#general:matrix.org');
mx.on(ClientEvents.Ready, () => console.log('Ready!'));
mx.on(ClientEvents.MessageCreate, ({ roomId, event }) => {
console.log(`[${roomId}] ${event.sender}: ${event.content?.body}`);
});
mx.startSync();new MxjsClient([options])
| Parameter | Type | Default | Description |
|---|---|---|---|
options.homeserver |
string |
"https://matrix.org" |
Homeserver base URL |
options.publicReadToken |
string | null |
null |
Token for unauthenticated public reads |
| Name |
|---|
.homeserver |
.accessToken |
.userId |
.publicReadToken |
| Method |
|---|
.register() |
.registerGuest() |
.login() |
.logout() |
.deactivateAccount() |
.changePassword() |
| Method |
|---|
.getProfile() |
.setDisplayName() |
.setAvatarUrl() |
.mxcToHttp() |
| Method |
|---|
.resolveRoomAlias() |
.joinRoom() |
.createRoom() |
.leaveRoom() |
.inviteUser() |
.kickUser() |
.banUser() |
.unbanUser() |
.getRoomMembers() |
| Method |
|---|
.sendMessage() |
.sendImage() |
.editMessage() |
.redactEvent() |
.reactToMessage() |
.removeReaction() |
.getMessages() |
.sendTyping() |
.sendReadReceipt() |
| Method |
|---|
.sendStateEvent() |
.setRoomName() |
.setRoomTopic() |
.setRoomAvatar() |
.getRoomState() |
.getRoomName() |
.getRoomTopic() |
.getRoomAllState() |
| Method |
|---|
.uploadMedia() |
.sync() |
.processSyncData() |
.startSync() |
.stopSync() |
| Method |
|---|
.on() |
.off() |
.emit() |
ClientEvents |
accountDataUpdate
canonicalAliasUpdate
connect
disconnect
inviteReceive
memberUpdate
mention
messageCreate
messageDelete
messageUpdate
powerLevelUpdate
presenceUpdate
reactionAdd
reactionRemove
ready
receiptUpdate
roomAccountDataUpdate
roomAvatarUpdate
roomJoin
roomLeave
roomNameUpdate
roomTopicUpdate
spaceChildAdd
spaceChildRemove
syncComplete
syncError
typingStart
threadReply
typingEnd
| Method |
|---|
.isMention() |
.getEventRelation() |
.isEditEvent() |
.isReactionEvent() |
.getEditedBody() |
.getPrevContent() |
.getMembershipChange() |
.isImageMessage() |
.hasFormattedBody() |
.extractLocalpart() |
| Method |
|---|
.buildMentionHtml() |
.sanitizeHtml() |
| Method |
|---|
.fetchPublicLastMessage() |
.fetchPublicPresence() |
| Method |
|---|
.createSpace() |
.addSpaceChild() |
.removeSpaceChild() |
.setSpaceParent() |
.removeSpaceParent() |
.getSpaceChildren() |
.isSpaceRoom() |
| Method |
|---|
.sendThreadReply() |
.sendThreadReplyTo() |
.getThreadEvents() |
.getRoomThreads() |
.isThreadEvent() |
.getThreadRoot() |
.isThreadFallback() |
| Method |
|---|
.api() |
Type: string
The base URL of the Matrix homeserver used for all API requests.
Type: string | null
The access token for the currently authenticated session. Set automatically by login, register, and registerGuest. Cleared by logout.
Type: string | null
The Matrix user ID (e.g. @alice:matrix.org) of the currently authenticated user. Set alongside accessToken.
Type: string | null
An access token used for unauthenticated public read operations via fetchPublicLastMessage and fetchPublicPresence.
Registers a new account on the homeserver using the m.login.dummy UIAA flow.
| Parameter | Type | Description |
|---|---|---|
username |
string |
Desired username |
password |
string |
Account password |
Returns: Promise<{ accessToken: string, userId: string } | null>
const session = await mx.register('alice', 's3cr3t');Registers an anonymous guest account. No credentials required.
Returns: Promise<{ accessToken: string, userId: string } | null>
const session = await mx.registerGuest();Authenticates with an existing account using m.login.password.
| Parameter | Type | Description |
|---|---|---|
username |
string |
Account username |
password |
string |
Account password |
Returns: Promise<{ accessToken: string, userId: string } | null>
const session = await mx.login('alice', 's3cr3t');Clears the local accessToken and userId. Does not call the homeserver logout endpoint.
Returns: void
Permanently deactivates the current user's account via UIAA confirmation.
| Parameter | Type | Description |
|---|---|---|
password |
string |
Current account password |
Returns: Promise<boolean>
Changes the current user's password via UIAA confirmation.
| Parameter | Type | Description |
|---|---|---|
oldPassword |
string |
Current password |
newPassword |
string |
New password |
Returns: Promise<boolean>
Fetches the display name and avatar URL for a user.
| Parameter | Type | Default | Description |
|---|---|---|---|
userId |
string |
this.userId |
Target user ID |
Returns: Promise<{ displayName: string | null, avatarUrl: string | null } | null>
const profile = await mx.getProfile('@alice:matrix.org');
console.log(profile.displayName);Sets the display name for the current user.
| Parameter | Type | Description |
|---|---|---|
displayName |
string |
New display name |
Returns: Promise<boolean>
Sets the avatar for the current user.
| Parameter | Type | Description |
|---|---|---|
avatarUrl |
string |
An mxc:// URI |
Returns: Promise<boolean>
Converts an mxc:// URI to a full HTTP download URL on the current homeserver.
| Parameter | Type | Description |
|---|---|---|
mxcUrl |
string |
An mxc:// URI |
Returns: string | null — null if the input is not a valid mxc:// URI.
const url = mx.mxcToHttp('mxc://matrix.org/abc123');Resolves a room alias to its internal room ID.
| Parameter | Type | Description |
|---|---|---|
roomAlias |
string |
e.g. #general:matrix.org |
Returns: Promise<string | null>
const roomId = await mx.resolveRoomAlias('#general:matrix.org');Joins a room by room ID or alias.
| Parameter | Type | Description |
|---|---|---|
roomIdOrAlias |
string |
Room ID or alias |
Returns: Promise<{ roomId: string } | null>
Creates a new room. The options object is passed directly to the Matrix POST /createRoom endpoint.
| Parameter | Type | Description |
|---|---|---|
options |
Object |
Matrix room creation options |
Returns: Promise<{ roomId: string } | null>
const { roomId } = await mx.createRoom({ name: 'My Room', preset: 'public_chat' });Leaves a room.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
Returns: Promise<boolean>
Invites a user to a room.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
userId |
string |
User to invite |
Returns: Promise<boolean>
Kicks a user from a room.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
userId |
string |
User to kick | |
reason |
string |
"" |
Optional reason |
Returns: Promise<boolean>
Bans a user from a room.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
userId |
string |
User to ban | |
reason |
string |
"" |
Optional reason |
Returns: Promise<boolean>
Unbans a previously banned user.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
userId |
string |
User to unban |
Returns: Promise<boolean>
Returns an array of currently joined members for a room.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
Returns: Promise<Array<{ userId: string, displayName: string }> | null>
Sends a plain text message. Optionally includes an HTML-formatted body.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
message |
string |
Plain text body | |
formattedBody |
string | null |
null |
HTML body (org.matrix.custom.html) |
Returns: Promise<{ eventId: string } | null>
await mx.sendMessage(roomId, 'Hello!');
await mx.sendMessage(roomId, 'Hello!', '<b>Hello!</b>');Sends an image message.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
url |
string |
An mxc:// URI |
|
body |
string |
"Image" |
Alt text / fallback label |
info |
Object |
{} |
Image metadata (e.g. w, h, mimetype) |
Returns: Promise<{ eventId: string } | null>
Edits a previously sent message using the m.replace relation.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
eventId |
string |
Event ID of the original message |
newMessage |
string |
Replacement text body |
Returns: Promise<{ eventId: string } | null>
Redacts (deletes) a room event.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
eventId |
string |
Event to redact | |
reason |
string |
"" |
Optional reason |
Returns: Promise<{ eventId: string } | null>
Sends a reaction annotation (m.annotation) to an event.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
eventId |
string |
Event to react to |
reaction |
string |
Reaction key, typically an emoji |
Returns: Promise<{ eventId: string } | null>
Removes a reaction by redacting its event.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
reactionEventId |
string |
Event ID of the reaction |
Returns: Promise<boolean>
Fetches a page of events from a room's timeline.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
options.from |
string | null |
null |
Pagination token |
options.limit |
number |
50 |
Maximum events to return |
options.dir |
string |
"b" |
Direction: "b" (backwards) or "f" (forwards) |
Returns: Promise<{ messages: Object[], start: string, end: string } | null>
const page = await mx.getMessages(roomId, { limit: 30 });
for (const event of page.messages) { /* ... */ }
// Next page
const nextPage = await mx.getMessages(roomId, { from: page.end });Sends a typing notification to a room.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
typing |
boolean |
true to start, false to stop |
|
timeout |
number |
30000 |
Active duration in ms |
Returns: Promise<boolean>
Marks an event as read by sending an m.read receipt.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
eventId |
string |
Event ID to mark as read |
Returns: Promise<boolean>
Sends a raw state event to a room.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
type |
string |
Matrix event type | |
content |
Object |
Event content | |
stateKey |
string |
"" |
Optional state key |
Returns: Promise<{ eventId: string } | null>
Sets the name of a room (m.room.name).
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
name |
string |
New room name |
Returns: Promise<{ eventId: string } | null>
Sets the topic of a room (m.room.topic).
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
topic |
string |
New room topic |
Returns: Promise<{ eventId: string } | null>
Sets the avatar of a room (m.room.avatar).
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
url |
string |
An mxc:// URI |
Returns: Promise<{ eventId: string } | null>
Fetches the content of a specific state event.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
type |
string |
Matrix state event type | |
stateKey |
string |
"" |
Optional state key |
Returns: Promise<Object | null>
Gets the current name of a room.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
Returns: Promise<string | null>
Gets the current topic of a room.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
Returns: Promise<string | null>
Fetches a snapshot of common room state in a single call.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
Room ID |
Returns:
Promise<{
name: string | null,
topic: string | null,
avatarUrl: string | null,
canonicalAlias: string | null,
powerLevels: Object | null,
members: Array<{
userId: string,
displayName: string | null,
membership: string
}>
} | null>
Uploads binary data to the homeserver's media repository. Tries the v3 endpoint, falls back to r0.
| Parameter | Type | Default | Description |
|---|---|---|---|
data |
Blob | ArrayBuffer | FormData |
Media data | |
contentType |
string |
MIME type, e.g. "image/png" |
|
filename |
string |
"" |
Optional filename hint |
Returns: Promise<{ contentUri: string } | null> — contentUri is an mxc:// URI.
const { contentUri } = await mx.uploadMedia(blob, 'image/jpeg', 'photo.jpg');
await mx.sendImage(roomId, contentUri);Performs a single /sync poll to retrieve new events.
| Parameter | Type | Default | Description |
|---|---|---|---|
since |
string | null |
null |
Sync token from a previous response |
timeout |
number |
0 |
Long-poll timeout in ms |
Returns: Promise<Object | null> — Raw Matrix sync response.
let since = null;
while (true) {
const data = await mx.sync(since, 30000);
mx.processSyncData(data);
since = data?.next_batch ?? since;
}Processes a raw sync response and emits structured events for all new activity. Called automatically by startSync(), or call manually after each .sync() poll. Emits roomJoin, roomLeave, inviteReceive, messageCreate, messageUpdate, messageDelete, reactionAdd, reactionRemove, memberUpdate, typingStart, typingEnd, receiptUpdate, roomNameUpdate, roomTopicUpdate, roomAvatarUpdate, powerLevelUpdate, canonicalAliasUpdate, presenceUpdate, accountDataUpdate, roomAccountDataUpdate, spaceChildAdd, spaceChildRemove, threadReply — see Event Details for payload shapes.
| Parameter | Type | Description |
|---|---|---|
data |
Object |
Sync response returned by .sync() |
Returns: void
let since = null;
while (true) {
const data = await mx.sync(since, 30000);
mx.processSyncData(data);
since = data?.next_batch ?? since;
}Prefer
startSync()for automatic loop management.
Starts the automatic long-poll sync loop. On first call, performs an initial drain sync (timeout=0) to consume existing events and populate rooms, then emits ready. Subsequent polls use timeout to keep the connection open until the server has new data.
| Parameter | Type | Default | Description |
|---|---|---|---|
timeout |
number |
30000 |
Long-poll timeout per request in ms |
since |
string|null |
null |
Optional initial sync token. If provided, the drain sync is skipped and polling begins immediately from this token. |
Returns: Promise<void>
await mx.login('alice', 's3cr3t');
mx.on(ClientEvents.Ready, () => console.log('Ready!'));
mx.startSync(30000);Stops the automatic sync loop. The current in-flight request will complete before the loop exits.
Returns: void
mx.stopSync();Registers a listener for a named event.
| Parameter | Type | Description |
|---|---|---|
event |
string |
Event name |
fn |
function |
Callback |
Returns: this
mx.on('mention', (event) => alert(`Mentioned in ${event.room_id}`));Removes a listener, or all listeners for an event if fn is omitted.
| Parameter | Type | Description |
|---|---|---|
event |
string |
Event name |
fn |
function (optional) |
Specific listener to remove |
Returns: this
Emits a named event, invoking all registered listeners.
| Parameter | Type | Description |
|---|---|---|
event |
string |
Event name |
...args |
any |
Arguments forwarded to each listener |
Returns: void
A string constants object for all events emitted by the client. Use these with .on() instead of raw strings to avoid typos and benefit from editor autocompletion.
import MxjsClient, { ClientEvents } from '@litruv/mxjs-lite';
mx.on(ClientEvents.MessageCreate, ({ roomId, event }) => { /* ... */ });
mx.on(ClientEvents.Ready, () => { /* ... */ });| Constant | Value |
|---|---|
ClientEvents.Connect |
'connect' |
ClientEvents.Disconnect |
'disconnect' |
ClientEvents.Ready |
'ready' |
ClientEvents.MessageCreate |
'messageCreate' |
ClientEvents.MessageUpdate |
'messageUpdate' |
ClientEvents.MessageDelete |
'messageDelete' |
ClientEvents.ReactionAdd |
'reactionAdd' |
ClientEvents.ReactionRemove |
'reactionRemove' |
ClientEvents.RoomJoin |
'roomJoin' |
ClientEvents.RoomLeave |
'roomLeave' |
ClientEvents.InviteReceive |
'inviteReceive' |
ClientEvents.MemberUpdate |
'memberUpdate' |
ClientEvents.RoomNameUpdate |
'roomNameUpdate' |
ClientEvents.RoomTopicUpdate |
'roomTopicUpdate' |
ClientEvents.RoomAvatarUpdate |
'roomAvatarUpdate' |
ClientEvents.TypingStart |
'typingStart' |
ClientEvents.TypingEnd |
'typingEnd' |
ClientEvents.PresenceUpdate |
'presenceUpdate' |
ClientEvents.ReceiptUpdate |
'receiptUpdate' |
ClientEvents.AccountDataUpdate |
'accountDataUpdate' |
ClientEvents.RoomAccountDataUpdate |
'roomAccountDataUpdate' |
ClientEvents.SyncComplete |
'syncComplete' |
ClientEvents.SyncError |
'syncError' |
ClientEvents.PowerLevelUpdate |
'powerLevelUpdate' |
ClientEvents.CanonicalAliasUpdate |
'canonicalAliasUpdate' |
ClientEvents.SpaceChildAdd |
'spaceChildAdd' |
ClientEvents.SpaceChildRemove |
'spaceChildRemove' |
ClientEvents.ThreadReply |
'threadReply' |
Returns true if the event's body or formatted body contains a reference to userId and was not sent by userId.
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
userId |
string |
User ID to check for |
Returns: boolean
Returns the m.relates_to object from an event's content, or null.
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: Object | null
Returns true if the event is a message edit (m.replace relation).
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: boolean
Returns true if the event is a reaction annotation (m.annotation).
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: boolean
Extracts the text body from an edit event's m.new_content, falling back to the regular body.
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: string | null
Returns unsigned.prev_content from a state event, or null.
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: Object | null
Interprets an m.room.member event and returns a structured summary of the change.
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix m.room.member event |
Returns:
{
type: "join" | "rename" | "leave" | "kick" | "ban" | "unknown",
userId: string,
displayName: string | null,
prevDisplayName: string | null,
kicker: string | null
} | null
Returns null for non-member events or no meaningful change.
Returns true if the event is a message of type m.image.
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: boolean
Returns true if the event has an org.matrix.custom.html formatted body.
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: boolean
Extracts the localpart from a Matrix user ID (the segment before the :).
| Parameter | Type | Description |
|---|---|---|
userId |
string |
e.g. @alice:matrix.org |
Returns: string — The localpart (e.g. alice), or "?" on failure.
Scans plain text for @user:server patterns and wraps each match in an anchor link pointing to matrix.to.
| Parameter | Type | Description |
|---|---|---|
text |
string |
Plain text potentially containing Matrix user IDs |
getDisplayName |
function(userId): string |
Callback to resolve a user ID to a display name |
Returns: string | null — HTML string with mentions linked, or null if no mentions were found.
const html = mx.buildMentionHtml('cc @alice:matrix.org', (id) => members[id] ?? id);Sanitizes an HTML string against a safe allowlist of tags. Matrix mention links (<a href="https://matrix.to/#/@...">) are converted to <span class="mention"> elements.
Allowed tags: a, b, strong, i, em, code, del, s, u, span, br.
| Parameter | Type | Description |
|---|---|---|
html |
string |
Raw HTML to sanitize |
Returns: string
Requires
DOMParser(browser environment). In Node, returns the input unchanged.
Fetches the most recent text message from a public room without authentication. Requires publicReadToken to be set.
| Parameter | Type | Description |
|---|---|---|
roomAlias |
string |
e.g. #general:matrix.org |
Returns: Promise<{ sender: string, body: string, timestamp: number } | null>
const mx = new MxjsClient({ homeserver: 'https://matrix.org', publicReadToken: 'tok' });
const msg = await mx.fetchPublicLastMessage('#general:matrix.org');
console.log(`${msg.sender}: ${msg.body}`);Fetches the presence status for a user without authentication. Requires publicReadToken to be set.
| Parameter | Type | Description |
|---|---|---|
userId |
string |
e.g. @alice:matrix.org |
Returns: Promise<{ presence: string, lastActive: number } | null>
Creates a new space room. Sets creation_content.type to m.space and defaults events_default power level to 100 (preventing spam from non-admin members).
| Parameter | Type | Default | Description |
|---|---|---|---|
name |
string |
Display name for the space | |
options |
Object |
{} |
Additional room creation options (e.g. topic, visibility, preset) |
Returns: Promise<{ roomId: string } | null>
const { roomId } = await mx.createSpace('My Community', { visibility: 'public' });Adds a child room or subspace to a space by sending an m.space.child state event.
| Parameter | Type | Default | Description |
|---|---|---|---|
spaceId |
string |
Room ID of the space | |
childRoomId |
string |
Room ID of the child to add | |
via |
string[] |
Candidate servers for joining the child room | |
options.order |
string |
Lexicographic sort key for siblings | |
options.suggested |
boolean |
Whether to mark the child as suggested |
Returns: Promise<{ eventId: string } | null>
Removes a child from a space by sending an empty m.space.child state event.
| Parameter | Type | Description |
|---|---|---|
spaceId |
string |
Room ID of the space |
childRoomId |
string |
Room ID of the child to remove |
Returns: Promise<{ eventId: string } | null>
Declares a room's parent space via an m.space.parent state event.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room that will gain the parent link | |
spaceId |
string |
Room ID of the parent space | |
via |
string[] |
Candidate servers for joining the parent | |
canonical |
boolean |
false |
Whether this is the primary parent for the room |
Returns: Promise<{ eventId: string } | null>
Removes a parent declaration by sending an empty m.space.parent state event.
| Parameter | Type | Description |
|---|---|---|
roomId |
string |
The child room |
spaceId |
string |
Room ID of the parent to remove |
Returns: Promise<{ eventId: string } | null>
Returns all current children of a space. Fetches full room state and filters for valid m.space.child events (those with a non-empty via array).
| Parameter | Type | Description |
|---|---|---|
spaceId |
string |
Room ID of the space |
Returns:
Promise<Array<{
roomId: string,
via: string[],
order: string | null,
suggested: boolean
}> | null>
const children = await mx.getSpaceChildren(spaceRoomId);
for (const { roomId, suggested } of children) {
console.log(roomId, suggested ? '(suggested)' : '');
}Returns true if the given m.room.create event content represents a space room.
| Parameter | Type | Description |
|---|---|---|
createContent |
Object |
Content of the room's m.room.create event |
Returns: boolean
Sends a reply into a thread. Includes a fallback m.in_reply_to pointing to the thread root for clients that do not support threads (per MSC3440 backwards-compatibility).
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
threadRootId |
string |
Event ID of the thread root message | |
message |
string |
Plain text body | |
formattedBody |
string|null |
null |
Optional HTML-formatted body |
Returns: Promise<{ eventId: string } | null>
await mx.sendThreadReply(roomId, rootEventId, 'My reply');Sends a rich reply within a thread, targeting a specific event. Sets is_falling_back: false so thread-aware clients render it as a genuine reply rather than a plain thread message.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
threadRootId |
string |
Event ID of the thread root | |
replyToEventId |
string |
Event ID being directly replied to | |
message |
string |
Plain text body | |
formattedBody |
string|null |
null |
Optional HTML-formatted body |
Returns: Promise<{ eventId: string } | null>
Fetches events belonging to a thread via the Matrix /relations API.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
Room ID | |
threadRootId |
string |
Event ID of the thread root | |
options.from |
string |
Pagination token | |
options.limit |
number |
50 |
Maximum events to return |
options.dir |
string |
"b" |
Direction: "b" or "f" |
Returns: Promise<{ events: Object[], nextBatch: string | null } | null>
const thread = await mx.getThreadEvents(roomId, rootEventId, { limit: 30 });
for (const event of thread.events) { /* ... */ }Returns true if the event is a thread reply (rel_type of m.thread).
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: boolean
Returns the event ID of the thread root this event belongs to, or null.
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: string | null
Fetches all thread root events in a room via GET /_matrix/client/v1/rooms/{roomId}/threads (MSC3856 / Matrix v1.4). Returns paginated thread roots.
| Parameter | Type | Default | Description |
|---|---|---|---|
roomId |
string |
The room to list threads from | |
options.include |
'all'|'participated' |
'all' |
'all' returns every thread; 'participated' returns only threads the authenticated user contributed to |
options.from |
string |
Pagination token from a previous nextBatch |
|
options.limit |
number |
Maximum number of thread roots to return |
Returns: Promise<{threads: Object[], nextBatch: string|null}|null>
Returns true if the m.in_reply_to on a thread event is a backwards-compatibility fallback (is_falling_back: true) rather than a genuine reply.
| Parameter | Type | Description |
|---|---|---|
event |
Object |
A Matrix room event |
Returns: boolean
Makes a raw request to the Matrix Client-Server API at /_matrix/client/r0.
| Parameter | Type | Default | Description |
|---|---|---|---|
endpoint |
string |
Path relative to /_matrix/client/r0 |
|
method |
string |
"GET" |
HTTP method |
body |
Object | null |
null |
Request body, serialized as JSON |
accessToken |
string | null |
this.accessToken |
Bearer token override |
Returns: Promise<Object> — Parsed JSON response.
Automatically retries once if the server returns M_LIMIT_EXCEEDED, waiting the requested retry_after_ms.
Emitted after a successful login, register, or registerGuest call.
| Property | Type | Description |
|---|---|---|
accessToken |
string |
The session access token |
userId |
string |
The authenticated user's ID |
mx.on('connect', ({ userId }) => {
console.log(`Signed in as ${userId}`);
});Emitted after logout is called. No payload.
mx.on('disconnect', () => {
console.log('Signed out');
});Emitted by processSyncData when a message is edited.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
edits |
string |
Event ID of the original message being edited |
newBody |
string |
The new text content |
event |
Object |
The raw Matrix edit event |
mx.on(ClientEvents.MessageUpdate, ({ roomId, edits, newBody }) => {
console.log(`Message ${edits} edited to: ${newBody}`);
});Emitted by processSyncData when the client receives a room invitation.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room the invite is for |
mx.on(ClientEvents.InviteReceive, ({ roomId }) => {
console.log(`Invited to ${roomId}`);
});Emitted by processSyncData for each m.room.member event in the timeline. change is the object returned by getMembershipChange. This includes joins, leaves, kicks, bans, and display name changes. For display name changes, change.type will be "rename".
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
change |
Object |
Parsed membership change (see getMembershipChange) |
event |
Object |
The raw Matrix event |
mx.on(ClientEvents.MemberUpdate, ({ roomId, change }) => {
if (change.type === 'rename') {
console.log(`${change.userId} changed name from ${change.prevDisplayName} to ${change.displayName}`);
} else {
console.log(`[${roomId}] ${change.userId} — ${change.type}`);
}
});Emitted when an incoming message event contains a reference to the current user's ID. This event is not emitted by processSyncData; emit it manually inside your messageCreate handler using isMention.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room the mention occurred in |
event |
Object |
The raw Matrix room event |
room |
Object |
The room object from your local state |
mx.on(ClientEvents.MessageCreate, ({ roomId, event }) => {
if (mx.isMention(event, mx.userId)) {
mx.emit('mention', { roomId, event, room: myRooms.get(roomId) });
}
});
mx.on('mention', ({ roomId, event }) => {
console.log(`Mentioned in ${roomId} by ${event.sender}`);
});Emitted by processSyncData for each new (non-edit) m.room.message event.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
event |
Object |
The raw Matrix message event |
mx.on(ClientEvents.MessageCreate, ({ roomId, event }) => {
console.log(`[${roomId}] ${event.sender}: ${event.content.body}`);
});Emitted by processSyncData when an event is redacted (deleted).
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
redacts |
string |
Event ID of the message that was deleted |
event |
Object |
The raw Matrix redaction event |
mx.on(ClientEvents.MessageDelete, ({ roomId, redacts, event }) => {
console.log(`Message ${redacts} was deleted by ${event.sender}`);
});Emitted by processSyncData when a room's avatar is changed.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
avatarUrl |
string|null |
New avatar URL (mxc:// URI) |
prevAvatarUrl |
string|null |
Previous avatar URL |
event |
Object |
The raw Matrix state event |
mx.on(ClientEvents.RoomAvatarUpdate, ({ roomId, avatarUrl }) => {
console.log(`Room avatar changed to ${avatarUrl}`);
});Emitted by processSyncData the first time a room appears in a sync response (i.e. the client joined a new room or this is the first sync).
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the newly joined room |
mx.on(ClientEvents.RoomJoin, ({ roomId }) => {
console.log(`Joined room ${roomId}`);
});Emitted by processSyncData when the client has left or been removed from a room.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room that was left |
mx.on(ClientEvents.RoomLeave, ({ roomId }) => {
console.log(`Left room ${roomId}`);
});Emitted by processSyncData when a room's name is changed.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
name |
string|null |
New room name |
prevName |
string|null |
Previous room name |
event |
Object |
The raw Matrix state event |
mx.on(ClientEvents.RoomNameUpdate, ({ roomId, name, prevName }) => {
console.log(`Room name changed from "${prevName}" to "${name}"`);
});Emitted by processSyncData when a room's topic is changed.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
topic |
string|null |
New room topic |
prevTopic |
string|null |
Previous room topic |
event |
Object |
The raw Matrix state event |
mx.on(ClientEvents.RoomTopicUpdate, ({ roomId, topic, prevTopic }) => {
console.log(`Room topic changed from "${prevTopic}" to "${topic}"`);
});Emitted by processSyncData when users begin typing in a room. userIds contains only the users who started typing this cycle, not the full typing set.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
userIds |
string[] |
User IDs who started typing |
mx.on(ClientEvents.TypingStart, ({ roomId, userIds }) => {
console.log(`${userIds.join(', ')} started typing in ${roomId}`);
});Emitted by processSyncData when users stop typing in a room. userIds contains only the users who stopped typing this cycle.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
userIds |
string[] |
User IDs who stopped typing |
mx.on(ClientEvents.TypingEnd, ({ roomId, userIds }) => {
console.log(`${userIds.join(', ')} stopped typing in ${roomId}`);
});Emitted by startSync() once after the initial drain sync completes. All rooms the client belongs to will have already emitted roomJoin by the time ready fires. No payload.
mx.on(ClientEvents.Ready, () => {
console.log('Sync ready, rooms populated');
});Emitted by processSyncData when a reaction annotation is added to a message.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
reacts |
string |
Event ID of the message that was reacted to |
key |
string |
Reaction key, typically an emoji |
event |
Object |
The raw Matrix reaction event |
mx.on(ClientEvents.ReactionAdd, ({ roomId, reacts, key }) => {
console.log(`Reaction ${key} added to ${reacts} in ${roomId}`);
});Emitted by processSyncData when a reaction is removed (the reaction event is redacted). The library tracks seen reaction event IDs automatically so this fires instead of messageDelete for reaction removals.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
reacts |
string |
Event ID of the message the reaction was on |
key |
string |
The reaction key that was removed |
event |
Object |
The raw Matrix redaction event |
mx.on(ClientEvents.ReactionRemove, ({ roomId, reacts, key }) => {
console.log(`Reaction ${key} removed from ${reacts} in ${roomId}`);
});Emitted by processSyncData when a presence update is received for any user.
| Property | Type | Description |
|---|---|---|
userId |
string |
The user whose presence changed |
presence |
string|null |
e.g. "online", "offline", "unavailable" |
lastActiveAgo |
number|null |
Milliseconds since last active |
statusMsg |
string|null |
Optional status message |
currentlyActive |
boolean|null |
Whether the user is currently active |
mx.on(ClientEvents.PresenceUpdate, ({ userId, presence }) => {
console.log(`${userId} is now ${presence}`);
});Emitted by processSyncData when read receipts arrive for a room.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
receipts |
Array<{ eventId: string, read: string[] }> |
Array of receipt entries |
mx.on(ClientEvents.ReceiptUpdate, ({ roomId, receipts }) => {
for (const { eventId, read } of receipts) {
console.log(`${eventId} read by: ${read.join(', ')}`);
}
});Emitted by startSync() after every successful long-poll cycle. No payload.
mx.on(ClientEvents.SyncComplete, () => {
console.log('Sync cycle complete');
});Emitted by startSync() when a sync request fails. The loop retries after 5 seconds.
| Property | Type | Description |
|---|---|---|
error |
Error |
The caught error |
mx.on(ClientEvents.SyncError, ({ error }) => {
console.error('Sync failed:', error);
});Emitted by processSyncData when a room's power levels change (m.room.power_levels).
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
content |
Object |
New power levels content |
event |
Object |
The raw Matrix state event |
mx.on(ClientEvents.PowerLevelUpdate, ({ roomId, content }) => {
console.log(`Power levels updated in ${roomId}`);
});Emitted by processSyncData when a room's canonical alias changes (m.room.canonical_alias).
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
alias |
string|null |
New canonical alias, or null if removed |
event |
Object |
The raw Matrix state event |
mx.on(ClientEvents.CanonicalAliasUpdate, ({ roomId, alias }) => {
console.log(`Room ${roomId} canonical alias is now ${alias}`);
});Emitted by processSyncData when a global account data event is received.
| Property | Type | Description |
|---|---|---|
type |
string |
Matrix event type, e.g. "m.push_rules" |
content |
Object |
Event content |
mx.on(ClientEvents.AccountDataUpdate, ({ type, content }) => {
console.log(`Global account data updated: ${type}`);
});Emitted by processSyncData when a room-level account data event is received.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
type |
string |
Matrix event type, e.g. "m.fully_read" |
content |
Object |
Event content |
mx.on(ClientEvents.RoomAccountDataUpdate, ({ roomId, type, content }) => {
console.log(`Room ${roomId} account data updated: ${type}`);
});Emitted by processSyncData when a child room is added or updated in a space (m.space.child state event with a valid via array arrives in the timeline).
| Property | Type | Description |
|---|---|---|
roomId |
string |
Room ID of the space |
childRoomId |
string |
Room ID of the added/updated child |
via |
string[] |
Candidate servers for joining the child |
order |
string|null |
Sort order hint, or null if unset |
suggested |
boolean |
Whether the child is marked as suggested |
event |
Object |
The raw Matrix state event |
mx.on(ClientEvents.SpaceChildAdd, ({ roomId, childRoomId, suggested }) => {
console.log(`Space ${roomId} gained child ${childRoomId}${suggested ? ' (suggested)' : ''}`);
});Emitted by processSyncData when a child room is removed from a space (m.space.child with empty or missing via).
| Property | Type | Description |
|---|---|---|
roomId |
string |
Room ID of the space |
childRoomId |
string |
Room ID of the removed child |
event |
Object |
The raw Matrix state event |
mx.on(ClientEvents.SpaceChildRemove, ({ roomId, childRoomId }) => {
console.log(`Space ${roomId} removed child ${childRoomId}`);
});Emitted by processSyncData for every m.room.message that carries a rel_type of m.thread. Also fires as messageCreate simultaneously — listen to threadReply when you want thread-specific handling.
| Property | Type | Description |
|---|---|---|
roomId |
string |
ID of the room |
threadRootId |
string |
Event ID of the thread root message |
event |
Object |
The raw Matrix message event |
mx.on(ClientEvents.ThreadReply, ({ roomId, threadRootId, event }) => {
console.log(`[${roomId}] thread reply to ${threadRootId}: ${event.content?.body}`);
});Check Matrix Client-Server API coverage:
npm testRuns all Matrix Client-Server API endpoint tests against a live homeserver (chat.ruv.wtf). Test accounts are created and removed automatically — no configuration needed. Results are saved to test/api-coverage-report.txt.
MIT