Create a widget

View as Markdown
Creates a web-chat widget bound to one of your agents and mints its widget API key. The widget is active immediately: embed it with the script from `GET /widget-embed/{id}/embed.js`, which identifies the widget by its id and does not need the key. The plaintext key is returned **once**, as `plaintext_api_key` (64 hex characters). Only an HMAC-SHA256 digest is stored, so it cannot be retrieved again and there is no rotation endpoint. You only need it to call the public `/widget/*` endpoints from a server you control, in the `x-widget-api-key` header. `allowed_origins` must list at least one full origin (for example `https://www.example.com`); runtime calls from any other page are refused. `agent_id` should be an agent of your workspace; this endpoint does not look it up, and an id that matches no agent fails the database constraint with a 500. **Side effects.** Inserts the widget row and writes an audit entry. **Idempotency.** Not idempotent. Retrying after a timeout creates a second widget with a different id and key; list with `GET /api/widgets` first if unsure, and delete the duplicate. **Webhook events.** `audit.log_recorded` when you subscribe to it. See [Webhooks](/webhooks). **Access** - **Required scope:** `write`. - **Rate limit:** General API — 120 requests/min per workspace (200 on Growth, 300 on Business, 600 on Enterprise). See [Rate limits](/rate-limits). - **Plan:** Available on every plan.

Authentication

AuthorizationBearer
Workspace API key: `jl_` followed by 64 lowercase hex characters, created by the workspace owner in the dashboard (**Settings → API Keys**) and sent as `Authorization: Bearer jl_...`. The plaintext is shown once, at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys. | Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes | | --- | --- | --- | --- | | `read` | Yes | No | No | | `write` | Yes | Yes | No | | `full` | Yes | Yes | Yes | Operations restricted to admins or owners reject keys without the `full` scope with `403`, and say so in their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret — that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds. See [Authentication](/authentication).

Request

This endpoint expects an object.
agent_idstringRequiredformat: "uuid"

Agent that answers visitors. Use an agent of your workspace; the id is not otherwise checked.

namestringRequired1-200 characters
Internal name. Trimmed before validation.
allowed_originslist of stringsRequired

Full origins (URLs) the widget may be embedded on. At least one is required (At least one origin is required). Each entry must parse as a URL (Invalid url).

brandingobjectOptional

Widget look and copy. On write, primary_color is required whenever branding is sent, and the object REPLACES the stored branding (it is not merged). Widgets created without branding store {}, which is what POST /widget/init then returns.

voice_enabledbooleanOptionalDefaults to false
Let visitors talk to the agent by voice.
greeting_messagestringOptional<=2000 characters

First message the chat shows. Trimmed; an empty string is treated as absent (stored as null).

rate_limit_rpmintegerOptional>=1Defaults to 30

Requests per minute allowed per widget credential on the public /widget/* endpoints.

Response

Widget created. The only response that ever contains plaintext_api_key.

dataobject

A web-chat widget configuration. Returned by every /api/widgets endpoint. Field names are snake_case.

Errors

400
Bad Request Error
401
Unauthorized Error
403
Forbidden Error
429
Too Many Requests Error
500
Internal Server Error