# IntelliDesk ## Docs - [Embed](/docs): Widget script, iframe, single-page apps, JavaScript API (methods, events, options), identify, troubleshooting, session keys, floating initial messages, footer/notice - [Platform guides](/docs/install): WordPress, Shopify, Webflow, Wix, Squarespace, Google Tag Manager, Next.js, React, iframe, React Native, iOS, Android, Flutter, REST API, Node.js, Python - [Identity verification](/docs/identity): Sign users with HMAC-SHA256 or an HS256 JWT; server code for Node, Python, PHP, Ruby, Go - [REST API](/docs/api): Chat (streaming, users), conversations, agents, sources, retrain, leads, errors, rate limits - [Webhooks](/docs/webhooks): Events, payloads, signature verification, retries - [MCP server](/docs/mcp): Use the agent from Claude, Cursor and other MCP clients - [llms.txt](/llms.txt): This index - [docs/llms.txt](/docs/llms.txt): The same index, served under /docs ## Website - [Home](/), [Pricing](/pricing), [About](/about), [Changelog](/changelog) - [Security](/security), [Privacy](/privacy), [Terms](/terms), [Contact](/contact) - Questions or data requests: use the contact form at /contact. ## Embed - Script: `/widget.js` with `data-agent` (agent id or slug) - Global: `window.intellidesk` (open, close, resetChat, setInitialMessages, identify, resetUser, addEventListener). Events: ready, open, close, user-message, assistant-message, error (reason: domain_not_allowed, agent_not_found, identity_required, load_failed). Calls made before the script loads are queued. - resetUser() on logout starts a new anonymous visitor; identifying a different user on the same browser starts a new chat - Host config: `window.intellideskConfig` with `hideLauncher` (or `data-launcher="hidden"`: open from your own button), `showFloatingInitialMessages`, `floatingInitialMessagesDelay`, `floatingMessagesOncePerSession` (overrides dashboard Content flags when those keys are present; otherwise the saved widget content/style is used) - Identity: `window.intellideskUserConfig` or `window.intellidesk("identify", { token | user_id+user_hash, … })`. user_hash = hex HMAC-SHA256(identity secret, user_id), computed on your server - Iframe: `/embed/{slug|agentId}` with `allow="microphone; clipboard-write"`; allowed domains apply to the page it's on - Session keys: `id_visitor_{agentId}`, `id_convo_{source}_{agentId}` (legacy `id_convo_{agentId}` is migrated for the bubble), floating once-per-session `id_float_{agentId}` - Preview: `/preview/{slug|agentId}` empty-page public widget preview - Help: `/help/{slug|agentId}`. Local rewrite: `/help-proxy/{slug|agentId}`. Customer origin: proxy `/help`, `/__id/*` (assets + `/__id/api` public chat) to this app. Copy nginx/Caddy/Next snippets on Deploy → Help → Domain. No custom DNS or TLS from IntelliDesk. ## REST API (server-side, secret key) - OpenAPI 3.1 spec: /openapi.json - Base: `/api/v1`, header `Authorization: Bearer idk_live_…` (API keys page). Scopes: chat, read, write. No CORS. - POST /api/v1/agents/:id/chat { message, conversationId?, user?: { id, email?, name?, phone?, attributes? }, visitorId?, metadata?, stream? } → { data: { conversationId, messageId, reply, sources, handoff, collectLead, bookCall } }. stream=true: SSE events token, done, error. - GET /api/v1/agents, /agents/:id, /agents/:id/conversations?limit&before, /conversations/:id, /agents/:id/sources, /agents/:id/leads - POST /api/v1/agents/:id/sources { type: text|qa|website, … } (201), POST /agents/:id/retrain (202) - Errors: { error: { status, code, message } }; codes invalid_request, unauthorized, out_of_credits (402), forbidden, owner_unverified, not_found, conversation_not_found, rate_limited (429 + Retry-After), internal_error. 120 requests/min per key. ## Webhooks - Events: leads.submit, data.submit, message.feedback, conversation.completed. Body { event, payload, agentId, sentAt, deliveryId }. - Headers: X-IntelliDesk-Event, X-IntelliDesk-Signature (sha256= hex HMAC of the raw body with the endpoint's signing secret), X-IntelliDesk-Delivery, X-IntelliDesk-Attempt. - Retries after 30 s, 2 min, 10 min on network errors, 408, 429 and 5xx; same body and delivery id. ## MCP - Streamable HTTP at /api/mcp with the same secret keys. Tools: list_agents, ask_agent, search_knowledge, list_conversations, get_conversation, list_leads, list_knowledge_gaps. ## Public routes - GET /api/public/agent/:agentIdOrSlug — Widget config. Allowed domain + public visibility. Id or slug. - GET /api/public/conversation/:id — Restore messages when visitorId matches. - GET /api/public/conversations — This visitor’s widget/help threads. - DELETE /api/public/conversation/:id — Visitor may delete their own thread. - POST /api/public/conversation/:id/transcript — Email the thread to the address the visitor gave in it (3 an hour). - POST /api/public/chat — HTTP chat. Same domain, rate-limit, and identify rules as Socket.io. Optional attachmentIds after POST /api/public/attachment. Optional voice=true marks the visitor turn as spoken. - POST /api/chat/:agentId — Help-proxy alias for POST /api/public/chat. agentId can live in the path. - GET /__id/* — Help page proxy assets and /__id/api/* public routes. /__id/help/:slug is the rewritten help HTML. - POST /api/public/leads — Lead form (also /api/leads). Domain lock; returns only the visitor's own details. - POST /api/public/feedback — Thumbs up or down on a reply (also /api/feedback). Domain lock. - POST /api/public/attachment — Visitor file upload (images, pdf, txt, docx). Domain + rate-limit + channel-off rules. - GET /api/public/attachment/:id — Download a visitor file when visitorId matches. - GET /api/public/demo — Demo agent payload. - Socket.io chat:start — Public stream. source=widget or help. Optional handoff=true requests a human when Live chat is on. - Socket.io chat:join / operator:message — Visitor joins a conversation room and receives operator replies. Playground chats are `source=playground` and use the signed-in dashboard session. They do not write visitor session keys. No secrets are published here. Generate the identity secret in Deploy → Chat widget → Embed.