Web SDK chat API
Control the Runbear chat widget from your page — mount, reset and reopen conversations, send messages, and listen for its lifecycle and session events.
client.createChat() returns the widget instance, typed Chat. Your page drives it with the
methods below and follows what it is doing through events.
const client = new Runbear({ assistantId: "…", auth: { mode: "session", fetchSessionToken } })
const chat = client.createChat()
chat.on("containerReady", ({ threadId }) => saveThreadId(threadId))
chat.on("sessionFailed", ({ reason }) => showRetry(reason))
chat.mount("#runbear-chat")createChat(threadId) creates a widget that opens an existing conversation instead of starting a new
one. See Saving and reopening a conversation.
Methods#
| Method | What it does |
|---|---|
mount(target) | Renders the widget into target, a CSS selector or an HTMLElement, and starts the conversation. Throws "Could not find element to mount chat widget" when the selector matches nothing, and "Chat widget is already mounted" on a second call. Does nothing outside a browser. Mount into an empty element: see Limitations |
destroy() | Removes the widget, removes every event listener, and stops its session renewals. Call it when the element goes away, such as in a React effect's cleanup |
on(event, callback) | Subscribes to an event |
off(event, callback) | Unsubscribes the same callback |
reset() | Starts a new, empty conversation. In session mode it asks your endpoint for a new session, without a resume token |
startWithMessage(text) | Starts a new conversation and sends text as its first message |
startWithThread(threadId) | Opens an existing conversation and loads its history. In session mode it first mints a session bound to that thread |
addUserMessage(text) | Sends text as if the visitor had typed it. Before the widget has a conversation it does nothing and logs a warning |
addSystemMessage(text) | Queues text as a system message, sent together with the next user message. Before the widget has a conversation it does nothing and logs a warning. reset(), startWithMessage() and startWithThread() clear the queue |
retrySession() | Session mode only: recovers after sessionFailed. Does nothing in any other state. See Errors |
Events#
| Event | Payload | When |
|---|---|---|
chatCreated | { threadId } | The widget has a new conversation: created on mount or by reset(), startWithMessage() or, in session mode, startWithThread() |
chatStarted | None | The first message appears in a conversation |
rendered | None | The widget has rendered its UI. It renders again after reset(), startWithMessage(), startWithThread() and a session change, so this can fire several times |
containerReady | { threadId } | Once per mount, when the widget first has a conversation and can accept messages |
messagesLoaded | { threadId, messageCount } | After startWithThread() has loaded the history, and after startWithMessage() has created its conversation |
sessionReady | { sessionId, threadId } | Session mode: the first session is live |
sessionRenewed | { sessionId } | Session mode: the pass was renewed; same conversation |
sessionChanged | { sessionId, threadId } | Session mode: a different session is now active, after reset(), startWithMessage(), startWithThread(), or when your endpoint minted a new session instead of refreshing |
sessionFailed | { reason } | Session mode: the session ended. reason is "declined", "expired", "network" or "misconfigured". See Errors |
The ChatEventSession*Data payload types are exported from 0.2.0. ChatEventCreatedData,
ChatEventContainerReadyData and ChatEventMessagesLoadedData are exported from 0.5.0 (not yet
released); on 0.4.0 those payloads have the same shapes but no exported names. See Types.
Lifecycle#
mount()
├─ proxy or direct mode ─▶ POST /v1/threads ─▶ chatCreated ─▶ containerReady
│ (with createChat(threadId): containerReady only)
└─ session mode ─▶ fetchSessionToken() ─▶ sessionReady ─▶ chatCreated ─▶ containerReady
while mounted
├─ session mode ─▶ sessionRenewed on each renewal
├─ reset() / startWithMessage() ─▶ (sessionChanged) ─▶ chatCreated
├─ startWithThread(id) ─▶ (sessionChanged ─▶ chatCreated) ─▶ messagesLoaded
└─ a session ends ─▶ sessionFailed ─▶ retrySession()
destroy()Two rules follow from it:
- Subscribe before you mount. Some events fire during
mount()itself, such ascontainerReadyforcreateChat(threadId)outside session mode. - Wait for
containerReadybefore sending.addUserMessage()andaddSystemMessage()need a conversation; called earlier they do nothing and log a warning. In session modesessionReadyfires just before the widget adopts the session's conversation, so a message sent from asessionReadyhandler is dropped. UsesessionReady,sessionChangedandsessionFailedto follow the session, andcontainerReadyorchatCreatedto know the widget can take a message.
chat.on("containerReady", () => {
chat.addSystemMessage("The visitor is on the pricing page.")
chat.addUserMessage("What does the Pro plan include?")
})
chat.mount("#runbear-chat")Saving and reopening a conversation#
To let a visitor come back to a conversation later, on another device or after the stored session has expired:
- Save the thread id. Record the
threadIdfromchatCreatedin your own database, next to the visitor. - Reopen it. Create the widget with
client.createChat(savedThreadId), or callchat.startWithThread(savedThreadId)on a mounted one. - In session mode, forward the thread id once. The SDK passes it to
fetchSessionTokenasthreadIdfor that one mint; your endpoint forwards it asthread_idtoPOST /v1/sessions. Forward it only when the SDK sends it. An endpoint that always adds the saved id makesreset()reopen the old conversation instead of starting a new one.
Reopening a conversation replaces the widget's current session, including the stored resume token.
The thread must belong to the same agent and your organization, or the mint returns 404. If your
endpoint ignores threadId, the visitor lands in a new conversation and sessionChanged reports a
different thread id from the one you asked for.
Within one browser, you don't need this: the default storage: "session" already resumes the
conversation after a reload. See
Where the session is stored.
Related#
- Authentication: session mode and your endpoint
- Errors: recovering from
sessionFailed - Types:
Chatand the event payload types