From Website Widget to Mobile APK: Embedding JestBot Everywhere with the SDK
Why a web-only bot isn't enough
A huge share of usage for consumer and B2B products alike happens inside a native mobile app, not a mobile browser. If your AI support bot only lives on your website, you're covering the smaller half of your traffic. A website widget is great for browsers, but it fundamentally can't be embedded inside a compiled Android APK or an iOS app — those are different runtimes with different rules. That's exactly the gap JestBot's SDK is built to close.
What the SDK actually gives you
JestBot's SDK exposes the same chat, streaming, and tool-calling capabilities that power the website widget and WhatsApp, as a set of REST and WebSocket calls you can wire into your own native chat screen. Instead of an iframe or a webview hack, you get a real client library that fits naturally into a React Native, Kotlin, or Swift codebase, and behaves like any other typed dependency in your project rather than an embedded web page pretending to be native.
Installing and initializing the SDK
npm install @jestbot/sdkimport { JestBotClient } from "@jestbot/sdk";
const client = new JestBotClient({
botId: "YOUR_BOT_ID",
apiKey: process.env.JESTBOT_PUBLIC_KEY,
});
const session = await client.createSession({ userId: currentUser.id });The public API key is scoped for client-side use — it can start sessions and send messages, but it can't read or modify your bot's configuration, so it's safe to ship inside a compiled app without exposing anything sensitive if someone decompiles your APK.
Streaming a reply into your Android app
Just like the website widget, the SDK streams tokens as they're generated instead of waiting for the full response, so your chat UI feels responsive even on a slower mobile connection.
client.sendMessage(session.id, "Do you deliver to Jaipur?", {
onToken: (token) => appendToChatBubble(token),
onComplete: (fullReply) => saveToLocalHistory(fullReply),
onError: (err) => showRetryOption(err),
});A native iOS integration looks just as simple
The same session and streaming model applies on iOS through the Swift package, so a native Swift app gets the same experience as a React Native or Android build, just with the idioms of that platform.
let client = JestBotClient(botId: "YOUR_BOT_ID", apiKey: publicKey)
let session = try await client.createSession(userId: currentUser.id)
try await client.sendMessage(sessionId: session.id, text: userInput) { token in
chatViewModel.appendToken(token)
}Persisting sessions across app restarts
Mobile users close and reopen apps constantly, and a chat history that resets every time feels broken. The SDK lets you persist the session ID locally and resume the same conversation, including the bot's memory of what was already discussed, the next time the user opens the app.
// On app launch
const savedSessionId = await AsyncStorage.getItem("jestbot_session_id");
const session = savedSessionId
? await client.resumeSession(savedSessionId)
: await client.createSession({ userId: currentUser.id });
await AsyncStorage.setItem("jestbot_session_id", session.id);Building a native chat screen
Because the SDK just returns plain text (or streamed tokens) and structured tool results, you're free to design the chat UI however fits your app's design system — bubbles, cards, quick-reply buttons — rather than being stuck with an embedded widget's fixed look.
function ChatScreen() {
const [messages, setMessages] = useState([]);
const handleSend = async (text) => {
setMessages((m) => [...m, { role: "user", text }]);
let botText = "";
await client.sendMessage(session.id, text, {
onToken: (t) => { botText += t; setMessages((m) => [...m.slice(0, -1), { role: "bot", text: botText }]); },
});
};
return <ChatList messages={messages} onSend={handleSend} />;
}Handling offline and flaky connections gracefully
Mobile networks drop far more often than a home wifi connection, so the SDK is built to queue an outgoing message if the connection briefly drops and retry automatically, rather than silently failing and leaving the customer wondering whether their message ever sent. Your UI can hook into a connection-state callback to show a subtle "reconnecting…" indicator rather than a hard error.
client.on("connectionStateChange", (state) => {
if (state === "reconnecting") showBanner("Reconnecting…");
if (state === "connected") hideBanner();
});Push notifications tie-in
When a bot conversation is handed over to a human agent, or when the bot needs to follow up after a tool call finishes (like an order status changing), the SDK can trigger a push notification through your existing notification service, so the customer doesn't have to keep the app open and staring at the screen to get an answer.
Packaging into an APK
None of this is JestBot-specific packaging — you build your Android app the normal way, with the SDK as a dependency, and generate your APK (or app bundle) through your usual Gradle build. The SDK adds no unusual native dependencies beyond standard networking and WebSocket libraries, so it doesn't bloat your build or introduce unusual permissions requirements that might slow down your Play Store review.
./gradlew assembleRelease
# outputs app/build/outputs/apk/release/app-release.apkDebugging and testing before you ship
The SDK exposes a debug mode that logs every request, tool call, and streamed token to your console during development, so you can see exactly what the bot decided to do and why before you build a release APK. It's worth leaving this on through QA and switching it off for your production build.
const client = new JestBotClient({ botId, apiKey, debug: __DEV__ });One bot, one config, every surface
The part that matters most: because the SDK talks to the same bot configuration as the website widget and WhatsApp number, an update to your knowledge base, your instructions, or your available tools instantly applies everywhere — web, WhatsApp, and your packaged mobile APK — without shipping a new app version or retraining anything.
When to reach for the SDK vs. the widget
- Use the website widget when you want a fast, zero-code embed for a marketing site, docs site, or web app
- Use the SDK when you're building or already have a native mobile app and want the bot's UI to match your app's design language exactly
- Use both when your product spans web and mobile — they share the same bot, so there's no duplicate configuration either way
Tool calling and calls from inside the app
Every capability covered elsewhere in this series works through the SDK exactly the way it works through the widget or WhatsApp. A customer inside your app can ask the bot to check whether an item is in stock, and the same tool orchestrator that powers the website widget runs the check and returns a real answer, not a canned response. If your app also has calling built in, a tap-to-call button can route into the same AI calling agent, so a customer who starts in the app and wants to talk it through by voice doesn't have to leave your product and dial a separate number — the handoff from in-app chat to a live or AI-assisted call can happen inside the same session.
Versioning and backward compatibility
Mobile apps update far more slowly than websites — a customer might keep an old version of your APK installed for months after a new one ships, especially if auto-update is disabled or they're on a slow connection. The SDK is versioned and backward compatible across bot configuration changes, meaning you can update your bot's knowledge base, instructions, or tools on the server side without needing every user to update their app first. The one exception is if you add a genuinely new SDK feature (like a new message type) — that does require a newer SDK version in the app itself, the same as any other client library.
Security considerations when shipping a compiled app
A compiled Android APK can be decompiled by anyone with a little patience, which is exactly why the SDK's public API key is deliberately limited in what it can do — session creation and messaging only, with no access to your bot's configuration, documents, or private tool credentials. If you're adding custom tools that touch sensitive systems, keep the actual credentials for those systems on your own backend behind the webhook, rather than passing anything sensitive through the client. The SDK's job is to get a message from the app to the bot and a reply back, not to hold secrets.
Analytics from inside your app
Conversations started through the SDK show up in the same analytics dashboard as the widget and WhatsApp, tagged by channel, so you can see how much support volume is coming from inside your app versus your website. This is often more revealing than teams expect — a product with a strong native app frequently finds that in-app users ask noticeably different questions than website visitors, since they're usually already customers rather than people evaluating whether to sign up, and the questions skew toward "how do I do X" rather than "what does this cost."
Frequently asked questions
Does the SDK work with React Native, or only native Android/iOS? All three — the JavaScript SDK works in React Native directly, and native Swift/Kotlin packages are available for fully native apps.
Is the public API key safe to ship inside a compiled app? Yes — it's scoped for client-side session creation and messaging only, and can't read or change your bot's configuration or knowledge base.
Do I need a backend of my own to use the SDK? No — the SDK talks directly to JestBot's API. A backend of your own only becomes necessary if you're adding custom tools that call into your own systems.
Can I see whether my mobile app or my website drives more bot conversations? Yes — the analytics dashboard breaks down conversations by channel, including the SDK, so you can compare volume and topics across your app and your website.
What's next
Once your bot is live inside your app, the same tool-calling and calling-agent capabilities covered elsewhere in this series apply here too — a mobile user can check order status, get product recommendations, or escalate to a human, all inside your native app rather than being bounced out to a browser or a phone call. Because the SDK, the widget, WhatsApp, and the calling agent all sit on top of the exact same bot, none of this requires a second integration effort — you're extending the reach of the bot you've already built, not starting a new project for every surface your customers happen to use.