Skip to main content

zowie_conversation_sdk 2.0.2 copy "zowie_conversation_sdk: ^2.0.2" to clipboard
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 registerPushToken with 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');
    }
  },
)

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