A Flutter plugin for integrating Zendesk Messaging SDK into your mobile applications. Provides in-app customer support messaging with multi-conversation support, real-time events, and JWT authentication.
- Initialize and display the Zendesk Messaging UI
- JWT user authentication
- Multi-conversation navigation
- Real-time event streaming (24 event types)
- Unread message count tracking
- Conversation tags and custom fields
- Connection status monitoring
- Push notifications support (FCM/APNs)
| Platform | Minimum Version |
|---|---|
| iOS | 14.0 |
| Android | API 21 (minSdk) |
| Dart | 3.6.0 |
| Flutter | 3.24.0 |
Add zendesk_messaging to your pubspec.yaml:
dependencies:
zendesk_messaging: ^3.0.0Add the Zendesk Maven repository to your project-level android/build.gradle:
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://zendesk.jfrog.io/artifactory/repo' }
}
}Update your ios/Podfile to target iOS 14.0:
platform :ios, '14.0'Then run:
cd ios && pod installBefore initializing the SDK, you need to obtain your Android and iOS channel keys from the Zendesk Admin Center:
- Go to Admin Center > Channels > Messaging and social > Messaging
- Hover over the brand you want to configure and click the options icon
- Click Edit and navigate to the Installation section
- Under Channel ID, click Copy to copy the key to your clipboard
- Use this key for both Android and iOS initialization
Note: The same Channel ID is used for both platforms. You can create separate channels for Android and iOS if needed.
import 'package:zendesk_messaging/zendesk_messaging.dart';
// Initialize the SDK (call once at app startup)
await ZendeskMessaging.initialize(
androidChannelKey: 'your_android_channel_key',
iosChannelKey: 'your_ios_channel_key',
);// Show the default messaging interface
await ZendeskMessaging.show();
// Show a specific conversation (requires multi-conversation enabled)
await ZendeskMessaging.showConversation('conversation_id');
// Show the conversation list
await ZendeskMessaging.showConversationList();
// Start a new conversation
await ZendeskMessaging.startNewConversation();// Login with JWT
try {
final response = await ZendeskMessaging.loginUser(jwt: 'your_jwt_token');
print('Logged in: ${response.id}');
} catch (e) {
print('Login failed: $e');
}
// Check login status
final isLoggedIn = await ZendeskMessaging.isLoggedIn();
// Get current user
final user = await ZendeskMessaging.getCurrentUser();
// Logout
await ZendeskMessaging.logoutUser();The SDK provides a unified event stream for all Zendesk events. Use Dart 3 pattern matching to handle specific event types:
ZendeskMessaging.eventStream.listen((event) {
switch (event) {
case UnreadMessageCountChanged(:final totalUnreadCount, :final conversationId):
print('Unread: $totalUnreadCount');
case AuthenticationFailed(:final errorMessage, :final isJwtExpired):
if (isJwtExpired) {
// Refresh JWT token
}
case ConnectionStatusChanged(:final status):
print('Connection: ${status.name}');
case ConversationAdded(:final conversationId):
print('New conversation: $conversationId');
case MessagesShown(:final messages):
print('${messages.length} messages shown');
default:
break;
}
});
// Start listening for events
await ZendeskMessaging.listenUnreadMessages();| Event | Description |
|---|---|
UnreadMessageCountChanged |
Unread message count changed |
AuthenticationFailed |
Authentication failed |
ConnectionStatusChanged |
Connection status changed |
ConversationAdded |
New conversation created |
ConversationStarted |
Conversation initiated |
ConversationOpened |
Conversation opened |
MessagesShown |
Messages rendered |
SendMessageFailed |
Message send failed |
FieldValidationFailed |
Field validation failed |
MessagingOpened |
Messaging UI opened |
MessagingClosed |
Messaging UI closed |
ProactiveMessageDisplayed |
Proactive message shown |
ProactiveMessageClicked |
Proactive message clicked |
ConversationWithAgentRequested |
User requested agent |
ConversationWithAgentAssigned |
Agent assigned |
ConversationServedByAgent |
Agent serving |
NewConversationButtonClicked |
New conversation clicked |
PostbackButtonClicked |
Postback button clicked |
ArticleClicked |
Article clicked |
ArticleBrowserClicked |
Article opened in browser |
ConversationExtensionOpened |
Extension opened |
ConversationExtensionDisplayed |
Extension displayed |
NotificationDisplayed |
Push notification shown |
NotificationOpened |
Push notification opened |
// Get current count
final count = await ZendeskMessaging.getUnreadMessageCount();
// Get count for specific conversation
final convCount = await ZendeskMessaging.getUnreadMessageCountForConversation('conv_id');
// Listen to count changes (legacy API)
ZendeskMessaging.unreadMessagesCountStream.listen((count) {
print('Unread: $count');
});// Set tags (applied when user sends a message)
await ZendeskMessaging.setConversationTags(['vip', 'mobile']);
// Clear tags
await ZendeskMessaging.clearConversationTags();
// Set custom fields
await ZendeskMessaging.setConversationFields({
'app_version': '3.0.0',
'user_tier': 'premium',
});
// Clear fields
await ZendeskMessaging.clearConversationFields();final status = await ZendeskMessaging.getConnectionStatus();
// Returns: connected, connecting, disconnected, or unknownEnable push notifications to notify users of new messages when the app is in the background or closed.
| Platform | Requirement |
|---|---|
| Android | Firebase Cloud Messaging (FCM) setup |
| iOS | APNs certificate uploaded to Zendesk Admin Center |
| Both | Real device (simulators don't support push) |
- Add Firebase to your Android app (Firebase setup guide)
- Add
firebase_messagingto yourpubspec.yaml:dependencies: firebase_messaging: ^15.0.0
- Get your FCM Server Key from Firebase Console
- Upload the key to Zendesk Admin Center > Channels > Messaging > Android > Notifications
- Create an APNs certificate in Apple Developer Portal
- Export as
.p12file from Keychain Access - Upload to Zendesk Admin Center > Channels > Messaging > iOS > Notifications
- Add Push Notifications capability in Xcode
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:zendesk_messaging/zendesk_messaging.dart';
Future<void> setupPushNotifications() async {
final messaging = FirebaseMessaging.instance;
// Request permission
await messaging.requestPermission();
// Get and register token
final token = await messaging.getToken();
if (token != null) {
await ZendeskMessaging.updatePushNotificationToken(token);
}
// Listen for token refresh
messaging.onTokenRefresh.listen((token) {
ZendeskMessaging.updatePushNotificationToken(token);
});
// Handle foreground notifications
FirebaseMessaging.onMessage.listen((message) async {
final responsibility = await ZendeskMessaging.shouldBeDisplayed(message.data);
switch (responsibility) {
case ZendeskPushResponsibility.messagingShouldDisplay:
await ZendeskMessaging.handleNotification(message.data);
case ZendeskPushResponsibility.notFromMessaging:
// Handle your own notification
break;
default:
break;
}
});
// Handle notification tap (app in background)
FirebaseMessaging.onMessageOpenedApp.listen((message) async {
await ZendeskMessaging.handleNotificationTap(message.data);
});
}| Method | Returns | Description |
|---|---|---|
updatePushNotificationToken(token) |
Future<void> |
Register FCM/APNs token with Zendesk |
shouldBeDisplayed(data) |
Future<ZendeskPushResponsibility> |
Check if notification is from Zendesk |
handleNotification(data) |
Future<bool> |
Display the notification |
handleNotificationTap(data) |
Future<void> |
Handle notification tap |
| Value | Description |
|---|---|
messagingShouldDisplay |
Zendesk notification, SDK can display it |
messagingShouldNotDisplay |
Zendesk notification, but should not display (e.g., user is viewing the conversation) |
notFromMessaging |
Not a Zendesk notification, handle it yourself |
unknown |
Unable to determine |
// Check if SDK is initialized
final isInit = await ZendeskMessaging.isInitialized();
// Invalidate SDK instance (cleanup)
await ZendeskMessaging.invalidate();
// After invalidate, you must call initialize() again to use the SDK| Method | Returns | Description |
|---|---|---|
initialize(androidChannelKey, iosChannelKey) |
Future<void> |
Initialize the SDK |
isInitialized() |
Future<bool> |
Check if SDK is initialized |
invalidate() |
Future<void> |
Invalidate SDK instance |
show() |
Future<void> |
Show messaging UI |
showConversation(id) |
Future<void> |
Show specific conversation |
showConversationList() |
Future<void> |
Show conversation list |
startNewConversation() |
Future<void> |
Start new conversation |
loginUser(jwt) |
Future<ZendeskLoginResponse> |
Login with JWT |
logoutUser() |
Future<void> |
Logout current user |
isLoggedIn() |
Future<bool> |
Check login status |
getCurrentUser() |
Future<ZendeskUser?> |
Get current user info |
getUnreadMessageCount() |
Future<int> |
Get total unread count |
getUnreadMessageCountForConversation(id) |
Future<int> |
Get unread count for conversation |
listenUnreadMessages() |
Future<void> |
Start listening for events |
setConversationTags(tags) |
Future<void> |
Set conversation tags |
clearConversationTags() |
Future<void> |
Clear conversation tags |
setConversationFields(fields) |
Future<void> |
Set custom fields |
clearConversationFields() |
Future<void> |
Clear custom fields |
getConnectionStatus() |
Future<ZendeskConnectionStatus> |
Get connection status |
updatePushNotificationToken(token) |
Future<void> |
Register push token |
shouldBeDisplayed(data) |
Future<ZendeskPushResponsibility> |
Check notification source |
handleNotification(data) |
Future<bool> |
Handle push notification |
handleNotificationTap(data) |
Future<void> |
Handle notification tap |
| Stream | Type | Description |
|---|---|---|
eventStream |
Stream<ZendeskEvent> |
All Zendesk events |
unreadMessagesCountStream |
Stream<int> |
Unread count changes (legacy) |
ZendeskUser
class ZendeskUser {
String? id;
String? externalId;
ZendeskAuthenticationType authenticationType;
}ZendeskLoginResponse
class ZendeskLoginResponse {
String? id;
String? externalId;
}ZendeskMessage
class ZendeskMessage {
String id;
String conversationId;
String? authorId;
String? content;
DateTime? timestamp;
}ZendeskAuthenticationType
anonymousjwt
ZendeskConnectionStatus
connectedconnectingdisconnectedunknown
ZendeskPushResponsibility
messagingShouldDisplaymessagingShouldNotDisplaynotFromMessagingunknown
- iOS 14.0 minimum - Apps targeting iOS 12/13 must upgrade
- Dart 3.6+ required - Update your SDK constraint
- Flutter 3.24+ required - Update your Flutter SDK
- New event API - Use sealed class pattern for type-safe event handling
- Update
pubspec.yaml:
environment:
sdk: ^3.6.0
flutter: ">=3.24.0"- Update iOS Podfile:
platform :ios, '14.0'- Update event handling (optional but recommended):
// Old way (still works)
ZendeskMessaging.unreadMessagesCountStream.listen((count) {
print('Unread: $count');
});
// New way (recommended)
ZendeskMessaging.eventStream.listen((event) {
if (event is UnreadMessageCountChanged) {
print('Unread: ${event.totalUnreadCount}');
}
});Ensure your Podfile has the correct platform version:
platform :ios, '14.0'Then run:
cd ios && pod install --repo-updateEnsure the Zendesk Maven repository is added:
maven { url 'https://zendesk.jfrog.io/artifactory/repo' }Make sure to call listenUnreadMessages() after initialization:
await ZendeskMessaging.initialize(...);
await ZendeskMessaging.listenUnreadMessages();| Plugin | Android SDK | iOS SDK |
|---|---|---|
| 3.0.0 | 2.36.1 | 2.36.0 |
| 2.9.x | 2.26.0 | 2.24.0 |
MIT License - see LICENSE for details.
Contributions are welcome! Please read the contributing guidelines before submitting a pull request.
