Kindly Web View SDK
Integrate the Kindly web view SDK into an iOS, Android, Flutter or React Native app. The SDK shows Kindly's web chat widget in a native web view and connects it to the app through a bridge that validates every message: the app starts the chat, shows and hides it, sends messages, triggers dialogues, passes context, authenticates its users and listens to chat events. The chat's look, texts and behaviour come from the bot's settings in the Kindly platform
This guide matches version 1.0.1 of the four packages, which share one version. The documentation at https://docs.kindly.ai/sdk/web-view-sdk is the reference when something here differs
Invoke this skill when
- The user asks to add Kindly's chat, the Kindly web chat or the Kindly web view SDK to an iOS, Android, Flutter or React Native app
- The user mentions KindlyWebViewSDK, KindlyWebView, sdk-chat-webview, ai.kindly:sdk-webview, kindly_webview or @kindly-ai/react-native-webview
- The app uses the native Kindly SDK (KindlySDK, ai.kindly:sdk, the kindly pub package or @kindly-ai/react-native) and the user wants the web chat instead of it or beside it
Before you start
The SDK needs two values from the Kindly platform: the bot key, and the slug of a market configured for the bot (Settings, General, Details & markets). The market is required and there is no fallback to another one. When the project does not hold them, ask the user for both. Never invent either value
Phase 1: Detect
Find out which kind of app this is and what is already there. Run the block for the platform you find:
# Which kind of app
ls Package.swift *.xcodeproj *.xcworkspace build.gradle build.gradle.kts pubspec.yaml package.json 2>/dev/null
# Native iOS: Kindly already added, deployment target, entry point, usage descriptions
grep -rlE 'sdk-chat-webview|sdk-chat-ios' --include='*.pbxproj' --include='Package.swift' --include='Package.resolved' . 2>/dev/null
grep -rhoE 'IPHONEOS_DEPLOYMENT_TARGET = [0-9.]+' --include='*.pbxproj' . 2>/dev/null | sort -u
grep -rlE '@main|UIApplicationMain' --include='*.swift' . 2>/dev/null | head -5
grep -rlE 'NSCameraUsageDescription|NSPhotoLibraryAddUsageDescription|WKAppBoundDomains' --include='*.plist' . 2>/dev/null
# Native Android: Kindly already added, SDK levels, Application class, camera permission
grep -E 'ai\.kindly' build.gradle* app/build.gradle* gradle/libs.versions.toml 2>/dev/null
grep -E 'minSdk|compileSdk' app/build.gradle* 2>/dev/null
grep -rlE ': Application\(\)' --include='*.kt' app/src/main 2>/dev/null | head -3
grep -E 'android:name=|android.permission.CAMERA' app/src/main/AndroidManifest.xml 2>/dev/null
# Flutter
grep -nE '^\s+(kindly|kindly_webview):' pubspec.yaml
grep -nE "platform :ios" ios/Podfile 2>/dev/null
grep -nE 'repositoriesMode' android/settings.gradle* 2>/dev/null
# React Native
grep -nE '"react-native"|"@kindly-ai/react-native(-webview)?"' package.json
grep -nE "platform :ios" ios/Podfile 2>/dev/null
grep -nE 'repositoriesMode' android/settings.gradle* 2>/dev/nullWhat to note:
Question | Why it matters |
|---|---|
Native iOS, native Android, Flutter or React Native | Picks the package and the steps below |
The web view SDK already in the project | Skip to the first step that is missing |
The native Kindly SDK in the project | Both can stay, see Next to the native SDK below |
iOS deployment target | 15.4 or later on every platform |
Android minSdk | 21 or later for a native app, 24 or later for Flutter and React Native |
React Native version | 0.82 or later, with the New Architecture |
Where the app starts | start goes there |
Usage descriptions in Info.plist | The chat needs all four, see Phase 3 |
Phase 2: Install
Native iOS
Swift Package Manager only. The SDK is a signed binary, KindlyWebView.xcframework, and there is no CocoaPods pod for native iOS apps. In a Package.swift:
dependencies: [
.package(url: "https://github.com/kindly-ai/sdk-chat-webview.git", from: "1.0.1"),
],
targets: [
.target(name: "YourApp", dependencies: [
.product(name: "KindlyWebView", package: "sdk-chat-webview"),
]),
]In an Xcode project, add the package in Xcode: File > Add Package Dependencies, the URL https://github.com/kindly-ai/sdk-chat-webview, then the KindlyWebView product on the app target. Editing project.pbxproj by hand is error-prone, so when you cannot run Xcode, ask the user to do this step. A beta, X.Y.Z-beta.N, needs an exact pin such as exact: "X.Y.Z-beta.N", because from: never resolves a prerelease
Native Android
The SDK is on Maven Central. Kotlin DSL:
dependencies {
implementation("ai.kindly:sdk-webview:1.0.1")
}Groovy:
dependencies {
implementation 'ai.kindly:sdk-webview:1.0.1'
}The project's repositories need google() and mavenCentral(). Pin an exact version, because a dynamic one such as 1.+ can resolve to a beta. Requirements: compileSdk 35 or later, and Kotlin 1.9.20 or later when the app is written in Kotlin. The SDK brings kotlinx-coroutines-core and depends on AndroidX WebKit, OkHttp and Sentry's JVM core io.sentry:sentry 8
Flutter
dependencies:
kindly_webview: ^1.0.1Then run flutter pub get. Requirements: Flutter 3.27 or later, Dart 3.6 or later, Android compileSdk 36 or later. The native SDK ships inside the package, so the app adds nothing else
React Native
yarn add @kindly-ai/[email protected]
cd ios && pod installWith npm: npm install @kindly-ai/[email protected]. Autolinking does the rest, and the native SDK ships inside the package. A beta is published under the npm dist-tag beta, so a plain install never picks one
Phase 3: App setup
Usage descriptions on iOS
Every iOS app needs these four keys in its Info.plist (ios/Runner/Info.plist in Flutter). The chat lets people attach photos and videos and save images, and iOS ends an app that reaches one of these features without its usage description. Word the strings for the app:
<key>NSCameraUsageDescription</key>
<string>Take a photo or video to send in the chat</string>
<key>NSMicrophoneUsageDescription</key>
<string>Record a video with sound to send in the chat</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Choose photos and videos to send in the chat</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Save images from the chat to your photo library</string>If the app declares WKAppBoundDomains, add chat.kindlycdn.com to it, or the chat cannot run. No LSApplicationQueriesSchemes entries are needed
Deployment target
- Native iOS: 15.4 or later on the app target
- Flutter: 15.4 or later on the Runner target, and platform :ios, '15.4' in ios/Podfile with CocoaPods
- React Native: platform :ios, '15.4' or later in ios/Podfile, before pod install
An app built with the Xcode 27 SDK must adopt the UIScene lifecycle, or iOS 27 stops it at launch. That is Apple's rule for every app, and the SDK works under scenes. In Flutter, declare a scene configuration with FlutterSceneDelegate as its delegate class, as Flutter's UIScene migration guide shows
Android
Nothing to add. The SDK's manifest brings the INTERNET permission, its chat activity, a FileProvider with the authority ${applicationId}.kindly.webview.fileprovider and a <queries> entry for the camera, and its R8 rules ship inside the package
- Flutter: the plugin resolves ai.kindly:sdk-webview only from the Maven repository bundled in the package. Do not declare another version of that artifact, and keep the default repositoriesMode in android/settings.gradle, because PREFER_SETTINGS and FAIL_ON_PROJECT_REPOS ignore or refuse that repository
- React Native: the package registers its bundled copy of ai.kindly:sdk-webview as the only source for that artifact, so do not declare another version. If android/settings.gradle sets repositoriesMode to PREFER_SETTINGS, add node_modules/@kindly-ai/react-native-webview/android/maven-repo to the settings repositories
The bot
The chat page runs on https://chat.kindlycdn.com, and the SDK sends the app's iOS bundle id or Android package name to the Kindly chat backend. A bot that only allows listed domains must list them, as for the native Kindly SDK. Tell the user to check this in the Kindly platform; never change a bot's settings yourself
Phase 4: Start the SDK
Call start once when the app starts. It does not load the chat yet: the chat page is created the first time the chat is shown. It does start the SDK's usage metrics and error reports, so when the app asks for the user's consent before collecting data, call start after the user gives it. languageCode defaults to en
Native iOS, UIKit
import KindlyWebView
import UIKit
@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
KindlyWebViewSDK.start(botKey: "YOUR_BOT_KEY", languageCode: "en", market: "YOUR_MARKET")
return true
}
}Native iOS, SwiftUI
import KindlyWebView
import SwiftUI
@main
struct MyApp: App {
init() {
KindlyWebViewSDK.start(botKey: "YOUR_BOT_KEY", languageCode: "en", market: "YOUR_MARKET")
}
var body: some Scene {
WindowGroup { ContentView() }
}
}Every member of KindlyWebViewSDK is static and can be called from any thread
Native Android
import ai.kindly.webview.KindlyWebViewSDK
import android.app.Application
class App : Application() {
override fun onCreate() {
super.onCreate()
KindlyWebViewSDK.start(
application = this,
botKey = "YOUR_BOT_KEY",
languageCode = "en",
market = "YOUR_MARKET",
)
}
}Register the class with android:name=".App" on the <application> element of AndroidManifest.xml when the app has no Application class yet. Every function can be called from any thread
Flutter
import 'package:flutter/widgets.dart';
import 'package:kindly_webview/kindly_webview.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await KindlyWebViewSDK.start(botKey: 'YOUR_BOT_KEY', market: 'YOUR_MARKET', languageCode: 'en');
runApp(const MyApp());
}React Native
In index.js, so every JavaScript reload calls it again:
import { AppRegistry } from 'react-native';
import { KindlyWebViewSDK } from '@kindly-ai/react-native-webview';
import App from './App';
import { name as appName } from './app.json';
KindlyWebViewSDK.start({ botKey: 'YOUR_BOT_KEY', market: 'YOUR_MARKET', languageCode: 'en' }).catch((error) => {
console.warn('Kindly start failed', error);
});
AppRegistry.registerComponent(appName, () => App);Argument rules
The bot key, market and language code are trimmed. A bot key is 8 to 64 letters, digits and hyphens, a market 1 to 64 letters, digits, _ and -, and a language code looks like en, nb or pt-BR. iOS and Android refuse anything else with an error in the log and do nothing, Flutter throws an ArgumentError and React Native rejects with INVALID_ARGUMENT
Calling start again with the same bot key and market keeps the live chat and replaces the language, for the next chat page, and the auth provider. A call without an auth provider removes it. A different bot key or market closes the chat and starts over
Phase 5: Show the chat
From a button or wherever the app offers help:
KindlyWebViewSDK.displayChat() // iOSKindlyWebViewSDK.launchChat(activity) // Android, from an Activityawait KindlyWebViewSDK.displayChat(); // Flutterawait KindlyWebViewSDK.displayChat(); // React NativeOn iOS the chat opens as a full-height sheet over the top view controller, and on Android on its own full-screen screen. People close it with the chat's minimise button, by swiping the sheet down on iOS or with the back button on Android, and the conversation stays. The first display loads the widget, later ones reopen the same conversation at once. Pass triggerDialogueId to start a dialogue as the chat opens, or languageCode to show the chat in another language. On Android pass an Activity when you can; with another context the chat starts in a new task. Before start, iOS and Android log an error and do nothing, and Flutter and React Native fail with NOT_STARTED
Common tasks
Close, end or kill
Call | Chat screen | Conversation | SDK |
|---|---|---|---|
closeChat(), Android close() | Dismissed | Kept, the page stays loaded | Started |
endChat() | Dismissed | Ended, the next display starts a new one | Started |
kill() | Dismissed | Ended | Stopped until the next start |
KindlyWebViewSDK.closeChat()
await KindlyWebViewSDK.endChat()
await KindlyWebViewSDK.kill()KindlyWebViewSDK.close()
lifecycleScope.launch { KindlyWebViewSDK.endChat().await() }
lifecycleScope.launch { KindlyWebViewSDK.kill().await() }Flutter and React Native: await KindlyWebViewSDK.closeChat(), await KindlyWebViewSDK.endChat(), await KindlyWebViewSDK.kill()
The conversation is stored in the app's web view storage for chat.kindlycdn.com, per bot and market, and survives app restarts. endChat and kill delete it, so call one of them when the user signs out of the app. kill keeps the link delegate and forgets the auth provider
Send a message as the user
try await KindlyWebViewSDK.sendMessage("I need help with my order", newContext: ["orderId": "1234"])KindlyWebViewSDK.sendMessage("I need help with my order", mapOf("orderId" to "1234")).await()await KindlyWebViewSDK.sendMessage('I need help with my order', newContext: {'orderId': '1234'});await KindlyWebViewSDK.sendMessage('I need help with my order', { newContext: { orderId: '1234' } });It needs a chat page, so show the chat at least once first; it may be hidden since, and then the message goes without showing the chat. Otherwise it fails with the chat-not-ready error. The text is trimmed and can be up to 10,000 characters, and newContext goes with this message only
Trigger a dialogue
KindlyWebViewSDK.triggerDialogue(id: "DIALOGUE_ID")KindlyWebViewSDK.triggerDialogue("DIALOGUE_ID")await KindlyWebViewSDK.triggerDialogue('DIALOGUE_ID');await KindlyWebViewSDK.triggerDialogue('DIALOGUE_ID');It also needs a chat page, and runs without opening the chat while it is hidden. Without a page it does nothing, and the SDK logs an error on iOS and a warning on Android. A dialogue id is 1 to 128 letters, digits, _ and -
Context
KindlyWebViewSDK.setNewContext(["plan": "gold"])
KindlyWebViewSDK.clearNewContext()KindlyWebViewSDK.setNewContext(mapOf("plan" to "gold"))
KindlyWebViewSDK.clearNewContext()await KindlyWebViewSDK.setNewContext({'plan': 'gold'});
await KindlyWebViewSDK.clearNewContext();KindlyWebViewSDK.setNewContext({ plan: 'gold' });
KindlyWebViewSDK.clearNewContext();Context goes with the next message, button click or triggered dialogue, once. The chat merges it with context it already holds, so two calls before the next message send both maps. A map holds up to 100 string entries, keys of 1 to 256 characters other than __proto__, constructor and prototype, and values of up to 4,096 characters
Authentication
Pass a provider to start. It gets the chat id and returns a JWT or opaque bearer token for the user signed in to the app:
KindlyWebViewSDK.start(botKey: "YOUR_BOT_KEY", market: "YOUR_MARKET", authTokenProvider: { chatId in
try await MyBackend.kindlyToken(chatId: chatId)
})KindlyWebViewSDK.start(
application = this,
botKey = "YOUR_BOT_KEY",
market = "YOUR_MARKET",
authTokenProvider = KindlyAuthTokenProvider { request -> myBackend.kindlyToken(request.chatId) },
)await KindlyWebViewSDK.start(
botKey: 'YOUR_BOT_KEY',
market: 'YOUR_MARKET',
authTokenCallback: (String chatId) => myBackend.kindlyToken(chatId),
);await KindlyWebViewSDK.start({
botKey: 'YOUR_BOT_KEY',
market: 'YOUR_MARKET',
authTokenCallback: async (chatId) => fetchKindlyToken(chatId),
});MyBackend, myBackend and fetchKindlyToken stand for the app's own call to its backend; tokens come from the backend and a signing key never goes in the app. Call authenticate() after the user signs in and deauthenticate() after they sign out. Credentials providers, the timeouts and the token rules are in AUTH.md
Links
No link opens inside the chat. http, https, mailto, tel and sms links open outside the app, and other schemes are blocked. To handle a link in the app, set a delegate and return false for it:
final class ChatLinks: KindlyWebViewClientDelegate {
func shouldHandleLink(url: URL) async -> Bool {
url.host != "myapp.example"
}
}
let chatLinks = ChatLinks() // keep a reference, the SDK holds it weakly
KindlyWebViewSDK.delegate = chatLinksKindlyWebViewSDK.`interface` = object : KindlyWebViewInteraction {
override suspend fun shouldHandleLink(url: String): Boolean = !url.startsWith("https://myapp.example/")
}await KindlyWebViewSDK.setDelegate(shouldHandleLink: (String url) async => !url.startsWith('https://myapp.example/'));KindlyWebViewSDK.setDelegate({ shouldHandleLink: async (url) => !url.startsWith('https://myapp.example/') });These return false, so the app handles the link, for myapp.example and true for every other link. Open the app's own screen where the delegate returns false. Timeouts, limits and patterns are in LINKS.md
Events and state
import Combine
var subscriptions = Set<AnyCancellable>()
KindlyWebViewSDK.events
.sink { event in print(event.rawType) }
.store(in: &subscriptions)
KindlyWebViewSDK.state
.sink { state in print(state.connectionState) }
.store(in: &subscriptions)lifecycleScope.launch { KindlyWebViewSDK.events.collect { event -> Log.d("Chat", event.rawType) } }
lifecycleScope.launch { KindlyWebViewSDK.state.collect { state -> Log.d("Chat", state.connectionState) } }final events = KindlyWebViewSDK.events.listen((KindlyWebViewEvent event) => debugPrint(event.rawType));
final state = KindlyWebViewSDK.state.listen((KindlyWebViewState state) => debugPrint(state.rawConnectionState));const events = KindlyWebViewSDK.addEventListener((event) => console.log(event.rawType));
const state = KindlyWebViewSDK.addStateListener((s) => console.log(s.connectionState));Events are not replayed, and a new state listener gets the current state first. Message events carry chat content, so keep them out of logs. Event types, payloads and their limits are in EVENTS.md
Logging and crash reporting
Platform | Debug logs, off by default | Crash reporting to Kindly, on by default |
|---|---|---|
iOS, Android | KindlyWebViewSDK.verboseLogging = true | KindlyWebViewSDK.enableCrashReporting = false |
Flutter | await KindlyWebViewSDK.setVerboseLogging(true) | await KindlyWebViewSDK.setCrashReporting(false) |
React Native | KindlyWebViewSDK.setVerboseLogging(true) | KindlyWebViewSDK.setCrashReporting(false) |
Set both before start. Logs go to the iOS unified log under the subsystem ai.kindly.webview and to Logcat under the tag KindlyWebView, and never contain chat content, tokens or URL paths
Privacy declarations
The app's App Store privacy details and Google Play Data safety form must cover what the SDK sends: usage metrics with a random device ID, error reports and the conversation. Privacy and Data maps each to the stores' data types and covers consent and bots that answer with third-party generative AI. The declarations are the user's to make, so point them to that page rather than deciding for them
Checking support
KindlyWebViewSDK.isSupported on iOS, KindlyWebViewSDK.isSupported(context) on Android, and await KindlyWebViewSDK.isSupported() in Flutter and React Native are false when the device's web view cannot run the chat (on Android a WebView older than version 85) or, on iOS, when the app declares WKAppBoundDomains without chat.kindlycdn.com. Showing the chat then opens a notice instead. Use it to hide the way into the chat
Next to the native Kindly SDK
Both SDKs can be in one app, with separate state, storage and conversations. On iOS, qualify the type names both modules have, such as KindlyWebView.KindlyEvent. On Android, import one of them under another name, such as import ai.kindly.webview.models.KindlyEvent as KindlyWebViewEvent. Every Flutter and React Native type of the web view packages starts with KindlyWebView
Core public surface
iOS, KindlyWebViewSDK
API | Purpose |
|---|---|
start(botKey:languageCode:market:authTokenProvider:) | Start the SDK, optionally with a token provider |
start(botKey:languageCode:market:authCredentialsProvider:) | Start the SDK with a credentials provider |
displayChat(languageCode:triggerDialogueId:) | Show the chat |
closeChat() | Hide the chat, keep the conversation |
endChat() async | End the conversation |
kill() async | End the conversation and stop the SDK |
sendMessage(_:newContext:) async throws | Send a message as the user |
triggerDialogue(id:) | Start a dialogue |
setNewContext(_:), clearNewContext() | Context for the next message |
authenticate() async throws, deauthenticate() async throws | Sign the chat in and out |
delegate: KindlyWebViewClientDelegate? | Link interception, held weakly |
events: AnyPublisher<KindlyEvent, Never> | Every event, on the main thread |
state: AnyPublisher<KindlyEventState, Never>, currentState | The SDK state |
isSupported | Whether the chat can run here |
verboseLogging, enableCrashReporting | Logging and crash reporting |
KindlyAuthCredentials(idToken:accessToken:issuer:expiresAt:) | Credentials, at least one token |
KindlyWebViewError | The thrown errors |
Android, KindlyWebViewSDK
API | Purpose |
|---|---|
start(application, botKey, languageCode, market, authTokenProvider, authCredentialsProvider) | Start the SDK. The providers are optional |
launchChat(context, triggerDialogueId, languageCode), displayChat(context) | Show the chat |
close() | Hide the chat, keep the conversation |
endChat(): Deferred<Unit> | End the conversation |
kill(): Deferred<Unit> | End the conversation and stop the SDK |
sendMessage(message, newContext): Deferred<Unit> | Send a message as the user |
triggerDialogue(id) | Start a dialogue |
setNewContext(context), clearNewContext() | Context for the next message |
authenticate(): Deferred<Unit>, deauthenticate(): Deferred<Unit> | Sign the chat in and out |
`interface`: KindlyWebViewInteraction? | Link interception |
events: Flow<KindlyEvent> | Every event |
state: Flow<KindlyEventState>, currentState | The SDK state |
isSupported(context) | Whether the chat can run here |
verboseLogging, enableCrashReporting | Logging and crash reporting |
KindlyAuthTokenProvider, KindlyAuthCredentialsProvider, AuthTokenRequest | Auth providers |
KindlyWebViewException | The failures of the Deferred results |
Flutter, KindlyWebViewSDK
API | Purpose |
|---|---|
start(botKey:, market:, languageCode:, authTokenCallback:, authCredentialsCallback:) | Start the SDK |
displayChat(languageCode:, triggerDialogueId:), launchChat(...) | Show the chat |
closeChat(), endChat(), kill() | Hide, end, stop |
sendMessage(message, newContext:) | Send a message as the user |
triggerDialogue(dialogueId) | Start a dialogue |
setNewContext(context), clearNewContext() | Context for the next message |
authenticate(), deauthenticate() | Sign the chat in and out |
setDelegate(shouldHandleLink:), clearDelegate() | Link interception |
events, state, currentState() | Events and state |
isSupported() | Whether the chat can run here |
setVerboseLogging(enabled), setCrashReporting(enabled) | Logging and crash reporting |
KindlyWebViewAuthCredentials, KindlyWebViewException | Credentials and errors |
React Native, KindlyWebViewSDK
API | Purpose |
|---|---|
start({ botKey, market, languageCode?, authTokenCallback?, authCredentialsCallback? }) | Start the SDK |
displayChat({ languageCode?, triggerDialogueId? }), launchChat(...) | Show the chat |
closeChat(), endChat(), kill() | Hide, end, stop |
sendMessage(message, { newContext? }) | Send a message as the user |
triggerDialogue(dialogueId) | Start a dialogue |
setNewContext(map), clearNewContext() | Context for the next message |
authenticate(), deauthenticate() | Sign the chat in and out |
setDelegate({ shouldHandleLink }), setDelegate(null) | Link interception |
addEventListener(listener), addStateListener(listener), getState() | Events and state |
isSupported() | Whether the chat can run here |
setVerboseLogging(enabled), setCrashReporting(enabled) | Logging and crash reporting |
KindlyWebViewError | The rejections, with a code |
Verification
- Build and run the app, then show the chat. It loads within a few seconds and shows the bot's greeting
- Turn on the debug logs and watch them, see Logging and crash reporting. A refused value, such as a market in the wrong format, shows up there as an error
- Subscribe to the state: connectionState goes from none to loading to connected when the chat page loads
- Send a message in the chat and see the bot answer. With the chat open, a message event arrives
- On iOS, attach a photo in the chat to prove the usage descriptions are in place
Troubleshooting
Symptom | Fix |
|---|---|
Nothing happens when the chat should show, and the log says the call came before start | start did not run, or refused its arguments, see Argument rules |
The chat shows an error about 20 seconds after it opens, and connectionState is failed | The market slug is not one configured for the bot, or the bot's settings for that market lack the web chat's translations. Check the slug, then ask Kindly support with the bot key and market |
The chat never connects on a bot that only allows listed domains | Add the app's iOS bundle id and Android package name to the bot's allowed domains |
The app quits when someone attaches a photo or saves an image on iOS | A usage description is missing from Info.plist, see Phase 3 |
A notice says the chat is not supported | See Checking support. On iOS, check WKAppBoundDomains |
sendMessage fails with the chat-not-ready error | Show the chat once first |
A link in the chat opens the browser instead of the app | Set the link delegate. A custom scheme such as myapp:// never reaches it, link to an https address instead |
The chat stays anonymous | Pass a provider to start on every call, and see the debugging steps in AUTH.md |
No message events for messages the user can see | Message events come only while the chat is open, see EVENTS.md |
Gradle cannot resolve ai.kindly:sdk-webview in Flutter or React Native | See the repositoriesMode notes in Phase 3 |
pod install fails on the deployment target | Set platform :ios, '15.4' or later in ios/Podfile |
Two types named KindlyEvent clash | See Next to the native Kindly SDK |
Deep reference
Topic | Fetch with |
|---|---|
Token and credentials providers on every platform, the token rules, timeouts, signing in and out, debugging | Use curl to download, read and follow: https://docs.kindly.ai/sdk/web-view-sdk-skill-auth.md |
Every event type and payload field on every platform, message event timing, state | Use curl to download, read and follow: https://docs.kindly.ai/sdk/web-view-sdk-skill-events.md |
The link delegate on every platform, what opens outside the app, timeouts and limits | Use curl to download, read and follow: https://docs.kindly.ai/sdk/web-view-sdk-skill-links.md |