zowie_conversation_sdk 2.0.2
zowie_conversation_sdk: ^2.0.2 copied to clipboard
Zowie Conversation SDK for Flutter — embed the Zowie chat and your AI agent in your Flutter app.
Zowie Conversation SDK for Flutter #
Embed the Zowie chat and your AI agent in your Flutter app with a single widget.
Requirements #
- Flutter 3.38.1+
- Dart 3.10+
- Android: minSdk 21, compileSdk 37
- iOS: 15.0+
The compileSdk 37 requirement comes from the latest permission_handler. If your
app cannot compile against SDK 37 yet, pin an older version in your app's
pubspec.yaml, which lowers the requirement to compileSdk 35:
dependencies:
permission_handler: ^12.0.0
Installation #
flutter pub add zowie_conversation_sdk
Quick start #
import 'package:zowie_conversation_sdk/zowie_conversation_sdk.dart';
class ChatScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ZowieChat(
config: ZowieChatConfig(
baseUrl: 'https://<slug>.chat.getzowie.com',
instanceId: '<your-instance-id>',
),
),
);
}
}
Configuration #
ZowieChatConfig accepts these parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
baseUrl |
String |
required | Base origin of your Zowie deployment, e.g. https://<slug>.chat.getzowie.com |
instanceId |
String |
required | Your Zowie instance ID |
metadata |
ZowieChatMetadata? |
null |
User metadata (name, email, etc.) |
externalAccessToken |
String? |
null |
Token for authenticated users |
context |
String? |
null |
Context string for the conversation |
resetSession |
bool |
false |
Start a fresh session |
voiceExperienceEnabled |
bool? |
null |
Override voice experience toggle |
voiceBlobColor |
String? |
null |
Override voice blob color |
title |
String? |
null |
Override chat header title |
primaryColor |
String? |
null |
Override primary brand color |
fontColor |
FontColor? |
null |
Override font color (white/black) |
userMessageBackgroundColor |
String? |
null |
Override user message bubble background color |
userMessageFontColor |
FontColor? |
null |
Override user message bubble text color |
logoUrl |
String? |
null |
Override header logo URL |
themeMode |
ZowieChatThemeMode? |
null |
Override theme (system/light/dark) |
headerVisible |
bool |
false |
Whether the chat header is visible |
initialConversationMode |
ConversationMode |
text |
Start in text or voice mode |
referral |
String |
"start" |
Referral ID for the initial message |
initialUserMessage |
String? |
null |
Auto-send a user message on start |
versionType |
VersionType |
production |
AI agent version the conversation runs against (production or staging) |
Testing against the staging version of your AI agent #
Set versionType: VersionType.staging to run the conversation against the AI
agent's current staging version instead of the published version, so the AI agent
can be tried out from the app before it goes live:
const config = ZowieChatConfig(
baseUrl: baseUrl,
instanceId: instanceId,
versionType: VersionType.staging,
);
Leave it at production in release builds.
Controller #
Use ZowieChatController to interact with the chat programmatically:
class ChatScreen extends StatefulWidget {
@override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final _controller = ZowieChatController.create();
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: ZowieChat(
config: ZowieChatConfig(
baseUrl: 'https://<slug>.chat.getzowie.com',
instanceId: '<your-instance-id>',
),
controller: _controller,
),
),
ElevatedButton(
onPressed: () => _controller.sendMessage('Hello!'),
child: Text('Send message'),
),
],
);
}
}
Methods #
| Method | Description |
|---|---|
sendMessage(String message) |
Send a message on behalf of the user |
sendReferral(String referralId) |
Trigger a referral |
updateMetadata(ZowieChatMetadata metadata) |
Update user metadata |
setVisible(bool visible) |
Show or hide the chat |
showCsat({onCompleted}) |
Display the CSAT survey. Optional onCompleted callback fires when the user submits or dismisses it. |
startChat() |
Start a new conversation (no-op if one is active) |
endChat() |
Clear the stored session and current conversation (use on logout) |
getConversationId() |
Get the current conversation ID |
registerPushToken(String token) |
Register an FCM registration token for push notifications |
deregisterPushToken() |
Deregister the current device token |
Controller methods called before the chat is loaded are silently dropped.
Push Notifications #
The SDK can register a device token with the Zowie backend so the user receives push notifications for new messages. The host app is responsible for Firebase/push notification setup — the SDK only handles token registration.
Zowie sends push notifications through Firebase Cloud Messaging, so pass the FCM
registration token on both Android and iOS. On iOS, do not pass the APNs device
token (FirebaseMessaging.instance.getAPNSToken()) — it is rejected.
// Register when your push library returns a token
final token = await FirebaseMessaging.instance.getToken();
if (token != null) {
_controller.registerPushToken(token);
}
// Deregister when the user opts out
_controller.deregisterPushToken();
Notes:
- If the chat session is not yet authenticated, the SDK queues the token and flushes it automatically when authentication completes.
- Multiple calls to
registerPushTokenwith different tokens are safe — the latest token wins. - The token is automatically cleared when the chat ends or the session expires.
Events #
Listen to chat events via the onEvent callback:
ZowieChat(
config: config,
onEvent: (event) {
switch (event) {
case ZowieChatLoaded():
print('Chat loaded');
case ZowieChatStarted(conversationId: final id):
print('Chat started: $id');
case ZowieChatEnded():
print('Chat ended');
case ZowieChatMessageSent(message: final msg):
print('Sent: $msg');
case ZowieChatMessageReceived(payload: final p):
print('Received: $p');
case ZowieChatUnreadMessagesCountChanged(count: final c):
print('Unread: $c');
case ZowieChatSessionExpired():
print('Session expired');
case ZowieChatMinimized():
print('Minimized');
case ZowieChatConfigError(error: final e):
print('Config error: $e');
case ZowieChatGenericEvent(name: final n, params: final p):
print('Backend event: $n $p');
}
},
)
Link handling #
By default, external links open in the system browser. To intercept them:
ZowieChat(
config: config,
onLinkPress: (url) {
// Return true if you handled the link, false for default behavior
print('Link pressed: $url');
return false;
},
)
Download handling #
By default, base64 downloads are saved to a temp file and shared via the system share sheet. URL downloads open in the browser.
ZowieChat(
config: config,
onDownload: (download) {
// Return true if you handled the download, false for default behavior
print('Download: ${download.filename}');
return false;
},
)
Back handling (Android) #
On Android, you can intercept the system back gesture while the chat is showing:
ZowieChat(
config: config,
onAndroidBackPress: () {
// Return true if you consumed the back press, false to let it propagate
Navigator.of(context).pop();
return true;
},
)
The handler is only active on Android — on iOS it is ignored.
AI session notice #
Override the "more" action in the AI session notice banner:
ZowieChat(
config: config,
onAiSessionNoticeMorePress: (header, message) {
print('AI notice: $header — $message');
},
)
When set, the SDK tells core to delegate the tap instead of showing its own
modal. The message may contain markdown.
Permissions #
The SDK declares only android.permission.INTERNET. Anything else you declare
yourself, so an app that does not use voice is never forced to ask for the
microphone.
Voice (microphone) #
Add to your AndroidManifest.xml:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
The SDK requests RECORD_AUDIO at runtime the first time the chat asks for
audio capture. MODIFY_AUDIO_SETTINGS is a normal permission (no runtime
prompt) required by WebRTC for audio routing.
On iOS, add to your Info.plist:
<key>NSMicrophoneUsageDescription</key>
<string>Required for voice conversations</string>
Photo upload (camera) #
Only needed if users take photos via the in-chat file picker.
On iOS, add to your Info.plist:
<key>NSCameraUsageDescription</key>
<string>Required to take and send photos in the chat</string>
On Android no setup is needed. Tapping the attachment button opens a sheet
to pick a file, take a photo or record a video. If your app declares
android.permission.CAMERA (directly or through another library), the SDK asks
for it the first time the user picks the camera.
Performance (Android) #
On Android 14+ devices with Vulkan support, enable
Hybrid Composition++
for significantly smoother WebView rendering. Add to your
AndroidManifest.xml inside <application>:
<meta-data
android:name="io.flutter.embedding.android.EnableHcpp"
android:value="true" />
On older devices this flag is ignored and Flutter falls back to its default Texture Layer compositing automatically.
Session persistence #
Sessions are persisted in platform secure storage (Keychain on iOS, Keystore-backed encryption on Android). To clear a session:
await ZowieChatSession.clearAnonymousSession('your-instance-id');
User metadata #
ZowieChatConfig(
baseUrl: 'https://<slug>.chat.getzowie.com',
instanceId: '<id>',
metadata: ZowieChatMetadata(
firstName: 'Jane',
lastName: 'Doe',
name: 'Jane Doe',
email: 'jane@example.com',
phoneNumber: '+1234567890',
locale: 'en-US',
timezone: 'Europe/Warsaw',
extraParams: {'plan': 'premium'},
),
)
| Field | Type | Description |
|---|---|---|
firstName |
String? |
First name |
lastName |
String? |
Last name |
name |
String? |
Full display name |
email |
String? |
Email address |
phoneNumber |
String? |
Phone number |
locale |
String? |
BCP 47 locale tag — also selects the AI agent's region |
timezone |
String? |
IANA timezone identifier |
extraParams |
Map<String, String>? |
Arbitrary key-value pairs |
Layout #
ZowieChat has no intrinsic size. It must be placed inside a widget that
provides bounded constraints — for example, wrapped in Expanded inside a
Column, or given an explicit height. Placing it inside a ListView or
unbounded SingleChildScrollView will not work.
Types #
ConversationMode #
| Value | Description |
|---|---|
text |
Start the conversation in text mode (default) |
voice |
Start the conversation in voice mode |
FontColor #
| Value |
|---|
white |
black |
ZowieChatThemeMode #
| Value | Description |
|---|---|
system |
Follow the device theme |
light |
Force light theme |
dark |
Force dark theme |
VersionType #
| Value | Description |
|---|---|
production |
Published version (default) |
staging |
Current staging version |
ChatDownload #
| Field | Type | Description |
|---|---|---|
filename |
String |
Suggested file name |
mimeType |
String? |
MIME type of the content |
base64 |
String? |
Base64-encoded file content (inline downloads) |
url |
String? |
URL to download from (URL-based downloads) |
License #
MIT