Skip to main content

Message overview

Message structure

PropertyTypeDescription
channelTypeChannelType?Channel type
channelIdString?Channel ID
subChannelIdString?Business identifier for the channel (max 20 characters). Only applies to community channels.
messageTypeMessageType?Message type
clientIdint?Unique local message ID (database index)
messageIdString?Unique server message ID (globally unique within an App Key)
directionMessageDirectionMessage direction
receivedTimeintReceive time (Unix timestamp in milliseconds)
sentTimeintSend time (Unix timestamp in milliseconds)
receivedStatusReceivedStatusReceive status
sentStatusSentStatusSend status
senderUserIdStringSender user ID
metadataMap?Metadata key-value pairs. Set them at send time. After sending, they can't be changed through this field. Supported only in direct channels and group channels. Key length ≤ 32, value length ≤ 4096, max 20 pairs per update, max 300 total per message.
offLineboolWhether this is a missed message. Only valid in the message receive callback. true for missed messages, false otherwise.
groupReadReceiptInfoGroupReadReceiptInfoGroup read receipt status
userInfoUserInfoUser info attached to the message
mentionedInfoMentionedInfo?Mention (@) information

| extra | String? | Additional field attached to the message. The receiver can access this data. |

Message types and constructors

The Chat SDK MessageType enum provides predefined types for text, voice, image, and other messages. Not every enum value has a dedicated Flutter constructor. The current Flutter wrapper exposes registered custom messages through CustomMessage and CustomMediaMessage.

By default, all message types are stored locally and counted toward the unread count, except:

  • Recall (MessageType.recall): Stored locally but not counted as unread.
  • Command (MessageType.command): Not stored locally, not counted as unread.
  • Command notification (MessageType.commandNotification): Stored locally but not counted as unread.
  • Custom (MessageType.custom): Reserved enum value. The current Flutter wrapper does not provide a dedicated constructor for this type.
  • User custom (MessageType.userCustom): Reserved enum value for app-defined custom handling.
  • Registered custom (MessageType.customMessage): Storage controlled by CustomMessagePersistentFlag.
  • Registered custom media (MessageType.customMediaMessage): Storage controlled by CustomMessagePersistentFlag.
tip

Use registerCustomMessage() and registerCustomMediaMessage() to register interoperable custom message types before connecting. After registration, send them with CustomMessageParams or CustomMediaMessageParams.

Text message

Type: MessageType.text

PropertyTypeDescription
textStringText content

Build a text message

Dart
final channel = DirectChannel('<target-id>');
await channel.sendMessage(SendMessageParams(
messageParams: TextMessageParams(
text: '<message-text>',
),
));
ParameterTypeDescription
textStringText content

Voice message

tip

Record voice messages in AAC format with a bitrate of at least 56 kbps for quality and compatibility.

Type: MessageType.voice

PropertyTypeDescription
durationintVoice duration in seconds

Build a voice message

Dart
final channel = DirectChannel('<target-user-id>');
await channel.sendMediaMessage(SendMediaMessageParams(
messageParams: HDVoiceMessageParams(
path: path,
duration: duration,
),
));
ParameterTypeDescription
pathStringLocal path to the voice file (must be valid)
durationintVoice message duration

Image message

Type: MessageType.image

PropertyTypeDescription
thumbnailBase64StringStringBase64 thumbnail data
thumWidthintThumbnail width (pixels)
thumHeightintThumbnail height (pixels)
originalboolWhether this is the original image

Build an image message

Dart
final channel = DirectChannel('<target-user-id>');
await channel.sendMediaMessage(SendMediaMessageParams(
messageParams: ImageMessageParams(
path: path,
),
));
ParameterTypeDescription
pathStringLocal path to the image file (must be valid)

File message

Type: MessageType.file

PropertyTypeDescription
nameStringFile name
fileTypeStringFile type
sizeintFile size in bytes

Build a file message

Dart
final channel = DirectChannel('<target-user-id>');
await channel.sendMediaMessage(SendMediaMessageParams(
messageParams: FileMessageParams(
path: path,
),
));
ParameterTypeDescription
pathStringLocal path to the file (must be valid)

Short video message

Type: MessageType.sight

PropertyTypeDescription
durationintVideo duration
sizeintVideo size
nameStringVideo name
thumbnailBase64StringStringThumbnail data

Build a short video message

Dart
final channel = DirectChannel('<target-user-id>');
await channel.sendMediaMessage(SendMediaMessageParams(
messageParams: ShortVideoMessageParams(
path: path,
duration: duration,
),
));
ParameterTypeDescription
pathStringLocal path to the video file (must be valid)
durationintVideo duration. The server default maximum is 2 minutes. Contact your sales representative to adjust this limit.

GIF message

Type: MessageType.gif

PropertyTypeDescription
dataSizeintGIF size in bytes
widthintGIF width
heightintGIF height

Build a GIF message

Dart
final channel = DirectChannel('<target-user-id>');
await channel.sendMediaMessage(SendMediaMessageParams(
messageParams: GIFMessageParams(
path: path,
),
));
ParameterTypeDescription
pathStringLocal path to the GIF file

Combine message

Type: MessageType.combineV2

PropertyTypeDescription
sourceChannelTypeChannelType?Source channel type of the forwarded messages
summaryListList<String>?Summary lines shown in the combined message preview
nameListList<String>?Sender display names included in the combined message
msgNumint?Number of messages included in the combined message
msgListList<CombineMessageInfo>?Original message metadata included in the package
jsonMsgKeyString?Key used to retrieve the full combined payload

Build a combine message

Dart
final channel = GroupChannel('<group-id>');
await channel.sendMediaMessage(SendMediaMessageParams(
messageParams: CombineMessageParams(
sourceChannelType: ChannelType.direct,
summaryList: ['Alice: Hello', 'Bob: Hi'],
nameList: ['Alice', 'Bob'],
msgList: [
CombineMessageInfo(
fromUserId: 'alice',
channelId: 'alice',
timestamp: 1710000000000,
objectName: 'NC:TxtMsg',
content: {'content': 'Hello'},
),
CombineMessageInfo(
fromUserId: 'bob',
channelId: 'bob',
timestamp: 1710000005000,
objectName: 'NC:TxtMsg',
content: {'content': 'Hi'},
),
],
),
));
ParameterTypeDescription
sourceChannelTypeChannelTypeSource channel type of the combined messages
summaryListList<String>Preview text shown in the combined message
nameListList<String>Sender display names in the preview
msgListList<CombineMessageInfo>Message metadata included in the combined message

Recall message

Recall messages cannot be constructed manually. Use the recall message API instead.

Type: MessageType.recall

PropertyTypeDescription
adminboolWhether the operation was performed by an admin
deletedboolWhether the message is deleted
recallTimeintOriginal message send time (milliseconds)
recallActionTimeintTime of the recall action (milliseconds)
originalMessageMessageThe original recalled message

Reference message

Type: MessageType.reference

PropertyTypeDescription
textStringReference text
referenceMessageMessageThe referenced message

Build a reference message

Dart
final channel = DirectChannel('<target-user-id>');
await channel.sendMessage(SendMessageParams(
messageParams: ReferenceMessageParams(
referenceMessage: referenceMessage,
text: text,
),
));
ParameterTypeDescription
referenceMessageMessageThe message to reference
textStringReference text content

Location message

Type: MessageType.location

PropertyTypeDescription
longitudedoubleLongitude
latitudedoubleLatitude
poiNameStringPOI name
thumbnailPathStringThumbnail path

Build a location message

Dart
final channel = DirectChannel('<target-user-id>');
await channel.sendMessage(SendMessageParams(
messageParams: LocationMessageParams(
longitude: longitude,
latitude: latitude,
poiName: poiName,
thumbnailPath: thumbnailPath,
),
));
ParameterTypeDescription
longitudedoubleLongitude
latitudedoubleLatitude
poiNameStringPOI name
thumbnailPathStringLocal thumbnail path (must be valid)

Command message

Type: MessageType.command

PropertyTypeDescription
nameStringCommand name
dataStringCommand data. Can be any string, such as JSON data.

The Flutter SDK does not provide a create method for CommandMessage. It only supports receiving this message type. To send command messages from the client, define a wrapper class in the Flutter layer. See How to send command messages in the Flutter SDK.

Command notification message

Type: MessageType.commandNotification

PropertyTypeDescription
nameStringNotification name
dataStringNotification data. Can be any string, such as JSON data.

The Flutter SDK does not provide a create method for CommandNotificationMessage. It only supports receiving this message type. To send command notification messages from the client, define a wrapper class in the Flutter layer. See How to send command messages in the Flutter SDK.

Group notification message

Type: MessageType.groupNotification

Group notification messages are used for group-related operations such as member join, leave, and group dissolution.

PropertyTypeDescription
operationStringOperation type
operatorUserIdStringOperator user ID
dataStringOperation-related data
messageStringOperation message content
tip

Group notification messages are typically sent automatically by the server during group operations. The client primarily receives and parses these notifications. The Flutter SDK does not provide a method to create group notification messages.

Registered custom message

Type: MessageType.customMessage

PropertyTypeDescription
messageIdentifierStringCustom message identifier
searchableWordsList<String>?Search keywords used for local message search
fieldsMap<String, String>Key-value pairs

Build a registered custom message

tip

Register custom messages after initialization but before connecting by calling registerCustomMessage.

Register a custom message

Dart
await NCEngine.registerCustomMessage(messageIdentifier, persistentFlag);
ParameterTypeDescription
messageIdentifierStringUnique message identifier
persistentFlagCustomMessagePersistentFlagStorage policy
messageIdentifier naming conventions

messageIdentifier corresponds to the server-side objectName parameter and uniquely identifies a custom message type. Follow these guidelines:

  • Format: Use prefix:messageType, e.g., app:txtcontent
  • Length: Keep it under 16 characters to minimize impact on message size
  • Restrictions:
    • Do not start with RC: (reserved for built-in messages)
    • Do not use built-in message identifiers
  • Examples:
    • app:order — Order message
    • custom:gift — Gift message
    • myapp:notice — Notice message
    • RC:TxtMsg — Incorrect: uses a reserved prefix

Send a registered custom message

Dart
final channel = GroupChannel('<group-id>');
await channel.sendMessage(SendMessageParams(
messageParams: CustomMessageParams(
messageIdentifier: messageIdentifier,
fields: fields,
),
));
ParameterTypeDescription
messageIdentifierStringUnique message identifier
fieldsMap<String, String>Key-value pairs for message content

Registered custom media message

Type: MessageType.customMediaMessage

PropertyTypeDescription
fieldsMap?Key-value pairs for message content
searchableWordsList<String>?Searchable keywords
messageIdentifierStringUnique message identifier

Build a registered custom media message

tip

Register custom media messages after initialization but before connecting by calling registerCustomMediaMessage.

Register a custom media message

Dart
await NCEngine.registerCustomMediaMessage(messageIdentifier, persistentFlag);
ParameterTypeDescription
messageIdentifierStringUnique message identifier
persistentFlagCustomMessagePersistentFlagStorage policy

Send a registered custom media message

Dart
final channel = GroupChannel('<group-id>');
await channel.sendMediaMessage(SendMediaMessageParams(
messageParams: CustomMediaMessageParams(
messageIdentifier: '<message-identifier>',
path: '<local-media-path>',
fields: {'key': 'value'},
),
));
ParameterTypeDescription
messageIdentifierStringUnique message identifier
pathStringLocal path to the media file (must be valid)
fieldsMapKey-value pairs for message content

Unknown type

When the SDK receives an unrecognized message, it becomes an unknown type. This type cannot be constructed or sent.

Type: MessageType.unknown

PropertyTypeDescription
rawDataStringRaw message data
objectNameStringMessage identifier