# How to Add AI Chat to a Mobile App Without Leaking Keys

> Never put an AI chat key inside a mobile app: anyone can pull it out of the bundle. Keep the secret on your server, hand the app a short-lived session token,

Canonical: https://maxbound.ai/blog/securely-integrating-ai-chat-into-mobile-apps
Last updated: 2026-10-18

Published: 2026-07-25
Updated: 2026-10-18
Author: Baban Rashid
Category: [AI Agents](https://maxbound.ai/blog/category/agents)
Tags: Mobile App Security, In-App Chat, Session Tokens, API Keys

To add AI chat to a mobile app securely, keep the chat provider's secret key on your own server, never in the app. When a signed-in user opens the chat, the app asks your server for a short-lived session token, your server checks the user and requests the token with the secret, and the app opens the chat with that token. Anyone who unpacks the app finds nothing worth stealing.

The reason is simple: everything shipped inside an app can be read by someone determined. A website widget can be locked to a domain, because browsers send the page's origin with each request. A mobile app has no domain, so a key hardcoded in the app is effectively public.

## Why a key in the app is a problem

App bundles can be unpacked with freely available tools, and strings inside them, keys included, can be read. Once someone has the key they can skip the app entirely and call the chat service directly: running up the client's usage, or reading responses meant for real users.

The general rule from the [OWASP Mobile Application Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Mobile_Application_Security_Cheat_Sheet.html) applies: authenticate and authorise on the server side instead of trusting the client. The app is the client. Obfuscating the key, splitting it into pieces or hiding it in a native library only slows someone down; the app still has to put the key back together to use it, and whatever the app can do, a person with the app can do too.

## The session token flow

1. **The user opens the chat** in the app. They're already signed in to the app.
2. **The app asks your backend** for a chat session, sending the user's own app login as usual.
3. **Your backend checks the user** is real and signed in, then asks the chat service for a session token, using the secret key stored on the server.
4. **The token goes back to the app**, which opens the chat with it. The token is short-lived and tied to that session.

If someone intercepts a token, it expires quickly and works for one session. The secret never leaves the server.

## Setting it up with Maxbound

**Add Maxbound's AI chat to a mobile app securely**

1. **Create the mobile secret key** — In the client's Maxbound workspace, open the deploy settings for the mobile widget and generate a secret key for that agent.
2. **Store it on the server only** — Give the key to the client's backend team to store as an environment variable or in a secrets manager. It never goes into the app's code or repository.
3. **Add a session endpoint** — Create an endpoint on the client's backend that checks the signed-in user, then requests a chat session token using the secret, as described on the mobile setup page.
4. **Open the chat with the token** — When a user opens the chat, the app calls that endpoint and starts the chat with the token it gets back, passing who the user is.
5. **Allow the chat to load** — Add Maxbound to the app's allowed domains so the chat screen isn't blocked by the app's own security policy.
6. **Test before release** — Run the agent on the client's real past questions without sending anything, then test the flow on a device with a real signed-in account.

A minimal backend endpoint looks like this; the session address comes from the mobile setup page in the workspace:

```javascript
app.post('/api/chat/session', requireSignedInUser, async (req, res) => {
  const response = await fetch(process.env.MAXBOUND_SESSION_URL, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.MAXBOUND_AGENT_SECRET}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ userId: req.user.id })
  });
  if (!response.ok) return res.status(502).json({ error: 'Chat unavailable' });
  const { token } = await response.json();
  res.json({ token });
});
```

`requireSignedInUser` is whatever the app already uses to check its own logins. That check is the point: only real users get a chat session.

## Pass the signed-in user

Because the backend knows who the user is, the chat can too. Maxbound's in-app chat takes the signed-in user, so the agent can answer with their account, orders and past chats in mind: "Order 4821 is out for delivery" rather than "Can I have your order number?". Only pass what the agent needs to answer, and nothing it doesn't.

## If a key has already shipped in an app

It happens, often in a quick first version. Treat the key as public from the moment the app went out, because you can't recall copies of an app that people have already downloaded. Generate a new secret, store it only on the server, and switch the app to the session-token flow in the next release. Once most users have updated, revoke the old key, so the copy inside old versions stops working. Watch usage in the meantime: a sudden jump in conversations with no matching rise in app activity is the usual sign that someone else is using the key.

## Don't put tokens in URLs

When the chat screen loads, pass the session token in the way the setup page describes, not as part of a web address. Addresses end up in logs, analytics tools and crash reports, and a token written into one is a token stored in places nobody is watching. The same goes for the user's details: send them when the session is created, from your server, rather than adding them to the chat's address in the app.

## Who owns what, on an agency build

When an agency builds or runs chat for a client's app, write down who holds what. The client's backend team usually owns the secret, the session endpoint and the user check, because they own the servers and the logins. The agency owns the agent: its knowledge, its voice and the rules for what goes to a person. Keep separate keys for the test and live versions of the app, so a test build can never use the live agent by mistake, and make sure someone on the client's side knows how to rotate the key if a developer leaves.

## Other basics for in-app chat

- **HTTPS everywhere.** Mobile devices often join untrusted networks; Android's own [security tips](https://developer.android.com/privacy-and-security/security-tips) recommend HTTPS wherever the server supports it.
- **Rotate the secret** if it might have leaked, and whenever someone with access leaves the project.
- **Separate keys per client app.** One leaked key should affect one client, not all of them.
- **Decide who answers.** The agent can answer on its own or draft replies for a person to approve, the same as on other channels.

## Where Maxbound fits

Maxbound's [in-app chat](/platform/mobile-chat) puts the same AI agent that answers Instagram, Facebook, WhatsApp and [website chat](/platform/web-chat) inside a client's iOS or Android app, with every thread in the same inbox. Its [AI agents](/platform/ai-agents) are trained on the client's own material and hand anything sensitive to a person. Connections are encrypted in transit with TLS, and each client is its own workspace; the details are on the [security page](/security). Before release, [test the agent on real past conversations](/blog/how-to-stress-test-ai-agents-before-go-live).

## Frequently Asked Questions

### Can I put an API key in my mobile app?

Not a secret one. Anything inside an app bundle can be extracted. Keep secrets on your server and give the app short-lived tokens instead.

### Why can't mobile apps use domain-restricted keys like websites?

A website widget can be restricted to a domain because browsers send the page's origin with requests. A mobile app has no domain, so that check doesn't protect it.

### What is a session token?

A short-lived credential your server requests for one chat session after checking the user. If it's intercepted, it expires quickly and can't be used to call the service freely.

### Can the AI chat know which user is asking?

Yes. Because your backend has already checked the user, it can pass who they are when the session starts, so the agent can answer with their account and orders in mind.

### Does the security setup change how the AI agent behaves?

No. The agent can still answer on its own or draft replies for a person to approve, and hand sensitive conversations to the team.

## Related

- [How to Answer Instagram DMs in Arabic for Clients](https://maxbound.ai/blog/how-to-answer-instagram-dms-in-arabic-for-clients) — A step-by-step playbook for agencies: connect, train and brief an agent for Arabic Instagram DM replies and comment-to-DM, dialects and spelling variants
- [How to Test a Kurdish Sorani WhatsApp AI Chatbot](https://maxbound.ai/blog/how-to-test-a-kurdish-sorani-whatsapp-ai-chatbot) — A step-by-step walkthrough for agencies: connect a client's WhatsApp, train a Sorani agent, rehearse it on past chats, and launch with approval on.
- [Comment Moderation Tool for Agencies: A Setup Playbook](https://maxbound.ai/blog/comment-moderation-tool-for-agencies-a-setup-playbook) — How agencies set up comment moderation for every client: a policy template, hide-vs-reply rules, approval settings and the mistakes that cost clients.
- [Busting the Myths of Instagram DM Automation Tools](https://maxbound.ai/blog/busting-the-myths-of-instagram-dm-automation-tools) — Four myths keep agencies answering Instagram DMs by hand: that customers hate automation, that it's all-or-nothing, that setup takes weeks, and that it gets
- [Best Way to Automate Instagram and Facebook Replies](https://maxbound.ai/blog/best-tool-to-automate-instagram-facebook-replies) — Which tool to automate Instagram and Facebook comment and DM replies depends on what the replies are. What Meta allows, what to check, and how to test tools
- [All posts](https://maxbound.ai/blog)
- [Platform overview](https://maxbound.ai/platform)
