Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.sigmic.ai/llms.txt

Use this file to discover all available pages before exploring further.

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.

Architecture

Your Backend                         Sigmic AI API                      Browser Widget
     |                                    |                                |
     |  1. POST /api/v1/auth/token        |                                |
     |    { appId, appSecret, endUserId,  |                                |
     |      env, secrets }                |                                |
     |----------------------------------->|                                |
     |    { token, expiresAt }            |                                |
     |<-----------------------------------|                                |
     |                                    |                                |
     |  2. Return JWT to browser          |                                |
     |------------------------------------------------------->|           |
     |                                    |                                |
     |                                    |  3. Chat via widget            |
     |                                    |    Authorization: Bearer eyJ... |
     |                                    |<-------------------------------|
     |                                    |    Streaming response          |
     |                                    |------------------------------->|
  1. Your backend calls the token endpoint with credentials + optional env/secrets (credentials stay server-side)
  2. Your backend sends the short-lived JWT to the browser
  3. The browser uses the JWT to chat via the embedded widget

Setup

1. Create a Widget App

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.

2. Exchange Credentials for a JWT

From your backend, call the token endpoint:
POST /api/v1/auth/token
Content-Type: application/json
{
  "appId": "wapp_a1b2c3d4e5f6",
  "appSecret": "wsec_7890abcdef...",
  "endUserId": "user-123",
  "expiresIn": "1h",
  "env": {
    "TENANT": "acme-corp",
    "REGION": "us-east-1"
  },
  "secrets": {
    "DB_URL": "postgres://...",
    "API_TOKEN": "sk-..."
  }
}
FieldTypeRequiredDefaultDescription
appIdstringYesWidget app’s public App ID
appSecretstringYesWidget app’s secret
endUserIdstringYesYour end user’s identifier (scopes conversations to this user)
expiresInstringNo"1h"Token lifetime: "30m", "1h", "7d", etc.
envobjectNoNon-sensitive environment variables (stored as JSON)
secretsobjectNoSensitive environment variables (encrypted at rest, never logged)
Response:
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "expiresAt": "2026-01-31T12:00:00.000Z"
  }
}

3. Embed the Widget

Add two script tags to your page — no build step required:
<script>
  window.SigmicChat = {
    token: 'JWT_TOKEN_FROM_YOUR_BACKEND',
    host: 'https://api.sigmic.ai'
  };
</script>
<script src="https://api.sigmic.ai/widget/sigmic-chat.js" async></script>
This creates a floating chat button in the bottom-right corner. Clicking it opens a full chat UI.

Live Demo

See the widget in action on a live customer website:

Live Customer Demo

A live website that embeds the Sigmic AI chat widget with custom branding, logo, and per-user context. Visit simple-agent-chat.space to try it.

Passing Environment Variables & Secrets

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 Configuration

window.SigmicChat = {
  token: 'JWT_TOKEN',         // Required — JWT from your backend
  host: '...',                // Backend URL (auto-detected from script src if omitted)
  position: 'bottom-right',   // Or 'bottom-left'
  title: 'Chat with AI',      // Chat header title
  open: false,                 // Set true to start with widget open
  fetchToken: async () => {    // Optional — callback to refresh expired JWTs
    const res = await fetch('/api/sigmic-token');
    const data = await res.json();
    return data.token;
  }
};

Token Refresh

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.

How it works

  1. Proactive refresh: ~60 seconds before the token expires, the widget requests a new token from the parent page
  2. Reactive refresh: If an API call returns 401, the widget requests a new token and retries the request once
  3. No fetchToken: If fetchToken is not provided, behavior is unchanged — a 401 on expiry is surfaced as an error

Configuration

window.SigmicChat = {
  token: 'INITIAL_JWT_TOKEN',
  host: 'https://api.sigmic.ai',
  fetchToken: async function() {
    // Call your backend to get a fresh JWT
    const response = await fetch('/api/sigmic-chat/token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: currentUser.id })
    });
    const data = await response.json();
    return data.token;
  }
};

Backend example (Express)

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.

Widget Events

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;
  }
});

End User Scoping

The endUserId field isolates data between your end users:
  • Conversations are scoped to the endUserId embedded in the JWT
  • One end user cannot access another’s conversation history
  • Use a stable identifier from your system (database ID, email hash, etc.)

Authentication Details

JWT Claims

ClaimDescription
appIdYour Widget App ID
subThe endUserId you provided
allowedOriginsOrigins allowed to use this token
jtiUnique token ID (present when env/secrets are provided)
iatIssued-at timestamp
expExpiration timestamp

Expiration Format

FormatExampleDescription
Seconds"300s"5 minutes
Minutes"30m"30 minutes
Hours"1h"1 hour
Days"7d"7 days

Origin Validation

When a widget app has allowedOrigins configured, the server validates the Origin header on every JWT-authenticated request.
  • Set allowedOrigins to ["*"] to allow all origins (not recommended for production)
  • Leave allowedOrigins empty to skip origin validation
  • Origins must match exactly (e.g., https://mysite.com does not match https://www.mysite.com)

Error Codes

CodeHTTP StatusDescription
JWT_NOT_CONFIGURED501Server JWT signing not configured
MISSING_CREDENTIALS400appId or appSecret not provided
MISSING_END_USER_ID400endUserId not provided or empty
INVALID_EXPIRES_IN400expiresIn format invalid
INVALID_ENV400Invalid env var name or non-string value
INVALID_CREDENTIALS401App ID or secret is incorrect
INVALID_TOKEN401JWT is invalid or expired
ORIGIN_NOT_ALLOWED403Request origin not in allowed list