chatwoot_flutter_sdk 0.1.1
chatwoot_flutter_sdk: ^0.1.1 copied to clipboard
A flutter client sdk for chatwoot. Integrate Chatwoot flutter client into your flutter app and talk to your visitors/users in real time.
Chatwoot Flutter SDK #
Integrate Chatwoot's real-time messaging capabilities into your Flutter app with ease. This comprehensive SDK provides both WebView-based widgets and native Flutter implementations for seamless customer support integration.
Chatwoot is an open-source customer engagement platform that helps you connect with your visitors and provide exceptional support in real time.

β¨ Features #
- π Easy Integration - Simple setup with WebView or native Flutter widgets
- π¬ Real-time Messaging - WebSocket-powered live chat
- π± Cross Platform - Works on iOS, Android, and other Flutter platforms
- πΎ Offline Support - Local message persistence with Hive
- π File Attachments - Support for image and file sharing
- π¨ Customizable UI - Build your own chat interface or use pre-built widgets (full native components coming soon)
- π Event Callbacks - Handle typing indicators, message status, and more
- π Internationalization - Multi-language support
π¦ Installation #
Add this to your pubspec.yaml
:
dependencies:
chatwoot_flutter_sdk: ^0.1.0
Or install via command line:
flutter pub add chatwoot_flutter_sdk
π Quick Start #
Option 1: WebView Widget (Recommended for Quick Setup) #
The easiest way to integrate Chatwoot is using the ChatwootWidget
, which provides a full-featured chat interface in a WebView.
Setup:
- Create a Website Channel in your Chatwoot dashboard (Guide)
- Get your
websiteToken
andbaseUrl
import 'package:chatwoot_flutter_sdk/chatwoot_sdk.dart';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
class ChatPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Customer Support')),
body: ChatwootWidget(
websiteToken: 'your-website-token-here',
baseUrl: 'https://your-chatwoot-instance.com',
user: ChatwootUser(
identifier: 'user@example.com',
name: 'John Doe',
email: 'user@example.com',
),
locale: 'en',
onAttachFile: () async {
// File picker implementation
final result = await FilePicker.platform.pickFiles(
allowMultiple: true,
type: FileType.any,
);
return result?.paths.where((path) => path != null).cast<String>().toList() ?? [];
},
onLoadStarted: () => print('Chat loading...'),
onLoadCompleted: () => print('Chat loaded!'),
),
);
}
}
That's it! Your chat widget is ready. π
Option 2: Native Flutter Implementation #
For more control over the UI and advanced features, use ChatwootClient
to build your own chat interface.
β οΈ Note: Full native chat UI components are currently in development. The example below shows how to implement a basic chat interface. A complete native chat widget with advanced features will be available in future releases.
Setup:
- Create an API Channel in your Chatwoot dashboard (Guide)
- Get your
inboxIdentifier
andbaseUrl
Example: Custom Chat Page
import 'package:chatwoot_flutter_sdk/chatwoot_sdk.dart';
import 'package:flutter/material.dart';
class CustomChatPage extends StatefulWidget {
@override
_CustomChatPageState createState() => _CustomChatPageState();
}
class _CustomChatPageState extends State<CustomChatPage> {
ChatwootClient? _client;
final List<ChatwootMessage> _messages = [];
final TextEditingController _controller = TextEditingController();
@override
void initState() {
super.initState();
_initializeChat();
}
void _initializeChat() async {
try {
_client = await ChatwootClient.create(
baseUrl: 'https://your-chatwoot-instance.com',
inboxIdentifier: 'your-inbox-identifier',
user: ChatwootUser(
identifier: 'user@example.com',
name: 'John Doe',
email: 'user@example.com',
),
enablePersistence: true,
callbacks: ChatwootCallbacks(
onWelcome: () => print('Chat connected! π'),
onMessageReceived: (message) {
setState(() {
_messages.add(message);
});
},
onMessageSent: (message, echoId) => print('Message sent β
'),
onMessageDelivered: (message, echoId) => print('Message delivered β
'),
onConversationStartedTyping: () => print('Agent is typing...'),
onConversationStoppedTyping: () => print('Agent stopped typing'),
onError: (error) => print('Error: ${error.cause}'),
),
);
// Load previous messages
_client?.loadMessages();
} catch (error) {
print('Failed to initialize chat: $error');
}
}
void _sendMessage() {
if (_controller.text.trim().isNotEmpty) {
_client?.sendMessage(
content: _controller.text.trim(),
echoId: DateTime.now().millisecondsSinceEpoch.toString(),
);
_controller.clear();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Custom Chat')),
body: Column(
children: [
// Connection status
Container(
padding: EdgeInsets.all(8),
color: _client != null ? Colors.green.shade100 : Colors.red.shade100,
child: Row(
children: [
Icon(_client != null ? Icons.check_circle : Icons.error),
SizedBox(width: 8),
Text(_client != null ? 'Connected' : 'Connecting...'),
],
),
),
// Messages list
Expanded(
child: ListView.builder(
itemCount: _messages.length,
itemBuilder: (context, index) {
final message = _messages[index];
final isUser = message.messageType == 1;
return Container(
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: Row(
mainAxisAlignment: isUser ? MainAxisAlignment.end : MainAxisAlignment.start,
children: [
Container(
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.7),
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: isUser ? Colors.blue : Colors.grey.shade200,
borderRadius: BorderRadius.circular(16),
),
child: Text(
message.content ?? '',
style: TextStyle(
color: isUser ? Colors.white : Colors.black,
),
),
),
],
),
);
},
),
),
// Message input
Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
border: Border(top: BorderSide(color: Colors.grey.shade300)),
),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(
hintText: 'Type a message...',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(24),
),
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
),
onSubmitted: (_) => _sendMessage(),
),
),
SizedBox(width: 8),
FloatingActionButton(
mini: true,
onPressed: _sendMessage,
child: Icon(Icons.send),
),
],
),
),
],
),
);
}
@override
void dispose() {
_client?.dispose();
_controller.dispose();
super.dispose();
}
}
π Widget Parameters #
ChatwootWidget Parameters #
Parameter | Type | Required | Description |
---|---|---|---|
websiteToken |
String |
β | Website inbox channel token |
baseUrl |
String |
β | Your Chatwoot instance URL |
user |
ChatwootUser |
β | User information (email, name, etc.) |
locale |
String |
β | User locale (default: 'en') |
customAttributes |
Map<String, dynamic> |
β | Additional customer information |
onAttachFile |
Future<List<String>> Function() |
β | File attachment handler |
onLoadStarted |
void Function() |
β | Widget load start callback |
onLoadProgress |
void Function(int) |
β | Widget load progress callback |
onLoadCompleted |
void Function() |
β | Widget load completed callback |
closeWidget |
void Function() |
β | Widget close callback |
ChatwootClient Parameters #
Parameter | Type | Required | Description |
---|---|---|---|
baseUrl |
String |
β | Your Chatwoot instance URL |
inboxIdentifier |
String |
β | API inbox identifier |
user |
ChatwootUser |
β | User information |
enablePersistence |
bool |
β | Enable local data storage (default: true) |
callbacks |
ChatwootCallbacks |
β | Event callbacks |
π Available Callbacks #
The ChatwootCallbacks
class provides handlers for various chat events:
ChatwootCallbacks(
onWelcome: () => print('Welcome! Chat is ready π'),
onPing: () => print('Connection ping received'),
onConfirmedSubscription: () => print('Successfully connected to chat'),
onConversationStartedTyping: () => print('Agent is typing...'),
onConversationStoppedTyping: () => print('Agent stopped typing'),
onConversationIsOnline: () => print('Agent is online'),
onConversationIsOffline: () => print('Agent is offline'),
onMessageReceived: (message) => print('New message: ${message.content}'),
onMessageSent: (message, echoId) => print('Message sent successfully'),
onMessageDelivered: (message, echoId) => print('Message delivered'),
onPersistedMessagesRetrieved: (messages) => print('Loaded ${messages.length} cached messages'),
onMessagesRetrieved: (messages) => print('Loaded ${messages.length} messages from server'),
onConversationResolved: () => print('Conversation resolved'),
onError: (error) => print('Chat error: ${error.cause}'),
)
πΎ Data Persistence #
The SDK uses Hive for local storage, providing:
- Offline Message Access: View previous conversations without internet
- Seamless Experience: Continue conversations across app sessions
- Automatic Sync: Messages sync when connection is restored
// Enable persistence (default: true)
ChatwootClient.create(
enablePersistence: true,
// ... other parameters
);
// Clear local data
await client.clearClientData(); // Clear current user's data
await ChatwootClient.clearAllData(); // Clear all stored data
π Example App #
Check out our comprehensive example app that demonstrates:
- β WebView Chat Widget - Full-featured chat interface
- π§ Custom Flutter Chat - Native Flutter implementation using
flutter_chat_ui
(basic example) - β File Attachments - Image and file sharing
- β Real-time Events - Connection status, typing indicators
- β Persistence - Offline message access
- β Error Handling - Graceful error management
Run the example:
cd example
flutter run
π€ Contributing #
We welcome contributions! Please see our Development Guide for details on:
- Setting up the development environment
- Running tests
- Submitting pull requests
- Code style guidelines
π License #
This project is licensed under the MIT License - see the LICENSE file for details.
π Support #
- π Documentation
- π¬ Community Discussions
- π Bug Reports
- π§ Email Support
Made with β€οΈ by the Chatwoot team