To use Stringee Live Chat API, you need to have a widget key which will be used to identify your portal. You can get that key by doing the following steps:

Install stringee-plugin from pub.dev by running the following command from the project root:
$ flutter pub add stringee_plugin:^1.3.2
Check out plugin's documentation for more information.
Stringee Plugin 1.3.2 requires JDK 17 and Android API 21 or later. Set compileSdk to 36 and minSdk to 21 or later in android/app/build.gradle.
AndroidManifest.xml file:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
Only add and request permissions required by attachment features in your app.
Stringee Plugin 1.3.2 requires iOS 13.0 or later. Set platform :ios, '13.0' in ios/Podfile.
pod install --repo-update.xcworkspace file.import 'dart:async';
import 'package:stringee_plugin/stringee_plugin.dart';
...
final StringeeClient client = StringeeClient();
final StringeeChat chat = StringeeChat(client);
StreamSubscription? clientSubscription;
StreamSubscription? chatSubscription;
String? queueId;
StringeeConversation? conversation;
StringeeChatRequest? chatRequest;
bool isClientConnected = false;
The StringeeClient class is defined in the Stringee Plugin. It includes methods interacting with Stringee Server. The StringeeChat class is defined in the chat section in the Stringee Plugin. It includes methods interacting with Stringee Server.
Chat Profile is an object that will let you know:
chat.getChatProfile('YOUR_WIDGET_KEY').then((value) {
print("getChatProfile: " + value.toString());
bool status = value['status'];
if (status) {
List queueList = value['body']['queues'];
if (queueList.isNotEmpty) {
queueId = queueList.first['id'];
}
}
});
To chat with your agents, your customers have to connect to Stringee server first. But they are not users in your system, they can be anybody, so you need to generate a token for them. Call getLiveChatToken(...) on the StringeeChat object:
late String token;
...
chat.getLiveChatToken('YOUR_WIDGET_KEY', 'YOUR_CUSTOMER_NAME', 'YOUR_CUSTOMER_EMAIL').then((value) {
print("getLiveChatToken: " + value.toString());
bool status = value['status'];
if (status) {
token = value['body'];
}
});
In which:
Next, we will connect to Stringee Server. You must do this before you can start a live chat conversation.
Register the client's events and chat's events.
clientSubscription = client.eventStreamController.stream.listen((event) {
Map<dynamic, dynamic> map = event;
switch (map['eventType']) {
case StringeeClientEvents.didConnect:
handleDidConnectEvent();
break;
case StringeeClientEvents.didDisconnect:
handleDidDisconnectEvent();
break;
case StringeeClientEvents.didFailWithError:
int code = map['body']['code'];
String msg = map['body']['message'];
handleDidFailWithErrorEvent(code,msg);
break;
case StringeeClientEvents.requestAccessToken:
handleRequestAccessTokenEvent();
break;
case StringeeClientEvents.didReceiveCustomMessage:
handleDidReceiveCustomMessageEvent(map['body']);
break;
case StringeeClientEvents.timeoutInQueue:
handleTimeoutInQueueEvent(map['body']);
break;
case StringeeClientEvents.conversationEnded:
handleConversationEndedEvent(map['body']);
break;
case StringeeClientEvents.userBeginTyping:
handleUserBeginTypingEvent(map['body']);
break;
case StringeeClientEvents.userEndTyping:
handleUserEndTypingEvent(map['body']);
break;
default:
break;
}
});
...
chatSubscription = chat.eventStreamController.stream.listen((event) {
Map<dynamic, dynamic> map = event;
if (map['eventType'] == StringeeChatEvents.didReceiveObjectChange) {
handleDidReceiveObjectChangeEvent(map['body']);
}
});
...
/// Invoked when the StringeeClient is connected
void handleDidConnectEvent() {
isClientConnected = true;
}
/// Invoked when the StringeeClient is disconnected
void handleDidDisconnectEvent() {}
/// Invoked when the StringeeClient connection fails
void handleDidFailWithErrorEvent(int code, String message) {}
/// Invoked when your token is expired
void handleRequestAccessTokenEvent() {}
/// Invoked when get Custom message
void handleDidReceiveCustomMessageEvent(Map<dynamic, dynamic> map) {}
/// Invoked when no agent answer this chat and time out route in queue
void handleTimeoutInQueueEvent(Map<dynamic, dynamic> map) {}
/// Invoked when conversation ended
void handleConversationEndedEvent(Map<dynamic, dynamic> map) {}
/// Invoked when a user sends a begin typing event
void handleUserBeginTypingEvent(Map<dynamic, dynamic> map) {}
/// Invoked when a user sends an end typing event
void handleUserEndTypingEvent(Map<dynamic, dynamic> map) {}
/// Invoked when a chat change event is received
void handleDidReceiveObjectChangeEvent(StringeeObjectChange stringeeObjectChange) {}
Call connect(...) on the StringeeClient object:
...
client.connect(token);
...
Before starting a live chat conversation, you can update the customer information to Stringee Server, so your agent can know more about your customer (where is the customer from? what type of cell phone the customer using?...). Call updateUserInfo(...) on the StringeeChat object:
if (!isClientConnected || queueId == null) {
return;
}
chat.updateUserInfo(
name: 'USER_NAME',
email: 'USER_EMAIL',
avatar: 'USER_AVATAR',
).then((value) {
bool status = value['status'];
if (status) {
}
});
After StringeeClientEvents.didConnect is received and queueId has been selected from the profile, start a live chat conversation by calling chat.createLiveChatConversation(...):
chat.createLiveChatConversation(queueId!).then((value) {
bool status = value['status'];
if (status) {
conversation = value['body'];
}
});
In which:
Follow this instruction Messages
To end the live chat conversation, call endChat() on the StringeeConversation object:
final activeConversation = conversation;
if (activeConversation == null) {
return;
}
activeConversation.endChat().then((value) {
bool status = value['status'];
if (status) {
}
});
Next, we will connect to Stringee Server. You must do this before you can start a live chat conversation.
Register the client's events and chat's events.
clientSubscription = client.eventStreamController.stream.listen((event) {
Map<dynamic, dynamic> map = event;
switch (map['eventType']) {
case StringeeClientEvents.didConnect:
handleDidConnectEvent();
break;
case StringeeClientEvents.didDisconnect:
handleDidDisconnectEvent();
break;
case StringeeClientEvents.didFailWithError:
int code = map['body']['code'];
String msg = map['body']['message'];
handleDidFailWithErrorEvent(code,msg);
break;
case StringeeClientEvents.requestAccessToken:
handleRequestAccessTokenEvent();
break;
case StringeeClientEvents.didReceiveCustomMessage:
handleDidReceiveCustomMessageEvent(map['body']);
break;
case StringeeClientEvents.didReceiveChatRequest:
handleDidReceiveChatRequestEvent(map['body']);
break;
case StringeeClientEvents.didReceiveTransferChatRequest:
handleDidReceiveTransferChatRequestEvent(map['body']);
break;
case StringeeClientEvents.timeoutAnswerChat:
handleTimeoutAnswerChatEvent(map['body']);
break;
case StringeeClientEvents.conversationEnded:
handleConversationEndedEvent(map['body']);
break;
case StringeeClientEvents.userBeginTyping:
handleUserBeginTypingEvent(map['body']);
break;
case StringeeClientEvents.userEndTyping:
handleUserEndTypingEvent(map['body']);
break;
default:
break;
}
});
...
chatSubscription = chat.eventStreamController.stream.listen((event) {
Map<dynamic, dynamic> map = event;
if (map['eventType'] == StringeeChatEvents.didReceiveObjectChange) {
handleDidReceiveObjectChangeEvent(map['body']);
}
});
...
/// Invoked when the StringeeClient is connected
void handleDidConnectEvent() {}
/// Invoked when the StringeeClient is disconnected
void handleDidDisconnectEvent() {}
/// Invoked when the StringeeClient connection fails
void handleDidFailWithErrorEvent(int code, String message) {}
/// Invoked when your token is expired
void handleRequestAccessTokenEvent() {}
/// Invoked when get Custom message
void handleDidReceiveCustomMessageEvent(Map<dynamic, dynamic> map) {}
/// Invoked when receive chat request
void handleDidReceiveChatRequestEvent(StringeeChatRequest request) {
chatRequest = request;
}
/// Invoked when receive transfer chat request from other agent
void handleDidReceiveTransferChatRequestEvent(StringeeChatRequest request) {
chatRequest = request;
}
/// Invoked when time out chat request for agent
void handleTimeoutAnswerChatEvent(StringeeChatRequest chatRequest) {}
/// Invoked when conversation ended
void handleConversationEndedEvent(Map<dynamic, dynamic> map) {}
/// Invoked when a user sends a begin typing event
void handleUserBeginTypingEvent(Map<dynamic, dynamic> map) {}
/// Invoked when a user sends an end typing event
void handleUserEndTypingEvent(Map<dynamic, dynamic> map) {}
/// Invoked when a chat change event is received
void handleDidReceiveObjectChangeEvent(StringeeObjectChange stringeeObjectChange) {}
Call connect(...) on the StringeeClient object:
String token = '';
...
client.connect(token);
...
After receiving a chat request, agent can accept or reject this chat request.
To accept the chat request, call accept() on the StringeeChatRequest object:
final request = chatRequest;
if (request == null) {
return;
}
request.accept().then((value) {
bool status = value['status'];
if (status) {
chat.getConversationById(request.convId).then((value) {
conversation = value['body'];
});
}
});
After the chat request is accepted, get its conversation by using the conversation ID from the request.
To reject the chat request, call reject() on the StringeeChatRequest object:
final request = chatRequest;
if (request == null) {
return;
}
request.reject().then((value) {
bool status = value['status'];
if (status) {
}
});
Follow this instruction Messages
To end the live chat conversation, call endChat() on the StringeeConversation object:
final activeConversation = conversation;
if (activeConversation == null) {
return;
}
activeConversation.endChat().then((value) {
bool status = value['status'];
if (status) {
}
});
Customers can create a ticket when live chat is unavailable, for example outside business hours. Call createLiveChatTicket(...) on the StringeeChat object:
chat.createLiveChatTicket('YOUR_WIDGET_KEY', 'CUSTOMER_NAME', 'CUSTOMER_EMAIL', 'TICKET_DESCRIPTION').then((value) {
bool status = value['status'];
if (status) {
}
});
To send the chat content by email, call sendChatTranscript(...) on the StringeeConversation object:
conversation.sendChatTranscript('EMAIL', 'DOMAIN').then((value) {
bool status = value['status'];
if (status) {
}
});
You can view a completed version of this sample app on GitHub: Stringee Flutter plugin example