# How chat works

> The architecture shared by every Kustomer chat SDK. The UI and Core layers, chat keys and customer identity, HTTPS for writes and history, the realtime channel for delivery, and the conversation lifecycle.

Source: https://developer.kustomer.com/docs/chat/realtime-architecture

Every Kustomer chat SDK (web, iOS, Android and React Native) has the same shape: a **UI** layer on top of a headless **Core**, talking to Kustomer over HTTPS for anything it sends and over a realtime channel for anything Kustomer pushes back.

_Animated diagram of a chat message moving between the chat UI, the Core SDK, the HTTPS and realtime transports, Kustomer, and the agent. Scenarios show a customer sending, an agent replying, an agent typing, and reconnecting after going offline._

## Two layers

| Platform     | UI layer                           | Core layer                           |
| ------------ | ---------------------------------- | ------------------------------------ |
| Web          | `widget.js`, the `Kustomer` global | `core.js`, the `KustomerCore` global |
| iOS          | `KustomerChat`                     | `KustomerCore`                       |
| Android      | `com.kustomer.ui` (`:ui`)          | `com.kustomer.core` (`:core`)        |
| React Native | Native UI on each platform         | Native Core on each platform         |

**Core** owns identity, conversations, messages, the realtime connection, unread counts and the knowledge base. **UI** renders it: the launcher, conversation list, message thread, CSAT and knowledge base screens. The UI only talks to Kustomer through Core, so if you build your own UI on Core, you get exactly the same behavior.

On the web, both layers run in their own iframes. Your page's CSS and JavaScript can't reach into chat, and chat's can't leak onto your page.

## Identity

Every SDK starts with a **chat key**: an API key whose only role is `org.tracking`. It's meant to be public. With it, the SDK can do one thing: chat as the customer on that browser or device.

```mermaid
stateDiagram-v2
  direction LR
  [*] --> Anonymous: SDK starts with the chat key
  Anonymous --> Anonymous: Customer chats (a customer record is created)
  Anonymous --> Identified: login(jwt signed by your server)
  Identified --> Identified: Same customer on every device
  Identified --> Anonymous: logout()
```

1. **Anonymous.** The SDK creates an identity for the browser or device and stores it locally, so conversations survive reloads and app restarts. When the visitor first chats, Kustomer creates a customer for them.
2. **Identified.** When your user signs in, your server signs a short-lived JWT with their email or your user ID, and the SDK calls `login` with it. Kustomer attaches the session to that customer, so their conversations follow them across browsers and devices.
3. **Logged out.** `logout` clears the local session. The next visitor on the device starts anonymous.

Never identify a customer from the client alone: anyone could claim to be anyone. The JWT is signed with a secret only your server knows. See [Customer identity](https://developer.kustomer.com/docs/chat/identity).

## Transport

| Direction      | Transport        | Carries                                                                                                    |
| -------------- | ---------------- | ---------------------------------------------------------------------------------------------------------- |
| SDK → Kustomer | HTTPS            | Creating conversations, sending messages and attachments, read receipts, CSAT, identity, settings, history |
| Kustomer → SDK | Realtime channel | New messages, typing indicators, read state, conversation ended or reopened, merges, deletes               |

The realtime channel is a subscription to channels for the customer and their conversations, set up after `init` and again after `login` or creating a conversation. The SDKs never poll for messages.

History is read from the realtime channel first, for recent messages, and from Kustomer over HTTPS for anything older or missing, such as after the device was offline.

Typing indicators are **signals**: they're delivered live and never stored, so they're absent from history.

## Conversation lifecycle

```mermaid
stateDiagram-v2
  direction LR
  [*] --> Assistant: Brand has an assistant
  [*] --> Open: No assistant
  Assistant --> Open: Assistant hands off
  Open --> Ended: Agent or customer ends it
  Ended --> Open: Reopened
  Ended --> CSAT: Survey sent
  CSAT --> [*]
```

| State                                        | Core event               |
| -------------------------------------------- | ------------------------ |
| Conversation created                         | `onConversationCreate`   |
| Assistant finished, waiting for an agent     | `onAssistantEnded`       |
| Ended                                        | `onConversationEnded`    |
| Reopened                                     | `onConversationUnended`  |
| CSAT survey arrived                          | `onSatisfactionReceived` |
| Merged with another conversation in Kustomer | `onConversationMerged`   |

On the Kustomer side, a chat conversation is a normal [conversation](https://developer.kustomer.com/docs/concepts/conversations-and-messages) on the `chat` channel, and each chat message is a message on it. Everything else in Kustomer, including [workflows](https://developer.kustomer.com/docs/workflows), routing, [webhooks](https://developer.kustomer.com/docs/events/outbound-webhooks) and the [REST API](https://developer.kustomer.com/api), sees chat like any other channel. To act as a participant from your server, use the [server-side chat API](https://developer.kustomer.com/docs/chat/server-chat-api).

## Settings come from Kustomer

The SDK fetches the brand's chat settings when it starts: colors, greeting, business hours, assistant, knowledge base, attachments and page rules. Admins change chat for every platform at once without an app release. Your code chooses the brand and handles placement and identity.

## Where to go next

- [Web quickstart](https://developer.kustomer.com/docs/chat/web): Two script tags and `Kustomer.start`.
- [Customer identity](https://developer.kustomer.com/docs/chat/identity): Sign JWTs and log customers in on every platform.
- [Server-side chat API](https://developer.kustomer.com/docs/chat/server-chat-api): Answer chats from your own bot or AI agent.
