Web chat widget

Put a Jelliu agent on your website with one script tag.
View as Markdown

The web chat widget adds a floating chat button to your site. Visitors who open it talk to one of your Jelliu agents, by text or, if you enable it, by voice.

Two credentials, not interchangeable

Every widget has two identifiers. Keep them apart:

CredentialWhat it isWhere it goes
Widget ID (a UUID)Public. Identifies the widget. Safe to put in your page.In the embed script URL. The widget sends it as the x-widget-id header or the wid query parameter.
Widget API keySecret. For calling the public widget endpoints directly from your own code.Only in the x-widget-api-key header, and only from a server or app you control. Never in a URL.

The widget API key is shown once, as plaintext_api_key in the response that creates the widget. Jelliu stores only a keyed hash of it. The standard embed does not need it.

The widget API key is not a workspace API key (jl_...), and neither one belongs in a web page. The only credential the embed snippet uses is the public widget ID.

Embed the widget

1

Create the widget

Create it in the dashboard under Widgets, or with the API (a write key is enough):

curl -sS -X POST "https://api.jelliu.co/api/widgets" \
-H "Authorization: Bearer $JELLIU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "7c1d9f30-5e2a-4a7e-9c8f-91a0b1c2d3e4",
"name": "Website chat",
"allowed_origins": ["https://www.example.com"],
"branding": {
"primary_color": "#2563EB",
"position": "bottom-right",
"title": "Chat with us"
}
}'

The widget’s id in the response is your widget ID.

2

Add the script to your site

Paste this before the closing body tag of every page where the chat should appear, replacing WIDGET_ID:

<script src="https://api.jelliu.co/widget-embed/WIDGET_ID/embed.js" async></script>

This is the same snippet the dashboard gives you. The script is public and cached by browsers for up to 5 minutes, so branding changes can take that long to show up.

3

Check the allowed origins

Load your page and open the chat. If it does not answer, make sure the page’s origin is in the widget’s allowed_origins (see below).

What the script does

  • Adds a round launcher button in the corner set by branding.position, in your primary_color.
  • Loads the chat panel in an iframe the first time a visitor opens it, so pages where nobody chats only load the small loader.
  • Shows a side panel on desktop and a full-screen panel on screens up to 520 px wide.
  • Allows the chat panel to use the microphone, which voice conversations need. Browsers still ask the visitor before granting it.
  • Runs once per page, even if the snippet is included twice.
  • On Shopify storefronts, forwards the signed-in customer’s email, name and ID, and the shop domain, so conversations are linked to the right contact.

Allowed origins

A widget answers only on the sites listed in allowed_origins. The chat panel reports the origin of the page that embeds it, and Jelliu compares it with the list:

  • The scheme and port must match exactly.
  • The hostname must match, except that one leading www. is ignored: https://example.com also covers https://www.example.com, and the reverse.
  • Other subdomains need their own entry. https://shop.example.com is not covered by https://example.com.
  • * is never accepted. At least one origin is required.

Requests from a page that is not allowed receive 403 with code FORBIDDEN and the message Origin not allowed.

Widget settings

agent_id
string (uuid)Required

The agent that answers visitors.

name
stringRequired

1 to 200 characters.

allowed_origins
string[]Required

Full origins such as https://www.example.com. At least one.

branding
object

primary_color (required inside branding, hex #RRGGBB), position (bottom-right or bottom-left), title (up to 100 characters), subtitle (up to 120), logo_url, quick_replies (up to 4 short replies), agent_names (up to 8 display names), agent_avatars (up to 8 HTTPS image URLs aligned with agent_names), and i18n (per-language greeting and quick_replies, keyed by language such as es or en).

greeting_message
string

Up to 2000 characters.

voice_enabled
booleanDefaults to false

Let visitors talk to the agent by voice.

rate_limit_rpm
integerDefaults to 30

Requests per minute allowed for this widget.

Update a widget with PUT /api/widgets/{id} (send only the fields to change) and remove it with DELETE /api/widgets/{id}.

Limits

Public widget traffic is limited at several levels:

LevelLimit
Per visitor IP60 requests per minute
Per widgetrate_limit_rpm (30 per minute by default)
Per workspace300 requests per minute across all widgets
Per workspace, per dayA daily cap on visitor messages; once reached, messages are refused until the next UTC day

Exceeding a limit returns 429 with code RATE_LIMIT_EXCEEDED.

Calling the widget endpoints directly

The standard embed handles everything. If you build your own chat interface, the widget endpoints are served from https://api.jelliu.co:

MethodPathBody
POST/widget/initvisitor_id (required), metadata (optional object). Returns 201 with a session_id.
POST/widget/messagesession_id (uuid), message (1 to 4000 characters). An optional attachment can be sent as a multipart file field, up to 10 MB.

Authenticate with the x-widget-api-key header and send x-widget-parent-origin set to one of the widget’s allowed origins. Keep the widget API key on a server you control.