Skip to main content
A storefront can share a public widget identity across visitors while keeping every conversation behind its own capability. The reviewed response-chat-widget backend enforces these independently. Custom backends must implement their own equivalent authorization.

Credentials and ownership

Widget signatures use STATESET_WIDGET_AUTH_SECRET. Tokens have either orgId.agentId.timestamp.signature or orgId.agentId.timestamp.siteId.signature; the site claim is signed and UUID-shaped. Tenant hints in headers or request metadata must agree with verified claims; they cannot grant ownership. The public session issuer binds those claims to server configuration and checks an exact allowed Origin. That identifies the deployment, not the visitor’s identity. When a conversation is created, its response discloses threadToken, either in JSON or a leading SSE thread event. Default widget requests store and echo it for chat, history, mutations and feedback. An org-wide widget token does not grant access to another visitor’s thread. For this server, STATESET_THREAD_TOKEN_REQUIRED=true also rejects legacy threads that never had capabilities; it does not recover missing capabilities. The separate hosted ResponseCX service uses its own enforcement settings. A browser storage failure falls back to memory for the current page. It does not authorize a later page load that lost a protected conversation’s token. Custom buildThreadRequest overrides own the full request and must supply required headers.

Preserve message identity on retries

The current widget creates a stable clientMessageId for a send and reuses it on recovery. With a session ID (or thread-token header as the execution scope), the server caches completed logical replies for ten minutes, subject to a 256 KiB captured-response limit. JSON and completed SSE can replay with X-Idempotent-Replay: true, without executing the action again. Cached access to an existing thread is reauthorized; a session ID alone is not a capability. Oversized or incomplete replies are not reusable cached successes, even if an external action already happened. For a custom client, preserve both IDs for the same intentional send:
A failed stream is not proof that a commerce action failed. Use Check for a reply to refresh without resending. To inspect the authorized thread directly, populate these environment variables from the same visitor session and issue a read:
A timeout or interrupted connection does not prove that the server or a commerce provider rejected the action. Preserve its identity and reconcile the stored result first.
Stop/cancellation ends the client’s wait; it cannot undo accepted server or external work. For a new intentional action, use a new message ID. The ten-minute replay cache and distributed leases do not make external provider or commerce systems transactional. For replay, a stream needs a terminated data: [DONE] event and no error events. A quoted marker, a comment or an unfinished frame cannot establish completion. The UI may accept a custom stream’s natural end; that does not make an incomplete server execution replayable.

Timeouts and conversation changes

Current browser limits cover response bodies as well as connection setup: Partial output remains marked interrupted. Starting or selecting another conversation, forgetting it, or deleting the current thread cancels obsolete reads and sends so late replies cannot restore the discarded transcript. Failed deletion preserves the transcript and capability.

Browser privacy and retention

Set settings.security.retentionDays to expire inactive browser transcripts before restoring them. Omit it to retain existing behavior, or use 0 to disable transcript and capability persistence. settings.session.persistThreadTokens: false keeps capabilities in memory. Session storage can be selected through sessionConfig.storage or the session settings alias. Forget this conversation on this device clears its local transcript, saved session and capability. It does not erase server reporting, Redis state, helpdesk tickets or backups. Thread deletion and those systems’ retention policies are separate operations. Persisted attachment labels do not contain file bytes or temporary preview URLs.

When a send looks lost

Check the request ID, thread ID, reply format and capability headers first. Avoid logging tokens or attachment contents. Refresh the same thread before creating another conversation. Confirm readiness on every API replica and shared Redis coordination before treating repeated conflicts as a browser problem. For a human-controlled thread, check the active operator claim and customer polling as described in native live chat.
Last modified on November 13, 2026