Client SDK overview
The Univerx Client SDK (@univerx/client-sdk) lets you embed real-time video calling and cobrowsing directly into your web application. When a visitor clicks a help button, they join a support queue, get connected to an available agent, and can share their screen — all without leaving your site.
When to use the Client SDK
Section titled “When to use the Client SDK”- You want to add live video support to your own website or web app.
- You need cobrowsing: agents see and interact with the visitor’s browser in real time.
- Your team manages queues and agents in the Univerx dashboard, and you want the customer-facing widget on your domain.
- You are building a custom UI rather than embedding the hosted widget.
- You need fine-grained control over theming, positioning, and lifecycle events.
Installation
Section titled “Installation”npm install @univerx/client-sdkyarn add @univerx/client-sdkpnpm add @univerx/client-sdk<script src="https://cdn.univerx.ai/widget@1.0.0/index.js"></script>Get your widget key
Section titled “Get your widget key”Before initialising the SDK you need a widget key. Create one in your Univerx dashboard under Settings → Widgets. Each key is tied to a set of allowed domains, so make sure to add your site’s origin there too.
Store the key as an environment variable so it is not committed to source control:
UNIVERX_WIDGET_KEY=your-widget-key-hereQuickstart
Section titled “Quickstart”The minimal flow is: instantiate → init → submit pre-call form (optional) → join queue → handle events.
import { WidgetClient } from "@univerx/client-sdk";
const widget = new WidgetClient({ widgetKey: "your-widget-key-here", // required // baseUrl defaults to https://api.univerx.ai});
// Initialise: authenticates with the Univerx API and sets up realtime channelsawait widget.init();
// (optional) collect visitor details before placing them in the queueawait widget.submitForm({ name: "Jane Smith", email: "jane@example.com",});
// join the support queue; pass consent flags your pre-call form collectedconst ticket = await widget.joinQueue({ terms: true, // visitor accepted terms of service recording: false, // visitor declined recording consent});
console.log("Queue position:", ticket.position);
// react to key lifecycle eventswidget.on("agent:assigned", (agent) => { console.log(`Connected to agent: ${agent.name}`);});
widget.on("call:started", () => { console.log("Video call is live");});
widget.on("call:ended", () => { widget.destroy(); // clean up listeners and connections});React integration
Section titled “React integration”import { WidgetClient } from "@univerx/client-sdk";import { useEffect, useRef } from "react";
export function SupportWidget() { const widgetRef = useRef<WidgetClient | null>(null);
useEffect(() => { const widget = new WidgetClient({ widgetKey: process.env.UNIVERX_WIDGET_KEY, onAgentAssigned: (agent) => console.log(`Agent: ${agent.name}`), onCallEnded: () => widgetRef.current?.destroy(), });
widget.init(); widgetRef.current = widget;
return () => { widgetRef.current?.destroy(); }; }, []);
// The SDK renders its own UI; this component is a lifecycle wrapper only return null;}Configuration reference
Section titled “Configuration reference”| Option | Type | Required | Description |
|---|---|---|---|
widgetKey | string | Yes | Your widget installation key |
baseUrl | string | No | API base URL. Defaults to https://api.univerx.ai |
container | string | HTMLElement | No | Mount the widget inside a specific DOM element |
theme | WidgetTheme | No | Visual customisation: colors, position, font |
cursor | CursorConfig | No | Agent cursor visibility settings |
onReady | () => void | No | Called when the SDK is initialised and ready |
onError | (error: Error) => void | No | Called on any unhandled SDK error |
onAgentAssigned | (agent: Agent) => void | No | Called when an agent accepts the session |
onCallStarted | () => void | No | Called when the video call begins |
onCallEnded | () => void | No | Called when the video call ends |
Key events
Section titled “Key events”The SDK extends EventEmitter. Subscribe with widget.on(event, handler).
| Event | Payload | Description |
|---|---|---|
ready | — | SDK initialised |
queue:joined | QueueTicket | Visitor entered the queue |
queue:update | number | Queue position changed |
queue:left | — | Visitor left the queue |
agent:assigned | Agent | Agent accepted the session |
call:started | — | Video call is live |
call:ended | — | Video call finished |
cobrowse:started | — | Cobrowsing session started |
cobrowse:ended | — | Cobrowsing session ended |
error | Error | Unhandled error |
Next steps
Section titled “Next steps”Troubleshooting
Section titled “Troubleshooting”401 Unauthorized on init
Section titled “401 Unauthorized on init”Your widget key is missing or incorrect. Double-check the value passed to widgetKey. Also ensure the domain you are running from is allowlisted under Settings → Widgets → Domains in your dashboard.
Widget initialises but no agents appear
Section titled “Widget initialises but no agents appear”The queue may be empty or no agents are currently online. Check the Queues section of your dashboard and verify the widget is assigned to the correct queue under Settings → Widgets.
CORS errors in the browser console
Section titled “CORS errors in the browser console”Your domain must be added to the widget’s allowed-domain list. Open Settings → Widgets, select your widget, and add your full origin including protocol (e.g. https://example.com).
Rate-limit errors (429 Too Many Requests)
Section titled “Rate-limit errors (429 Too Many Requests)”The public init endpoint is rate-limited to 10 requests per minute per IP. Avoid calling widget.init() on every render — call it once on component mount and keep the instance alive.