Total Chat Documentation
Total Chat is a script-tag AI chat product that integrates into your web application in one line. It provides screen-aware customer support and lead generation — all with flat monthly pricing.
Unlike generic chat widgets, Total Chat knows what page a user is on and can point them to a specific page and highlight an element for them — no ticket, no "which screen are you looking at?"
Key Capabilities
- Screen-Aware AI — Knows the current page/route on every message
- Navigation & Walkthroughs — Moves a user to a page, highlights an element, or walks them through one feature step by step (Starter+)
- Self-Evolving KB — Drafts knowledge articles from real conversations (Starter+; you approve each one)
- Lead Generation — Fingerprinting, UTM tracking and email capture on every plan
- Bug Routing — Users report bugs in chat; a developer agent reads your repo and Sentry and drafts a fix (Starter+)
- Ticketing — Bug reports filed in Zendesk, Jira, Linear, Freshdesk, Help Scout or any webhook (Pro+)
- CRM — Leads posted to HubSpot, Salesforce, GoHighLevel or any webhook (Pro+)
Quickstart
Get Total Chat running in your app in 3 steps:
1. Register Your App
curl -X POST https://totalchat.hub.danielswick.com/api/onboarding/register \
-H "Content-Type: application/json" \
-d '{
"appId": "my-app",
"appName": "My App",
"ownerEmail": "[email protected]"
}'
Save the appId and apiKey from the response. The API key is shown only once — store it securely.
2. Add the Script Tag
<script
src="https://totalchat.hub.danielswick.com/widget.js"
data-app-id="YOUR_APP_ID"
data-position="bottom-right"
></script>
3. Scan Your Codebase (Optional)
TOTALCHAT_API_KEY=YOUR_API_KEY npx @totalchat/cli scan --dir . --app-id YOUR_APP_ID --upload
This generates a micro-function map of every route, feature, and interactive element in your app — giving Total Chat deep knowledge of your UI.
Installation
Total Chat installs as a single script tag — no npm package, no build step:
<script
src="https://totalchat.hub.danielswick.com/widget.js"
data-app-id="YOUR_APP_ID"
data-position="bottom-right"
data-greeting="Hi! How can I help?"
></script>
On pages where a user is logged in, add data-user-token with a token your server signs for that user (see Logged-in Users) to switch the widget to internal mode (screen-aware help, navigation, walkthroughs). Without a valid token the widget runs in external mode for visitors. The widget colour comes from Settings → Primary Color in your dashboard; data-color overrides it on a page.
The widget loads asynchronously and won't block your page. Total bundle impact: ~15KB gzipped.
Script Tag Integration
The script tag is the simplest way to add Total Chat. Perfect for marketing sites, landing pages, or any site where you want lead capture and support without a build step. For a longer walkthrough of the script-tag approach, see how to embed an AI chatbot in a web application.
Available Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
data-app-id | string | required | Your app ID from registration |
data-user-token | string | — | A signed token for the logged-in user (how to sign). Valid = internal mode; absent or invalid = external mode for visitors. data-user-id on its own is ignored. |
data-position | string | "bottom-right" | "bottom-right" or "bottom-left" |
data-color | string | dashboard setting | Hex colour; overrides the Primary Color saved in dashboard Settings |
data-title | string | "Help & Support" | Chat window header |
data-avatar | string | "💬" | Emoji or short text shown as the assistant's avatar |
data-greeting | string | built-in greeting | Opening message |
Configuration
Total Chat is configured via the script tag's data-* attributes (see the table above) plus the dashboard for branding, KB curation, and integrations — there's no separate SDK config object. Escalation email/webhook and other account-level settings are set from the dashboard, not the script tag.
Logged-in Users (Signed Tokens)
Internal mode shows internal-only articles and can act on the user's screen, so Total Chat only grants it to users your server vouches for. Your server signs a short-lived token for the signed-in user; the widget passes it along; Total Chat checks the signature. Anyone can copy a user ID out of a page, but nobody can sign a token without your secret.
- In the dashboard, open Settings → Logged-in users and create a secret (or
POST /api/dashboard/identity-secretwith{ "appId": "..." }and your API key). It is shown once. Keep it in your server's environment, never in browser code. - On each page load for a signed-in user, sign a JWT with HS256 and that secret. Claims:
sub(the user's id, required),exp(required, at most 24 hours ahead — 1 hour is a good default), and optionallyname,email,plan. - Render it in the script tag as
data-user-token. To refresh it in a single-page app, update the attribute; the widget reads it on every request.
// npm install jsonwebtoken — or any JWT library that signs HS256
const jwt = require('jsonwebtoken');
const userToken = jwt.sign(
{ sub: user.id, name: user.name, email: user.email, plan: user.plan },
process.env.TOTALCHAT_IDENTITY_SECRET,
{ algorithm: 'HS256', expiresIn: '1h' }
);
// in your page template
`<script src="https://totalchat.hub.danielswick.com/widget.js"
data-app-id="YOUR_APP_ID" data-user-token="${userToken}"></script>`
- Only HS256 is accepted. Expired tokens, tokens valid for more than 24 hours, tokens without
sub, and bad signatures all fall back to visitor mode (the chat still works). - Replacing the secret stops every token signed with the old one immediately.
- The user's name, email and plan reach the assistant only from the token, never from the browser.
Plans & Limits
Limits reset on the 1st of each calendar month. Messages count what your users send; the assistant's replies don't count. When either monthly cap is reached, new conversations and messages return 429 Usage limit reached until the reset or an upgrade. The article cap counts published articles; drafts waiting for review don't count, and publishing past the cap returns 403 PLAN_LIMIT.
| Free | Starter | Pro | Business | |
|---|---|---|---|---|
| Price / month | $0 | $49 | $99 | $249 |
| Conversations / month | 50 | 500 | 2,500 | 10,000 |
| Messages / month | 300 | 5,000 | 30,000 | 150,000 |
| Published KB articles | 20 | 100 | 500 | Unlimited |
| Lead capture, UTM, scanner, crawler, in-chat bug reports, branding | ✓ | ✓ | ✓ | ✓ |
| Navigation & highlight (internal mode) | — | ✓ | ✓ | ✓ |
| Self-evolving KB drafts | — | ✓ | ✓ | ✓ |
| Developer agent investigations / month | — | 25 | 60 | 150 |
| CRM webhooks | — | — | ✓ | ✓ |
| Ticketing (Zendesk, Jira, Linear…) | — | — | ✓ | ✓ |
| Support | Community | Priority |
Enterprise is custom-priced: unlimited conversations, messages and articles, 300 investigations a month, priority support. Contact sales.
Screen Awareness
Total Chat sends the user's current route with every message, so the AI's answer is grounded in what page they're actually looking at right now — not a generic FAQ answer disconnected from context.
- Current route — e.g.,
/dashboard/settings, sent fresh on every message
Once your function map is uploaded, the widget fills in screenState automatically: any open dialog ([role="dialog"] or .modal), the active tab, and the features available on the current page. Reading active filters, form state or other visible elements isn't built yet. If you call the messages API directly, screenState accepts a short freeform string you control, describing whatever's relevant.
Knowledge Base
Total Chat's knowledge base uses semantic search (pgvector embeddings) to find relevant answers even when users phrase questions differently.
Auto-Drafted Articles
On paid plans, when a conversation exposes a question the KB doesn't cover, Total Chat drafts a new article from that conversation. You'll receive an email notification to approve, edit, or reject it, and nothing goes live until you approve it.
Public vs. Internal Articles
Each KB article has an isPublicVisible flag (default: true). In external mode, only public articles are searched — protecting internal procedures, pricing logic, and admin docs from pre-login visitors. In internal mode, all published articles are available.
- Set
isPublicVisible: falseon internal-only articles (e.g., billing workarounds, admin processes) - Public articles are seen by both logged-in users and anonymous visitors
- This filtering is server-enforced — clients cannot override it
KB Search API
GET /api/kb/search?q=how+to+export&appId=YOUR_APP_ID&limit=5
Returns semantically similar articles ranked by relevance score.
Lead Capture
In external mode, Total Chat captures visitor information for your sales pipeline, on every plan.
What's Captured
- Digital fingerprint — First-party cookies + localStorage (privacy-friendly)
- UTM parameters — Source, medium, campaign, content, term
- Referrer — Where the visitor came from
- Email — Collected via configurable prompt
- Conversation context — What they asked about, pages visited
CRM Delivery
On the Pro plan and up, leads are automatically pushed to your configured CRM via webhooks. On Free and Starter they stay in your dashboard. See CRM Webhooks.
Bug Routing & the Developer Agent
When a user tells the assistant something is broken, it asks a short follow-up if needed, then files a structured bug report: what happened, what they expected, steps to reproduce, severity, the page address, their browser, and the last few JavaScript errors on the page. Every report appears under Reports in your dashboard, linked to the full conversation. This works in both modes and on every plan.
Developer Agent (Starter plan and up)
Connect your GitHub repository and the developer agent investigates each bug report automatically. It reads your code on the branch you choose, starting from the page where the bug happened, checks your Sentry errors if you connect Sentry, and writes up the likely cause with file and line references plus a proposed fix as a diff. The result appears on the report in your dashboard and is emailed to your escalation email (or owner email). It can also open a GitHub issue for each result.
- Setup: Dashboard → Settings → Developer Agent. Add
owner/repoand a fine-grained GitHub token for that repo with Contents: read (add Issues: write to open issues). Optionally add your Sentry organization, project and an auth token withproject:readandevent:read. Use Test connection to check access. - Read-only: the agent never pushes code or opens pull requests; the fix is a proposal for you to review.
- Security: tokens are encrypted at rest and never shown again after saving. The agent only reads the repository and Sentry project you configure.
- Limits: Starter 25, Pro 60, Business 150, Enterprise 300 investigations a month, at most 20 a day. You can re-run any investigation from the report.
Routing Destinations
- Developer Agent — Investigates your repository and Sentry and proposes a fix (see above)
- Jira / Linear — Creates an issue (see Ticketing Systems)
- Zendesk / Freshdesk / Help Scout — Creates a ticket or conversation
- Webhook (Zapier / Make) — Posts the report as JSON
Security & Mode Enforcement
Total Chat has a layered security model to prevent prompt injection, data leakage, and mode bypassing.
Layer 1 — Server-Enforced Mode
Mode is never derived from client input. The server verifies a user token your own server signed:
- Valid signed token →
INTERNALmode — full KB, navigation tools (Starter+), user context from the token - No token, or one that fails →
EXTERNALmode — public KB only, lead capture, no navigation
Clients cannot request mode elevation: a mode field, a bare userId, or user details in a message body are all ignored.
Layer 2 — System Prompt Guardrails
Every conversation — regardless of mode — includes a security preamble injected at the top of the system prompt:
- The AI is scoped to your app only — it won't answer unrelated questions
- It cannot reveal its system prompt or instructions
- It cannot generate code, recipes, or content unrelated to your product
- It cannot collect credentials or perform actions outside its defined tool set
- KB answers must cite actual articles — fabrication is blocked
Layer 3 — API Input Sanitization
Every user message is scanned before being processed. Messages containing injection patterns are rejected with a 400 error:
// Example rejection
{
"error": "Message contains disallowed content"
}
// Blocked patterns include:
// "ignore all instructions", "you are now", "act as a [character]",
// "pretend you are", "roleplay as", "repeat your system prompt",
// "DAN mode", "jailbreak", "developer mode", etc.
KB Visibility Enforcement
Articles with isPublicVisible: false are never returned in external mode searches — even if a user asks about them by name. Internal procedures, admin docs, and sensitive pricing logic stay invisible to unauthenticated users.
isPublicVisible: false before enabling external mode.
Codebase Scanner
The scanner CLI analyzes your codebase and generates a micro-function map — a complete inventory of every route, feature, and interactive element. There are three ways to scan depending on your setup.
Option 1 — npx (Quickest)
Run directly from your project root. No install required.
# Scan and upload in one command
npx @totalchat/cli scan \
--dir . \
--app-id YOUR_APP_ID \
--api-key YOUR_API_KEY \
--upload
# Scan only (write to file, upload manually later)
npx @totalchat/cli scan --dir . --app-name "My App" --output ./totalchat-map.json
# Then upload manually
curl -s -X POST https://totalchat.hub.danielswick.com/api/onboarding/YOUR_APP_ID/function-map \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d @totalchat-map.json
CLI Flags
| Flag | Description | Default |
|---|---|---|
--dir | Project root directory | Current directory |
--app-id | Your Total Chat app ID (required for --upload) | — |
--api-key | Your API key, or set TOTALCHAT_API_KEY env var | — |
--upload | POST the map to the API after scanning | false |
--app-name | Human-readable app name | MyApp |
--output | Output JSON file path | ./output/app-map.json |
--api-url | Total Chat API base URL | https://totalchat.hub.danielswick.com |
Framework auto-detection: The scanner automatically finds your app directory by trying src/app, app, src/pages, pages, and dashboard/src/app in order. No configuration needed for standard Next.js projects.
When to Re-scan
- After adding new pages or major features
- After restructuring your navigation
- When the freshness check shows
staleorwarn
# Check your function map freshness
curl https://totalchat.hub.danielswick.com/api/onboarding/YOUR_APP_ID/function-map/freshness
# Response:
# { "status": "fresh", "ageDays": 2, "currentVersion": 4 }
# { "status": "stale", "recommendation": "Re-scan recommended" }
What Gets Scanned
- Routes — All pages, dynamic params, route groups
- Features — Buttons, forms, links, and interactive elements
- Components — Your component inventory
- data-guide attributes — Existing navigation anchors
- Recommendations — Suggested
data-guideplacements (P1/P2/P3)
GitHub Action — Automatic Rescanning
Automatically rescan and upload your function map on every push to main. Add this to your repository once and never think about rescanning again.
# .github/workflows/totalchat.yml
name: Total Chat Sync
on:
push:
branches: [main]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Scan and upload function map
run: npx --yes @totalchat/cli@0 scan --dir . --app-id YOUR_APP_ID --upload
env:
TOTALCHAT_API_KEY: ${{ secrets.TOTALCHAT_API_KEY }}
Add TOTALCHAT_API_KEY to your GitHub repository secrets (Settings → Secrets → Actions). The step finds your Next.js app directory, records the commit it scanned, and uploads the map. It uses only GitHub's own actions plus the published CLI, so there is no third-party action to trust with your key.
The step accepts the same flags as the CLI (see CLI Flags) — for example --dir ./web for a monorepo.
AI URL Crawler — No Code Required
Don't want to run a scanner? Point Total Chat at your live site and the AI will crawl it, read your pages, and generate knowledge base articles automatically. No CLI, no GitHub Action, no code changes needed.
POST /api/onboarding/:appId/crawl
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"url": "https://yourapp.com",
"maxPages": 20,
"generateArticles": true
}
curl -s -X POST https://totalchat.hub.danielswick.com/api/onboarding/YOUR_APP_ID/crawl \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://yourapp.com", "maxPages": 20 }'
What happens:
- Total Chat fetches your root URL and follows internal links (same domain only)
- For each page, it extracts the title, headings, and visible text
- The AI reads all pages and generates 3–8 knowledge base articles
- Articles are saved as AI drafts — you review and publish from the dashboard
Response
{
"crawled": 14,
"articlesGenerated": 6,
"articles": [
{ "id": "...", "title": "Getting Started", "category": "onboarding", "isPublicVisible": true },
{ "id": "...", "title": "Managing Your Account", "category": "account", "isPublicVisible": false }
]
}
Best for: Marketing sites, documentation sites, or any app where a crawl gives the AI enough content to work with. For navigate/highlight to work reliably against your actual UI (via data-guide selectors), pair with the CLI scanner.
data-guide Attributes
These attributes help Total Chat identify and navigate to specific UI elements:
<!-- P1: Critical navigation elements -->
<button data-guide="export-data">Export</button>
<a data-guide="nav-settings" href="/settings">Settings</a>
<!-- P2: Important interactive elements -->
<input data-guide="search-input" placeholder="Search..." />
<select data-guide="filter-status">...</select>
<!-- P3: Supporting elements -->
<div data-guide="dashboard-chart">...</div>
The scanner CLI generates a prioritized list of recommendations showing exactly where to add these attributes. P1 items have the highest impact on navigation accuracy.
API: Conversations
Create Conversation
POST /api/conversations
Content-Type: application/json
{
"appId": "YOUR_APP_ID",
"userToken": "optional signed token for a logged-in user",
"fingerprintId": "optional visitor id"
}
mode field is derived server-side — with a valid userToken the conversation is INTERNAL (full KB, navigation tools, screen awareness) and its user is the token's sub. Without one it's EXTERNAL (public KB only, lead capture). Clients cannot override this. Send the same userToken with each message so the assistant knows the user's name and plan.
Get Conversation
GET /api/conversations/:id
API: Messages
Send Message
POST /api/conversations/:id/messages
Content-Type: application/json
{
"content": "How do I export my data?",
"pageContext": { "route": "/dashboard" },
"screenState": "optional freeform string describing extra state you control"
}
The response is a server-sent events stream. Each event is a data: line holding JSON with a type: text_delta chunks as the AI writes, tool_invoked/tool_result as it works, a navigate, highlight or walkthrough_start event if it decides to move the user, and message_complete at the end (or error). The widget performs one navigation per turn (the last), and a walkthrough_start replaces any bare navigate/highlight in the same turn:
data: {"type":"text_delta","content":"I can see you're on the Dashboard. "}
data: {"type":"navigate","path":"/settings/export","reason":"Export lives in Settings"}
data: {"type":"highlight","dataGuide":"export-btn","label":"Export"}
data: {"type":"message_complete","messageId":"msg_123","fullText":"I can see you're on the Dashboard. ..."}
API: Knowledge Base
Search KB
GET /api/kb/search?q=export+data&appId=YOUR_APP_ID&limit=5
Create Article
POST /api/kb/articles
Content-Type: application/json
{
"appId": "YOUR_APP_ID",
"title": "How to Export Dashboard Data",
"content": "Navigate to Settings > Export...",
"category": "data-management",
"pageRoute": "/settings/export",
"approved": true
}
API: Onboarding
Register App
POST /api/onboarding/register
Content-Type: application/json
{
"appId": "my-app",
"appName": "My App",
"ownerEmail": "[email protected]",
"integrationMode": "FULL",
"aiPersonality": "friendly",
"escalationEmail": "[email protected]",
"bugRouteTarget": "my-agent-topic"
}
| Field | Required | Description |
|---|---|---|
appId | ✓ | Unique identifier for your app (lowercase, hyphens ok) |
appName | ✓ | Display name for the app |
ownerEmail | ✓ | Email for KB draft notifications and escalations |
integrationMode | FULL (default), HEADLESS, or EXTERNAL_ONLY | |
aiPersonality | Tone for AI responses (e.g. friendly, professional) | |
escalationEmail | Human support email for tier-3 escalations | |
bugRouteTarget | Agent Hub topic for bug report routing |
The response includes your apiKey (shown once — store it securely) and full app config.
Upload Function Map
POST /api/onboarding/:appId/function-map
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
{
// Output from totalchat scan / npx @totalchat/cli scan
"app": { "name": "My App", "framework": "nextjs" },
"routes": [...],
"features": [...],
"stats": { "totalRoutes": 14, "totalFeatures": 47 }
}
Check Function Map Freshness
GET /api/onboarding/:appId/function-map/freshness
Authorization: Bearer YOUR_API_KEY
// Response:
{
"appId": "my-app",
"status": "fresh", // "fresh" | "warn" | "stale"
"ageDays": 2,
"currentVersion": 4,
"recommendation": "Function map is current."
}
AI URL Crawler
Crawl a live URL and auto-generate KB articles. No scanner required.
POST /api/onboarding/:appId/crawl
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
{
"url": "https://yourapp.com",
"maxPages": 20, // optional, default 20
"generateArticles": true // optional, default true
}
// Response:
{
"crawled": 14,
"articlesGenerated": 6,
"articles": [
{ "id": "...", "title": "Getting Started", "category": "onboarding" }
]
}
Deploy Notify
Call after each deploy to keep the freshness check accurate.
curl -s -X POST https://totalchat.hub.danielswick.com/api/onboarding/YOUR_APP_ID/deploy-notify \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"commitSha\": \"$(git rev-parse HEAD)\", \"environment\": \"production\"}"
API: Webhooks
Configure webhooks in your app settings to receive real-time events.
Event Types
| Event | Description |
|---|---|
conversation.created | New conversation started |
conversation.resolved | Conversation marked resolved |
lead.captured | New lead captured (email collected) |
report.created | Bug/feature report submitted |
kb.article_drafted | New KB article auto-drafted |
CRM Webhooks
Total Chat can push leads to your CRM automatically. Configure in your app settings.
Supported CRMs
- HubSpot — Contacts + Deals
- Salesforce — Leads + Contacts
- GoHighLevel — Contacts + Opportunities
- Pipedrive — Persons + Deals
- Zapier / Make — Universal webhook (works with any CRM)
Lead Data Format
{
"email": "[email protected]",
"name": "Jane Doe",
"company": "Acme Corp",
"title": "VP Engineering",
"phone": "+1-555-0123",
"source": {
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "brand-awareness"
},
"conversation": {
"firstMessage": "Do you have a free trial?",
"pagesVisited": ["/", "/features", "/pricing", "/docs"]
}
}
Ticketing Systems
Every bug report filed from chat can also be created in your helpdesk or issue tracker. Set it up under Dashboard → Integrations → Bug report destinations: pick a system, enter the details below, save, then use Test connection. Pro plan and up.
Supported Systems
- Zendesk — Ticket (type Problem, your report's priority, tag
totalchat). The report is an internal note, so your end user is not emailed. Needs: subdomain, agent email, API token. - Freshdesk — Ticket with priority and tags, filed under a requester email you choose. Needs: domain, requester email, API key.
- Jira Cloud (Software or Service Management) — Issue in your project, type Bug unless you pick another. Needs: site, account email, API token, project key.
- Linear — Issue in your team with priority and, optionally, an existing label. Needs: personal API key, team key.
- Help Scout — Conversation in a mailbox, from a customer address you choose (no auto-reply). Needs: My Apps app ID and secret, mailbox ID.
- Webhook (Zapier / Make / your endpoint) —
POSTof JSON{"event": "report.created", "report": {...}, "text": "..."}. Add a signing secret to get anX-TotalChat-Signature: sha256=<HMAC of the body>header.
What each ticket contains
Title, what happened, steps to reproduce, expected result, page URL, the last JavaScript errors from the page, browser, the recent conversation, and a link back to your dashboard. The text comes from your end user, so treat it like any customer-submitted ticket.
Delivery
- Tickets are created within seconds of the report. Each ticket links back from the report in Dashboard → Reports.
- Temporary failures (timeouts, rate limits, 5xx) are retried twice. Credential or configuration errors stop immediately. Failed deliveries show under Integrations → Recent Webhook Deliveries with the error and a Retry button.
- Credentials are encrypted at rest and never shown again after saving.