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. Apps can also implement custom messages using MessageType.nativeCustom.

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): Storage controlled by the app's CustomMessagePolicy.
  • Native custom (MessageType.nativeCustom): Storage controlled by CustomMessagePersistentFlag.
  • Native custom media (MessageType.nativeCustomMedia): Storage controlled by CustomMessagePersistentFlag.
tip

The SDK supports native custom messages. The difference between custom messages and native custom messages:

  • Custom messages (MessageType.custom): A cross-platform wrapper type. These messages are wrapped at a lower level and cannot interoperate with custom messages registered via the native iOS/Android SDKs.
  • Native custom messages (MessageType.nativeCustom): Fully interoperable with custom messages registered via the native iOS/Android SDKs.

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: VoiceMessageParams(
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

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.

Custom message

Type: MessageType.custom

PropertyTypeDescription
identifierStringCustom message identifier
policyCustomMessagePolicyStorage policy
fieldsMap<String, String>Key-value pairs

Build a 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

Native custom message

Native custom messages are interoperable with custom messages registered on other platforms after registration.

Type: MessageType.nativeCustom

PropertyTypeDescription
fieldsMap?Key-value pairs for message content
searchableWordsList<String>?Searchable keywords
messageIdentifierString?Unique message identifier (see naming conventions below)
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

Build a native custom message

tip

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

Register a native custom message

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

Send a native custom message

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

Native custom media message

Type: MessageType.nativeCustomMedia

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

Build a native custom media message

tip

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

Register a native custom media message

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

Send a native 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