Chat

Chatlink

Chat is the New Instance customer conversation product: an embeddable widget that pairs an AI chatbot (answering from your knowledge base, around the clock) with live human chat (your agents, in the dashboard), plus native SDKs so the same conversations work inside your mobile apps.

How it workslink

  • A visitor opens the widget on your site or app and talks to the AI assistant first; it answers from the knowledge you've configured.
  • When the AI can't help - or the visitor asks - the conversation hands off to a human agent in Dashboard → Chat, honouring your routing rules and agent availability.
  • Conversations are real-time both ways (server-sent events with WebSocket fallback), support file attachments, typing indicators and unread counts, and survive page reloads.
  • Prompts are screened by the platform's AI-injection guard; manipulation attempts are rejected before they reach the model.

Integration surfaceslink

SurfaceHowAuth
Webembed.js script tag or the NInstanceChat JavaScript API (below)Publishable widget key - the bare key ID, safe in page source
Android / iOS / React Native / FlutterNative chat SDKs (sub-pages below) with a ready-made chat UISame publishable widget key

The widget key is deliberately secret-less: server-side it is clamped to chat operations only, so shipping it in client code exposes nothing else.

Two ways to identify the customerlink

  • Anonymous. Ship the widget key alone. The visitor gets the pre-chat form and the conversation is anonymous.
  • Authenticated. Your backend mints a short-lived chat identity token with createCsCustomerToken and hands it to the client. The token is the identity: the customer's details never have to be passed into the SDK, and a tampered client cannot claim to be somebody else.

Both use the same publishable key. See Authentication and identity for the token API, the SDK calls, and the diagnostic error codes; see Theming for how dashboard, local and built-in themes combine.


Configure your chat widgetlink

  1. Log in to the merchant dashboard
  2. Navigate to Dashboard → Org → Chat (/dashboard/org/[orgId]/chat)
  3. Configure your widget: appearance, AI chatbot, routing rules, agent availability
  4. Copy your Widget API Key - this is the key ID only (e.g. sk_live_abc123), not the keyId:secret form. The widget runs in a browser; the secret must never appear in client-side code.

Embed the widget via script tag (auto-init)link

Add this to your HTML <head> or just before </body>:

<script
  src="https://widget.newinstance.cloud/embed.js"
  data-api-key="sk_live_abc123"
  data-theme="dark"
  data-position="bottom-right"
></script>

data attributes

AttributeTypeDefaultDescription
data-api-keystring (required)-Widget key ID (NOT the full secret)
data-themedarklightlight
data-positionbottom-rightbottom-leftbottom-right
data-transportssewsinherited
data-customer-name / -email / -idstring-Pre-fill customer identity
data-auto-openbooleanfalseOpen the panel on load
data-gql-endpoint / data-widget-urlURLderivedSelf-host overrides for API endpoint and iframe origin

Embed via JavaScript API (full control)link

<script src="https://widget.newinstance.cloud/embed.js"></script>
<script>
const widget = NInstanceChat.init({
  apiKey: 'sk_live_abc123',  // key ID only - never the secret
  theme: 'dark',
  position: 'bottom-right',
  customerName: 'John',
  customerEmail: 'john@example.com',
  customerId: 'usr_123',
  autoOpen: false,
  callbacks: {
    onAuth: (info) => console.log('Chat auth:', info.valid, info.status),
    onOpen: () => console.log('Chat opened'),
    onClose: () => console.log('Chat closed'),
  },
});

// Programmatic control
widget.open();
widget.close();
widget.toggle();
widget.isOpen();
widget.updateConfig({ theme: 'light', customerName: 'Ada' });
widget.destroy();

// File attachments (before opening composer)
widget.attachFile(file);
widget.attachFiles([fileA, fileB]);
widget.removeAttachment(id);
widget.clearAttachments();
widget.getAttachments();
widget.openComposer();
</script>

NInstanceChat.init(config) options

OptionTypeDescription
apiKeystring (required)Widget key ID
themedarklight
transportssews
gqlEndpoint / widgetUrlURLSelf-host overrides for the API endpoint and iframe origin
customerNamestringPre-fill customer name
customerEmailstringPre-fill customer email
customerIdstringYour internal customer ID
positionbottom-rightbottom-left
autoOpenbooleanOpen the chat on load
buttonSizenumberLauncher button size in px
panelWidthnumberChat panel width in px
panelHeightnumberChat panel height in px
zIndexnumberCSS z-index for the widget
callbacksobjectonReady, onAuth, onOpen, onClose, onDestroy

Defaults: buttonSize 60, panelWidth 400, panelHeight 620, zIndex 2147483647, autoOpen false, position bottom-right. Calls made before the auth handshake are queued and flushed after validation; every bridged call times out after 15 seconds. attachFile accepts a File, Blob, data URL or bare base64 plus an optional name; attachment snapshots carry id, name, type, size, status, progress and an error reason or URL. openComposer() also opens the panel locally, so isOpen() flips synchronously. updateConfig reloads the iframe and resets an in-progress conversation; only theme, customerName and customerEmail are re-applied.

Widget behaviour beyond these options (welcome and offline messages, input placeholder, file-upload, emoji and typing toggles, email-required, sound, online status, branding) is configured in the dashboard, not from the embed.

Conversation modellink

Flow states run idle → collecting_info → bot_conversation → handoff_pending → live_chat → ended | error; conversation statuses are BOT_ACTIVE, WAITING, ACTIVE, RESOLVED and CLOSED; channels are ai, live and ticket. The pre-chat info form is skipped only when a non-blank customerName was supplied. The transport heartbeats roughly every 10 seconds; a missed beat within about 16 seconds tears down, reconnects and replays missed messages from the server event log; connectivity is re-checked on online, visibilitychange and pageshow.

Widget lifecyclelink

  • Auto-init runs on window load (immediately if the document is already complete) and only when data-api-key is present.
  • A second init() returns null and warns that the widget is already initialized.
  • If the iframe never answers, a 10 second safety timeout removes the widget silently; on auth failure the root is removed, onDestroy fires, queued calls reject, and the console explains that chat is unavailable, disabled or not configured.
  • destroy() notifies the iframe, then rejects in-flight bridged calls with "widget destroyed".
  • The host page CSP must allow the widget origin in both frame-src and script-src.

How the iframe bridge workslink

The widget loads in a sandboxed <iframe>. All communication between the host page and the widget uses postMessage with source-tag and origin validation:

  • Host → widget messages are tagged with ninstance-chat-host
  • Widget → host messages are tagged with ninstance-chat

The widget fires onAuth after API key validation. The button stays hidden until onAuth confirms valid: true.


Permission scopes for Chat API keyslink

Scope codeDescription
full-accessAll chat permissions (recommended)
ai-chatbot-accessInteract with AI chatbot
live-chat-operationsManage live chat sessions
chat-configurationConfigure widget settings