Skip to main content
Let users bookmark messages for later. Saving a message is private to the logged-in user — nobody else in the conversation can see it — and works across conversations: a user’s saved messages from all of their chats appear in one list, synced across all of their devices. Let’s see how to work with saved messages in CometChat’s Android SDK.
Saving a message with the SDK requires the Save Message feature to be enabled for your app. You can check its availability at runtime using the feature flag.

Save a Message

To save a message, use the saveMessage method and pass the ID of the message. On success, the callback returns the updated BaseMessage with its savedAt attribute set.
Saving is idempotent — saving an already saved message succeeds and refreshes getSavedAt() rather than failing.
A just-sent message may not be pinnable or savable yet. On an app with moderation enabled, the server stamps a new message as moderation-pending and clears it a moment later. While it is pending, the call is rejected with ERR_MESSAGE_NO_ACCESS — the same code returned for a genuine permission refusal, so you cannot tell the two apart from the error alone.The window runs from send, not from the user’s tap, and clears within a few seconds. Do not disable the control on this error: by the time someone opens a menu and taps, moderation has usually finished. Prefer a retry or a transient “not ready yet” message over telling the user they lack permission. Moderation is configured per app, so this never reproduces on an app that has it switched off. (The CometChat UI Kits already withhold the Pin/Save options on a moderation-pending, disapproved, deleted or not-yet-sent message; this only concerns custom UI built directly on the SDK.)
Unlike pinning, saving has no role restrictions — every user can save any message they have access to. Deleted messages cannot be saved.

Unsave a Message

To remove a message from the user’s saved list, use the unsaveMessage method. On success, the callback returns the updated BaseMessage with its savedAt attribute cleared.

Fetch Saved Messages

To fetch all messages the logged-in user has saved, create a MessagesRequest with the setSaved(true) filter of the MessagesRequestBuilder. Because saved messages are user-level and span conversations, you must not set a UID or GUID. The returned list is sorted by the time of saving, most recently saved first.
The list is ordered by save time, most recently saved first — not by when the messages were sent. Page it with fetchNext() until a call returns an empty list; the cursor rides on savedAt instead of sentAt, and the SDK swaps it for you.
If the user loses access to a conversation (for example, they are removed from a group), messages saved from it are cleaned up and no longer returned.

Check if a Message is Saved

Every fetched message carries the logged-in user’s save state on the BaseMessage itself. These values are per-user: the same message shows different values to different users.

Real-time Save Events

Because saving is private, save events are never delivered to other participants. Register a MessageListener and override the save callbacks; each event delivers the full updated BaseMessage. Today these callbacks fire on the acting device when a save or unsave succeeds. Delivery to the user’s other devices activates once server-side real-time delivery for save events is rolled out — until then, other sessions pick up save changes on their next fetch.
To stop listening, remove the listener with CometChat.removeMessageListener(listenerID).

Save Limit

A user can save a capped number of messages, configurable per app. Read the cap rather than hard-coding it — it is tenant-overridable and will drift.
The call is synchronous and never throws. It returns Settings.LIMIT_UNSPECIFIED (-1) when the app settings carry no value or when it is called before init() completes — show generic copy in that case rather than guessing a number. Unlike pinning, saving has no separate system cap. When the limit is breached, the SDK surfaces the server error through onError, and the applicable limit is carried in the exception’s errorParams:

Error Handling

Feature Availability

Check whether the Save Message feature is enabled for your app before showing save actions in your UI. The method is synchronous and safe to call from the UI layer.

Next Steps

Pin A Message

Highlight a message for everyone in the conversation

Pin A Conversation

Pin a conversation to the top of the list

All Real Time Listeners

Every listener the SDK exposes, in one place

Additional Message Filtering

Filter messages by pinned, saved, type, tags and more