The /livekit/widget route is the entry point for embeddable browser web calls. A web visitor joins a LiveKit room from the browser, and this route asks a CXB Core worker to join the same room as the bot and run the standard pipeline — no telephony, no SIP.

Connection flow

Endpoint

POST /livekit/widget
Requires the X-CXB-Core-Secret header (403 without).

Request body

{
  "bot_id": "bot-uuid",
  "room_name": "widget-room-abc",
  "caller_id": "widget-user"
}
FieldTypeRequiredDescription
bot_idstringYesBot configuration to use
room_namestringYesLiveKit room the browser user is already in
caller_idstringNoIdentifier for the web caller. Defaults to "widget-user".

Response

{
  "status": "accepted",
  "call_id": "uuid-string"
}
The endpoint returns immediately; the pipeline runs in a background task.

Audio format

16 kHz mono LINEAR16 via the LiveKit SDK, same as the other LiveKit routes.

Behavior notes

  • Hangup: the bot ends a widget call with transport.disconnect(), which leaves the LiveKit room.
  • No SIP transfer / Agent Desk: the widget route does not register a transfer or agent-desk callback — build_and_run_pipeline() is called without them. Web widget calls are pure conversation.
  • Outside hours / unavailable bot: if config fetch returns None, the call is dropped with disconnected_by = "error" (the widget route does not use outside_hours).
  • Standard pipeline: opening message, STT/LLM/TTS, and post-call analysis run exactly as on other transports.

Capacity

The route returns 429 At capacity when the worker has no free slot. /livekit/widget is in the fleet nginx 429-retry list (proxy_next_upstream ... http_429), so nginx retries another worker — safe because CXB Core returns 429 before starting any side effects.