Add AI chat to any website with a drop-in JavaScript widget
The Sigmic AI chat widget lets you embed a fully-featured AI chat interface into any website. Your end users interact with the widget in the browser while your backend handles authentication and configuration.
Create a widget app in the Console. Navigate to the Widget Apps section, click Create Widget App, and configure your app name and allowed origins.After creation, copy the App ID (appId) and App Secret (appSecret) from the portal.
The appSecret is only shown once at creation time. Store it securely on your backend server — never expose it in client-side code.
You can pass per-user env and secrets at token exchange time to connect the agent to each end user’s data. These values are stored server-side (never in the JWT or browser) and injected into your project’s MCP servers as {{mcp.KEY}} template variables.For example, you can configure an MCP server with "Authorization": "Bearer {{mcp.API_TOKEN}}" in its headers, then pass each end user’s API token via secrets — the agent connects to the right service for each user automatically.
Environment Variables & Secrets Guide
Full guide with examples for HTTP, stdio, and SSE MCP servers, template reference, key naming rules, and a complete multi-tenant backend example.
Widget JWTs have a limited lifetime (default 1 hour). For long-running sessions, provide a fetchToken callback so the widget can automatically refresh expired tokens.
app.post('/api/sigmic-chat/token', async (req, res) => { const { userId } = req.body; // Look up user/tenant context for this refresh const user = await db.users.findById(userId); // Exchange credentials for a new widget JWT // Include env/secrets on every refresh — each token gets its own context const response = await fetch('https://api.sigmic.ai/api/v1/auth/token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ appId: process.env.SIGMIC_APP_ID, appSecret: process.env.SIGMIC_APP_SECRET, endUserId: userId, expiresIn: '1h', env: { TENANT_ID: user.tenantId }, secrets: { API_TOKEN: user.apiToken } }) }); const data = await response.json(); res.json({ token: data.data.token });});
Each token has its own env/secrets context. You must pass them on every token exchange, including refreshes — the new token does not inherit values from the previous one. See the Environment Variables & Secrets guide for details.
The fetchToken callback can be synchronous or asynchronous. The widget wraps the return value in Promise.resolve() for compatibility.
The widget communicates with the parent page via postMessage:
window.addEventListener('message', function(e) { if (!e.data || !e.data.type) return; switch (e.data.type) { case 'sigmic-chat-close': // Widget closed break; case 'sigmic-chat-maximize': // Widget expanded to fullscreen break; case 'sigmic-chat-restore': // Widget restored from fullscreen break; case 'sigmic-chat-task': // New task created (e.data.taskId) break; }});