DokumentasjonSikkerhet og dataMarkdown
Security and data
Secrets and tokens
- Secret API keys (
sk_snakkbar_…) identify a tenant's backend. Keep them server-side; rotate by creating a new key, deploying it, then revoking the old one. Snakkbar stores only a hash. - Operator tokens are signed JWTs bound to one tenant and one operator, ≤ 24 h. Mint them only for your authenticated staff, and only with the role they should have.
- Visitor tokens: anonymous ones are random and stored hashed; identified ones are signed JWTs
bound to your
externalId. A visitor can only read and write its own conversations. - Tokens are sent as
Authorization: Bearer. Snakkbar never uses cookies across sites, so CSRF does not apply; the origin allow-list stops other sites from using a visitor's token in the browser.
Origins
Only origins in the tenant's allowed list can run the widget and the embedded admin. Add every
production origin (with and without www), and staging origins as needed. http://localhost is
allowed outside production.
What visitors can see
Visitors see their own conversation: messages, operator names and photos, typing and read state.
They never see staff-only notes (handoff summaries), other conversations, operator emails or
tenant settings beyond the public config.
Content
- Assistant output is Markdown rendered without raw HTML; links open in a new tab with
rel="noopener". - Uploads are checked by their bytes (JPEG, PNG, WebP, GIF) and served through short-lived signed URLs.
- Operator "move visitor" only allows URLs on the tenant's own site.
Visitor profiles
Details sent from the browser (PATCH /visitor/me, the widget's setUser, data-user-*) are
unverified: anyone can send anything from a browser. For an anonymous visitor they are stored
as sent. For an identified visitor the browser can only fill name, email, phone and
company while they are empty, and only add attributes keys that don't exist yet (never change
or remove one); values from your backend (POST /server/visitor-tokens) always win. A key only
the browser has set is still browser data, so set anything that must be trusted from your backend.
Staff see verified on identified visitors, and the assistant is told when details are
unconfirmed. Never put secrets in a profile; staff see all of it.
Live visitors
With the tenant's liveVisitors switch on (default), the widget (or the SDK's startTracking())
reports each open page so staff can see who is on the site. See
widget.md → Live visitors for the switch and consent.
Collected: the page URL and title; the referrer as origin and path only; tab visibility; viewport size, scroll position and page height; the user agent (shown as device type, browser and OS); country and city from the hosting's geo headers at session start (the IP address is not stored on the visitor); and timestamps. Pointer positions and clicks (as coordinates) are sent only while an operator is watching that visitor. They are relayed to the operators' streams and not saved with the visitor or its history (the realtime transport keeps its own short-lived message log, like for every doorbell event).
Never collected: page content, the DOM, form values, keystrokes, text selections or screenshots. The live view is not a recording: the operator sees the public page re-loaded in their own browser, with the visitor's cursor drawn on top.
URL cleaning. Before a page URL (live visitors' current page, navigation history and
pointer events, and the pageUrl of conversations and messages) is stored, shown to staff or
loaded in a live view, Snakkbar keeps
only http(s) URLs, removes user name and password, drops query parameters whose names look like
credentials (token, secret, password, code, state, auth…, key, api_key, sig,
signature, session, sid, otp, reset…, ticket, jwt, nonce, hash and similar) and
drops fragments that carry data (#access_token=…; hash routes such as #/products/12 stay).
This way a one-time login, reset or payment link is never replayed from an operator's browser.
Use startTracking({ url }) to report even less (e.g. without ids in the path). Referrers are cut
to origin and path.
The live view runs in the operator's browser. It loads the cleaned public URL with the
operator's own cookies and session, never the visitor's, so it does not show the visitor's
logged-in content, basket or form input; pages behind a login usually show their logged-out
version or a login form. The page's own scripts (including any analytics) do run in the
operator's browser. The page is framed in a sandboxed iframe without forms, popups or top-level
navigation (admin-embed.md), and the customer's site
must opt in to being framed (frame-ancestors).
Who sees it. Any operator of the tenant (both roles) can list visitors, open their history and watch them.
Retention
Conversations, messages and images are deleted automatically after the tenant's retention period (7, 30, 90 or 365 days since the last message; default 90). Admins can delete a conversation at any time.
The same period applies to live-visitor data: navigation history (pageviews) older than the retention period is deleted, and visitors who never chatted are deleted once they have not been seen for that long. Visitors with conversations are kept as long as their conversations.
Rate limits
See api.md → Rate limits. Limits are shared across all servers.