Web Chatbot SDK

View Release Notes →

A plain-JavaScript client for the EnableX Dialogs web channel. It wraps the guest Socket.IO connection and channel-web REST API described in Chat Bots so you can build a custom chat UI without implementing session handling, reconnects, or event parsing yourself.

Web Chatbot SDK v1.0.0  ·  Released June 25, 2026

First release of the Web Chatbot SDK. See Release Notes for what's included.

  Download Web Chatbot SDK v1.0.0
Setup

Dependencies

Load the Socket.IO client before this script:

<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
<script src="dialogs-chatbot-web-v1.0.js"></script>

Minimal Usage

var chat = createDialogsChat({
  host: 'https://your-chatbot-host.com',
  botId: 'your-bot-id',
  ROOT_PATH: ''   // or '/api' if your API is under a path
});

chat.on('message', function (data) {
  if (data.authorId) return;   // skip echoed user message
  var text = data.payload && data.payload.text;
  if (text) console.log('Bot:', text);
});

chat.on('typing', function (data) {
  console.log('Bot typing for', data.timeInMs, 'ms');
});

chat.connect()
  .then(function () { return chat.createConversation(); })
  .then(function (conversationId) {
    return chat.sendMessage(conversationId, { type: 'text', text: 'Hello' });
  })
  .catch(function (err) { console.error(err); });
Method Reference

Creating a Client

FunctionDescription
createDialogsChat(config)Creates a chat client. config: { host, botId, ROOT_PATH?, reconnect? }. Returns the client instance.
chat.init(config)(Optional) Set or update config after create. Same keys. Reconnect config: reconnect: { autoReconnect: true, maxAttempts: 5, delayMs: 2000 }.

Connection and Session

FunctionDescription
chat.validateHost(origin?)Optional. Calls the server validation endpoint (same as the official embed). Resolves if the current origin is allowed for this bot, rejects otherwise. origin defaults to window.location.origin. Use before connect() to enforce a client-side domain check.
chat.connect()Connects to the Dialogs guest socket. Must be called before any conversation or message API. Returns a Promise that resolves when connected.
chat.reconnect()Manually reconnect: disconnects (if connected) and calls connect() again. Returns the same Promise as connect().
chat.disableAutoReconnect()Turns off auto-reconnect and clears any pending reconnect timer.
chat.disconnect()Closes the socket connection and clears reconnect timer. Emits a disconnect event.
chat.isConnected()Returns true if the socket is connected and webSessionId is available.
chat.getWebSessionId()Returns the current webSessionId (for debugging or custom API calls).
Connection required for most methods

Methods that require a connection (listConversations, getConversation, createConversation, resetConversation, sendMessage, sendFile) check both socket connection and webSessionId; if either is missing they reject with "Not connected. Call connect() first." Methods that don't use the session (getBotInfo, validateHost) may be called while disconnected.

Conversations

FunctionDescription
chat.listConversations(startupData?)Lists conversations for the current user. Requires connect() first. Optional startupData: { name, email, phone, custom_id, isEmulator }. Returns a Promise with { conversations: [...] }.
chat.getConversation(conversationId)Loads one conversation with full message history. Requires connect() first. Returns a Promise with { id, messages: [...] }.
chat.createConversation()Creates a new conversation. Requires connect() first. Returns a Promise<conversationId> and sets it as the "current" conversation for sendMessage.
chat.resetConversation(conversationId?)Resets a conversation (clears the dialog session). Requires connect() first. conversationId optional; uses current if omitted. Listen for on('clear'), then call createConversation() for a new thread.
chat.getBotInfo()Fetches bot metadata (name, description, theme, startup message, etc). Does not require connect(). Uses config.botId from init().
chat.getConversationId()Returns the current conversation id (from the last createConversation() or setConversationId()).
chat.setConversationId(id)Sets the current conversation id so sendMessage() without a first argument uses this id.

Sending Messages

FunctionDescription
chat.sendMessage(conversationId, payload)payload must include type (e.g. 'text') and type-specific fields (e.g. text: 'Hello'). conversationId optional — uses current if omitted. Returns a Promise that resolves when the request succeeds; the bot reply arrives via on('message').
chat.sendFile(conversationId, file, optionalPayload?)Uploads a file via POST /messages/files (multipart/form-data). conversationId optional (uses current). file: File or Blob. optionalPayload: optional object (e.g. { caption: '...' }) sent as a JSON string. The file appears as a message; the bot reply may arrive via on('message') with payload.type === 'file' or 'image'.

Events

Subscribe with chat.on(event, callback); unsubscribe with chat.off(event, callback).

EventWhen it firesCallback argument
'message'A bot/agent message is received (not the echoed user message)Message object: { id, conversationId, authorId, sentOn, payload: { type, text, ... }, ... }
'typing'The bot typing indicator is received{ timeInMs, conversationId } — show "typing…" for timeInMs ms
'clear'After resetConversation() — server sends guest.webchat.clearEvent data — use to clear the message list UI

Reconnect events: disconnect (socket closed), reconnecting (attempt N of M), reconnected (success), reconnect_failed (gave up after max attempts).

Feature Support (v1.0.0)

FeatureSupportedNotes
Connect to Dialogs backendYesGuest socket + webSessionId; visitor id stored in localStorage.
Create a new conversationYescreateConversation()convoId.
Send text messagesYessendMessage(id, { type: 'text', text: '...' }).
Receive bot messagesYesSubscribe with on('message', fn); filter by !data.authorId for bot-only.
Typing indicatorYesSubscribe with on('typing', fn); use data.timeInMs.
Current conversationYesgetConversationId(), setConversationId(id); sendMessage() can omit the first argument.
List conversationsYeslistConversations(startupData?) → pick a conversation for returning users.
Load conversation historyYesgetConversation(conversationId)convo.messages; render by authorId (user) vs. bot.
Reset conversationYesresetConversation(conversationId?); listen on('clear'), then createConversation() for a new thread.
Bot info (name, theme, etc.)YesgetBotInfo() (no connect required).
File uploadYessendFile(conversationId?, file, optionalPayload?)POST /messages/files.
Send visit / other eventsNoNot in this milestone — use the raw REST endpoint (see Chat Bots).
Quick reply / postbackNoPayload can be sent manually; the SDK does not parse or expose quick-reply UI.
Preferences (language)NoNot in this milestone.
Agent handoff (handoverStatus)NoMessages may contain payload.handoverStatus; the SDK does not emit a dedicated event for it yet.
Click-to-call (clickToCallEvent)NoNot in this milestone.
Security

Authentication and Host Validation

This SDK does not add authentication

Identity is entirely based on a visitor id (generated and stored in localStorage) and the guest Socket.IO connection (webSessionId). There is no separate "login" step, and the SDK does not check that the page is allowed to use the bot (domain whitelist) before connecting — it connects to whatever host and botId you pass in.

This means anyone who can load your app (or any page that uses this script) and knows host and botId can connect to the socket and start a conversation with that bot. The channel-web API is intended for "guest" (unauthenticated) web chat: the server typically has checkAuthentication: false for the bot's channel-web router, and does not validate the Origin or Referer of the request.

How the Official Embed Differs

The official inject.js embed calls a validation endpoint before showing the widget — GET {host}/lite/{botId}/validation/?domainName={window.location.origin}&... — and does not inject the iframe if that request is rejected. This is client-side enforcement only: it does not protect the channel-web API or socket, so a custom client talking to the API/socket directly can bypass it.

Recommendations

  • Configure the Dialogs server: if the bot supports a domain whitelist for the web channel, configure it so only your app's origin is allowed, and use CORS on the chatbot-engine server so only your frontend's origin can call REST and Socket.IO from a browser.
  • Optional client-side validation: call chat.validateHost() before connect() to get the same client-side gate as the official embed — the server must expose and enforce that endpoint.
  • Sensitive bots: use your own authentication — either a backend proxy (your frontend talks only to your server, which calls the Dialogs API/socket on the user's behalf) or the X-BP-ExternalAuth / ExternalAuth header if the Dialogs server supports it.
  • Operational: apply rate limiting and monitoring on the Dialogs/server side, and keep host and botId out of public repos.