Skip to content

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

dart
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.');
}

Parameters

ParameterTypeDescription
websiteIdStringYour Crisp Website ID
identifierStringYour Crisp REST API Identifier
keyStringYour Crisp REST API Key

Return Value

  • Returns an int with the unread message count if successful
  • Returns null if no active session exists or an error occurs
  • Returns 0 if 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

  1. Go to the Crisp Marketplace
  2. Sign in or create an account (this is separate from your main Crisp account)
  3. Go to Plugins > click New Plugin
  4. Select Private as the plugin type
  5. Name your plugin (e.g., "My Flutter App") and click Create
  6. Go to the Tokens tab > scroll to Development Token
  7. Copy your identifier and key

Before using the token, associate your marketplace account with your Crisp workspace:

  1. Go to Settings in your Crisp Marketplace account
  2. Click Add Trusted Workspace and submit your website_id
  3. 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

dart
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'),
      ),
    );
  }
}

How It Works

Internally, getUnreadMessageCount does the following:

  1. Calls getSessionIdentifier() to get the current session ID
  2. Makes a GET request to https://api.crisp.chat/v1/website/{websiteId}/conversation/{sessionId}
  3. Authenticates with Basic auth using your identifier:key
  4. Parses the data.unread.visitor field 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:

dart
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 0

Verify with REST (control test)

Use the verification script with your Marketplace credentials:

bash
export CRISP_WEBSITE_ID=... CRISP_IDENTIFIER=... CRISP_KEY=... CRISP_SESSION_ID=...
./scripts/verify_unread_read_receipts.sh full

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.

dart
final success = await FlutterCrispChat.markMessagesAsRead(
  websiteId: 'YOUR_WEBSITE_ID',
  identifier: 'YOUR_IDENTIFIER',
  key: 'YOUR_KEY',
);
// success == true when accepted (HTTP 202)

Returns: true on success, false on API error, null if no active session.

Next Steps