Skip to main content

Web Chat Widget

Embeds a chat bubble on a website, backed by an agent flow. Unlike the other channels there's no external provider involved: the widget is a NeuraFlow script tag plus a per-widget config record.

1. Prerequisites

None. No external account or portal is required; the widget is served from NeuraFlow itself.

2. Configuration

/channels/chat-widgets lists widgets. Each row has an enabled toggle (calls PATCH /chat-widgets/{id} with just { enabled }, no confirmation), a Get embed code action, and a delete action (confirmation dialog "Are you sure?", then DELETE /chat-widgets/{id}). Get embed code shows:

<!-- NeuraFlow Chat Widget -->
<neuraflow-bot agent-id="{widget_id}" core-url="{CORE_URL}"></neuraflow-bot>
<script src="{origin}/chat-widget.js" async></script>

/channels/chat-widgets/create and /channels/chat-widgets/{widgetId}/edit render the same full-page editor: two tabs on the left (General, Security), a live preview of the actual widget on the right that updates as you type, and Cancel / Create Widget (Update Widget when editing) in the page header. There's no per-tab save, the button submits the whole form; Create Widget/Update Widget validates every field across both tabs (Zod), and a failed check anywhere shows a generic "Please fix the form errors before submitting" toast plus inline messages under the specific fields. On success it calls POST /chat-widgets (create) or PATCH /chat-widgets/{id} (edit), toasts "Chat widget created successfully!" / "Chat widget updated successfully!", and for create, navigates to the edit page for the new widget.

General tab

Basic Information: Widget Name (required, "Widget name is required"), Bot Name (optional, falls back to Widget Name in the chat header if empty), Description (optional, max 500 chars, shown on the widget's list card), Input Placeholder (required, "Placeholder text is required"), Welcome Message (required, "Welcome message is required"), Agent Flow (optional select, "None (Use default chat)" is a real selectable option, not just a placeholder), Persona (Friendly / Professional / Custom, switching away from Custom clears the custom prompt), Custom Persona Prompt (shown only when Persona is Custom), Widget Enabled toggle.

Launcher & Icon: Button Title and Button Description (both optional, free text shown on the floating launcher button). Upload Icon is a file picker, not an upload to the server: it's read client-side and stored as a base64 data URL directly in the widget's logoUrl field on save, capped at 500KB ("Image size must be less than 500KB", checked before the file is even read). Once an icon is set, three toggles appear: Show in Header, Show in Toggle Button, Use as Agent Avatar. Two more toggles are always visible regardless of icon state: Show Bot Icon (default icon next to messages) and Show Message Actions (feedback/copy/resend buttons on messages).

Behavior: Minimized Bar, Picture-in-Picture on Tab Switch, Unread Notifications, all independent toggles, no fields.

Styles: Placement offers only Bottom Right and Bottom Left in the dropdown, even though the underlying position field also accepts top-right and top-left, there's no UI path to set those two. Every other row here is a colour picker (native swatch plus a synced hex text input, must match #RRGGBB or the field shows "Must be a valid hex color"), a 0-50px radius slider, or a shadow dropdown (None / Small / Medium / Large / Extra Large / 2x Large), grouped by element:

ElementColour(s)RadiusShadow
Chat sheetSheet ColorSheet RadiusShadow
Toggle buttonChat Toggle Color, Toggle Text/Icon ColorChat Toggle Button Radius (0-100px)Chat Toggle Shadow
Agent (bot) messagesBackground Color, Text ColorAgent RadiusAgent Shadow
User messagesBackground Color, Text ColorUser RadiusUser Shadow
Message inputText Color, Border Colornonenone
HeaderHeader Color, Header Text Color, Action Button ColorHeader Blur Effect (0-50, a backdrop blur intensity, not a corner radius)Header Shadow

"Action Button Color" is a misleading label: it writes to the widget's headerIconColor style field, not to any button-specific field. The schema also carries a sendButtonBackground style field that this tab never exposes a control for at all, it can't be set from the UI.

Voice Settings: Enable Voice toggle, disabled and forced off if voice is turned off globally for your account (Settings → Display), with a banner explaining that. When on, Speech-to-Text Model (Deepgram Nova 3/2/Enhanced/ Base, or OpenAI Whisper) and Text-to-Speech Model (five Deepgram Aura voices, six OpenAI voices) appear. Regardless of what's selected here, the editor forces voiceEnabled to false and both provider fields to null at submit time if voice is globally disabled for your account, the toggle being visually on doesn't survive save in that state.

Terms & Conditions: Enable Terms & Conditions toggle; when on, Terms Content (markdown, textarea), Accept Button Text and Decline Button Text (both default to "I Accept" / "Decline" via placeholder, not enforced defaults) become editable, greyed out otherwise.

Security tab

Widget Token: a read-only field, pre-filled with a random UUID generated in the browser the moment you open the create page, not fetched from the server. If it's ever empty, a Generate Token button appears and calls POST /chat-widgets/utils/generate-token. Once a value exists (always, in practice) the button becomes Copy (clipboard) and Regenerate Token (same endpoint), plus a warning that regenerating invalidates the old token as soon as you save.

Allowed Domains: a text input plus Add button (also triggered by Enter), client-side validated against a domain-shaped regex or the literal string localhost ("Please enter a valid domain name"), duplicates rejected ("Domain already added"). Each added domain is a removable badge. Empty list is explicitly labelled "No domains restricted. Widget will work anywhere."

Rate Limiting: Enable Rate Limiting toggle; when on, a Requests per Minute slider (1-120) appears, labelled "Maximum number of requests allowed from a single IP/Session in 60 seconds."

Identity Verification (HMAC): a "Developers Only" warning card, then Enforce Identity Verification toggle and HMAC Secret Key, same generate/copy/regenerate pattern as Widget Token, calling POST /chat-widgets/utils/generate-secret.

3. Other

The three Security tab controls are independently opt-in and backward compatible: an empty Allowed Domains list allows every origin, no Widget Token means the token header is never checked, and rate limiting is off unless explicitly enabled. A widget with nothing configured on the Security tab has none of these protections.

GET /chat-widgets/{widget_id} (used to load the widget on the embedding page) and POST /chat-widgets/{widget_id}/session-token (used to obtain the short-lived JWT the widget uses for chat calls) are both public endpoints, no NeuraFlow auth required, and only return data for enabled widgets.