Unread Messages
The plugin provides a method to check the number of unread messages for the current visitor session using the Crisp REST API.
Usage
int? unreadCount = await FlutterCrispChat.getUnreadMessageCount(
websiteId: 'YOUR_WEBSITE_ID',
identifier: 'YOUR_CRISP_API_IDENTIFIER',
key: 'YOUR_CRISP_API_KEY',
);
if (unreadCount != null && unreadCount > 0) {
print('You have $unreadCount unread messages.');
}2
3
4
5
6
7
8
9
Parameters
| Parameter | Type | Description |
|---|---|---|
websiteId | String | Your Crisp Website ID |
identifier | String | Your Crisp REST API Identifier |
key | String | Your Crisp REST API Key |
Return Value
- Returns an
intwith the unread message count if successful - Returns
nullif no active session exists or an error occurs - Returns
0if the session exists but has no unread messages
Obtaining API Credentials
The identifier and key are not the same as your Crisp dashboard login. They are REST API credentials from the Crisp Marketplace.
Step-by-Step
- Go to the Crisp Marketplace
- Sign in or create an account (this is separate from your main Crisp account)
- Go to Plugins > click New Plugin
- Select Private as the plugin type
- Name your plugin (e.g., "My Flutter App") and click Create
- Go to the Tokens tab > scroll to Development Token
- Copy your
identifierandkey
Link Your Workspace
Before using the token, associate your marketplace account with your Crisp workspace:
- Go to Settings in your Crisp Marketplace account
- Click Add Trusted Workspace and submit your
website_id - Enter your main Crisp account credentials and 2FA token (if enabled)
Production Tokens
Development tokens have rate limits. For production use, obtain a production token from the Crisp Marketplace once your plugin is ready.
Example: Badge with Unread Count
class ChatButton extends StatefulWidget {
const ChatButton({super.key});
@override
State<ChatButton> createState() => _ChatButtonState();
}
class _ChatButtonState extends State<ChatButton> {
int unreadCount = 0;
void _checkUnread() async {
int? count = await FlutterCrispChat.getUnreadMessageCount(
websiteId: 'YOUR_WEBSITE_ID',
identifier: 'YOUR_IDENTIFIER',
key: 'YOUR_KEY',
);
if (count != null && count > 0) {
setState(() => unreadCount = count);
}
}
@override
Widget build(BuildContext context) {
return Badge.count(
count: unreadCount,
isLabelVisible: unreadCount > 0,
child: ElevatedButton(
onPressed: _checkUnread,
child: const Text('Messages'),
),
);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
How It Works
Internally, getUnreadMessageCount does the following:
- Calls
getSessionIdentifier()to get the current session ID - Makes a GET request to
https://api.crisp.chat/v1/website/{websiteId}/conversation/{sessionId} - Authenticates with Basic auth using your
identifier:key - Parses the
data.unread.visitorfield from the response
If there is no active session (e.g., the user hasn't opened the chat yet), the method returns null.
iOS limitation: unread count not clearing after reading chat
On iOS, the native Crisp SDK may not send read receipts to the Crisp backend when a visitor reads operator messages in ChatViewController. The REST field unread.visitor therefore stays non-zero even after the chat is closed — this is a Crisp iOS SDK limitation, not a bug in this plugin's REST call.
Workaround: mark messages as read via REST
After the visitor closes the chat, call markMessagesAsRead to reset the server-side counter:
await FlutterCrispChat.markMessagesAsRead(
websiteId: 'YOUR_WEBSITE_ID',
identifier: 'YOUR_IDENTIFIER',
key: 'YOUR_KEY',
);
final count = await FlutterCrispChat.getUnreadMessageCount(
websiteId: 'YOUR_WEBSITE_ID',
identifier: 'YOUR_IDENTIFIER',
key: 'YOUR_KEY',
);
// count should now be 02
3
4
5
6
7
8
9
10
11
12
Verify with REST (control test)
Use the verification script with your Marketplace credentials:
export CRISP_WEBSITE_ID=... CRISP_IDENTIFIER=... CRISP_KEY=... CRISP_SESSION_ID=...
./scripts/verify_unread_read_receipts.sh full2
If PATCH /read clears unread.visitor but reading in the iOS chat does not, file an issue with Crisp using docs/crisp-sdk-ios-unread-issue.md.
See also Platform-Specific Issues — iOS unread count.
markMessagesAsRead
Marks all operator messages as read for the current session via the Crisp REST API. Use on iOS when getUnreadMessageCount stays non-zero after the visitor reads chat.
final success = await FlutterCrispChat.markMessagesAsRead(
websiteId: 'YOUR_WEBSITE_ID',
identifier: 'YOUR_IDENTIFIER',
key: 'YOUR_KEY',
);
// success == true when accepted (HTTP 202)2
3
4
5
6
Returns: true on success, false on API error, null if no active session.
Next Steps
- Firebase Setup — Set up push notifications for your app