# Znatoka — Integration guide (LLM-ready) > Chat as a service, multi-tenant. Two ways to use it: > 1. Contact-safe buyer<->seller dispute chat: both parties chat over a secret > link WITHOUT seeing each other's real phone/username/contact. You drive it > over a REST API + HMAC webhook. > 2. Support widget for your own site: one ", "seller_embed": "" } Send buyer_url to the buyer and seller_url to the seller. Or drop the ready buyer_embed / seller_embed Options: data-position="left|right", data-color="#5b7cfa", data-label="Help", data-fullscreen="mobile|always|off" (default "mobile" = opens full-screen on phones). ## Support widget — visitor -> you (different from embed.js) embed.js needs a token per party (buyer<->seller disputes you create from your backend). For plain visitor->support chat on your OWN site, use widget.js: one line on every page, no backend call, no token to manage. - widget_key ("wk_...") is PUBLIC — safe in page source. Your api_key is NOT. - Each visitor gets a random id in localStorage; ONE open conversation per visitor is created/restored via POST /w/:widgetKey/session, so a returning visitor lands back in the same thread. Read/reply in the admin inbox. - Options: data-position, data-color, data-label, data-fullscreen (as above), plus data-title-alert="on|off". ### Unread badge (on by default, no setup) A red count appears on the bubble when a reply arrives while the panel is closed. It works because widget.js loads the chat iframe HIDDEN as soon as the page does, so its SSE stream is connected before the bubble is ever clicked; the iframe posts {type:"cdj:unread", count} to the parent, which draws the badge. The count resets when the visitor opens the panel, and last-read is kept per browser in localStorage (cdj_read_), so a reload does not re-announce read messages. If the tab is in the BACKGROUND, the page title also blinks "(N) Pesan baru" and is restored on return; disable with data-title-alert="off". NOTE: the badge and the title blink are the only signals raisable on the host page. Sound + desktop notifications exist inside the chat UI, but browsers block both from a cross-origin frame — do not rely on them for a closed panel. ## Errors Non-2xx returns { "error": "" }, e.g. invalid_api_key (401), quota_exceeded (402). During beta the Free plan has a monthly conversation quota; Pro is unlimited. ## Integration checklist [ ] Store api_key + webhook_secret server-side (never ship to the browser). [ ] On a dispute/refund, POST /api/v1/conversations, keep the returned id. [ ] Deliver buyer_url/seller_url (or buyer_embed/seller_embed) to each party. [ ] (Optional) Expose a webhook endpoint; verify X-Chatdisiniaja-Signature over the raw body. [ ] (Optional) On webhook, notify notify_role via open_conversation_url — skip if you rely on the embed widget / SSE, or poll the transcript. [ ] Close the conversation when the dispute is resolved.