Message overview
Understand how MessageItem is created, sent, received, queried, and synchronized.
The WASM SDK represents each message as a MessageItem. Sending a message has two stages: first create a pending message object for the desired content, then send that object to an individual user or a group. A creation method does not send the message, and a successful send Promise does not mean that other clients have already received it.
Receiving new messages, loading history, searching, and managing messages are all scoped to a conversation. Store both conversationID and clientMsgID in a message list: the former identifies the conversation, while the latter locates and merges a specific message.
Message processing flow
| Stage | Primary operation | Description |
|---|---|---|
| Create | Call the corresponding create*Message() method | Returns a pending MessageItem; it does not write to the server or trigger a new-message event. |
| Send | Call sendMessage() or sendMessageNotOss() | For a one-to-one chat, set recvID; for a group chat, set groupID. Pass an empty string for the other target field. |
| Receive | Listen for new-message events | Determine the target conversation from the message routing fields, then merge idempotently by clientMsgID. |
| Query | Load history, search, or locate messages by ID | Queries return a snapshot at call time and do not trigger new-message events. |
| Update | Delete, revoke, modify, pin, or report message read status | Handle Promise results, related events, and any necessary re-query separately. |
For image, audio, video, and file messages created from a browser File, sendMessage() uses the SDK's built-in upload and send flow. If your application has already obtained a media URL from its upload service, create the message with the corresponding create*MessageByURL() method and send it with sendMessageNotOss() to avoid uploading the resource again.
MessageItem structure
Whether a message is created, sent, received, or queried, the message object in data is a MessageItem. Common fields include:
| Field | Type | Description |
|---|---|---|
clientMsgID | string | Stable client-side message ID used for list deduplication, state updates, queries, and history pagination cursors. |
serverMsgID | string | Server-side message ID. A pending or failed message may not yet have a valid value. |
sessionType | SessionType | Conversation type to which the message belongs, such as one-to-one or group chat. |
sendID | string | Sender's user ID. |
recvID | string | Recipient's user ID for a one-to-one message; usually empty for a group message. |
groupID | string | Group ID for a group message; usually empty for a one-to-one message. |
contentType | MessageType | Message content type, which determines which content field to read. |
createTime | number | Time when the message object was created. |
sendTime | number | Time when the message was sent, used for message ordering. |
seq | number | Server-side message sequence number. A message that has not been sent successfully may not have a usable sequence number. |
senderPlatformID | Platform | Client platform from which the message was sent. |
senderNickname | string | Snapshot of the sender's nickname. |
senderFaceUrl | string | Snapshot of the sender's avatar URL. |
status | MessageStatus | Current send state: sending, succeeded, or failed. |
isRead | boolean | Snapshot of the message's current read state. |
offlinePush | OfflinePush (optional) | Offline push configuration used when sending. |
ex | string (optional) | Extension string synchronized with the message. |
localEx | string (optional) | Extension string stored only on the current device. |
The message body is stored in the content field corresponding to contentType. Do not infer the message type from its array position or rendered text:
| Message content | Corresponding field |
|---|---|
| Text and Markdown | textElem, markdownTextElem |
| Image, audio, video, and file | pictureElem, soundElem, videoElem, fileElem |
| @ mention and reply | atTextElem, quoteElem |
| Merged forward and custom message | mergeElem, customElem |
| Contact card, location, and emoji | cardElem, locationElem, faceElem |
| Advanced text and typing status | advancedTextElem, typingElem |
| Notification and attached state | notificationElem, attachedInfoElem |
conversationID identifies the conversation to which a message belongs, but it is not a field of MessageItem. Obtain it from the active conversation, history query criteria, search result, or event context. Message state is generally merged by conversationID:clientMsgID.
Create messages with different content types
| Content | Entry point | Important details |
|---|---|---|
| Text and Markdown | Create a text message, Create a Markdown message | Render Markdown safely on the receiving client. |
| Group @ mentions | Create an @ message | Available only in group chats. Conversation data maintains the @ alert state. |
| Image, audio, video, and file | Create an image message from a file, Create an image message from a URL | Other media types use the same local-file or uploaded-URL paths. |
| Contact card, location, and emoji | Create a contact card message, Create a location message, Create an emoji message | Creation stores a content snapshot; it does not update automatically when the source data changes. |
| Reply, forward, and merged forward | Create a reply message, Create a forwarded message, Create a merged message | The created object must still be sent explicitly. |
| Custom business content | Create a custom message | Suitable for structured application data that must be synchronized to conversation members. |
Store state that affects only the current client's presentation in localEx; do not place business content that must be synchronized to other users there. See Set a local message extension.
Find a page by task
| Task | Page |
|---|---|
| Send an ordinary message or media that has already been uploaded | Send a message, Send an uploaded media message |
| Receive online, offline, and online-only messages | Receive messages |
| Load history, load in reverse, or retrieve message context | Load message history, Load message history in reverse, Load message context |
| Locate messages by ID or search local messages | Find messages by ID, Search messages |
| Delete, revoke, modify, or pin messages | Delete messages in a batch, Revoke a message, Modify a message, Pin or unpin a message |
| Clear a conversation's unread count or manage member-level group read status | Mark a conversation as read, Report group messages as read, Get members who read a group message |
| Report typing status or transcribe audio | Report typing status, Transcribe audio |
| Insert, delete, or extend messages visible only on the current device | Insert a local one-to-one message, Delete a local message, Set a local message extension |
State synchronization boundaries
The complete listener implementation for each message event is maintained only on its canonical page:
| Change | Canonical event page | Merge strategy |
|---|---|---|
| New, offline, and online-only messages | Receive messages | Determine the target conversation, then merge by clientMsgID. |
| Message deletion | Delete messages in a batch | Remove by target conversation and clientMsgID. |
| Message revocation | Revoke a message | Update the message to the revoked state by clientMsgID. |
| Message modification | Modify a message | Replace message content by clientMsgID. |
| Message pinning | Pin or unpin a message | Update the pinned set by conversationID. |
| Group read receipt | Report group messages as read | Merge by conversationID and clientMsgID. |
| Typing status | Report typing status | Update by conversationID:userID. |
Conversation unread counts, total unread count, and group @ alerts are conversation state. Their event handlers are maintained on Mark a conversation as read, Maintain the total unread count, and Get the conversation list, respectively.
Creating a message object and performing a read-only query use the Promise result only to establish a snapshot; they do not trigger shared message events. For state-changing operations, treat Promise completion, event arrival, and re-query reconciliation as separate stages.
Was this page helpful?