From zero to live chatbot.
Four steps, two minutes. No code beyond pasting one snippet — but a full API and SSE stream waits for you when you want to go deeper.
The whole flow, at a glance.
From visitor question → grounded answer in under 300ms. Here's every hop.
Create a chatbot
From the dashboard, click New chatbot. Give it a name, a brief description, and pick a tone. You can change everything later.
Add knowledge
Drop in documents or structured FAQs. Each item is chunked, semantically embedded, and indexed in a vector namespace dedicated to your chatbot.
Embed on your site
Copy the <script> snippet from the Embed tab and paste it before </body>. Or use the iframe variant for in-page placement. The widget inherits your theme.
<script src="https://knot.ai/widget.js" data-chatbot-id="cb_abc123" data-api="https://api.knot.ai" defer ></script>
Watch it work
Conversations, messages, fallback rate and every embedded site appear in real time under Analytics and Embedded sites.
Bring your own provider key.
The dashboard's API keys page is the single place to attach a provider key to your workspace. While a key is active, every chat your bots serve routes through your provider account instead of ours, and the monthly message cap is boosted 5×.
When you paste a key and click Test & save, we hit the provider with one tiny probe. Invalid keys are rejected before they ever land in storage — no broken chats.
Only the first 4 and last 4 chars of the key are returned to the browser. Remove the key any time — chats drop back to the platform default on the next request.
With BYOK active, your plan's monthly message ceiling multiplies by 5. The Usage page surfaces the boosted cap and how much you've consumed against it.
Resolution per chat: per-chatbot key (legacy) → your workspace BYOK → platform default. Nothing else is consulted.
Limits you can plan around.
Every write endpoint enforces your plan's caps server-side. Volume is counted from an append-only ledger, so deleting conversations doesn't refund the count. The Usage page in the dashboard shows live gauges against the current cap.
One visitor message = one ledger row. Visible in real time on the Usage page. BYOK multiplies the cap by 5.
Soft-capped per plan. Hitting the limit returns 402 with a structured error code so the UI can prompt an upgrade.
Total across all of your chatbots. Re-ingesting an existing item doesn't count against the cap.
Counts distinct origins that have loaded your widget. Deactivating an origin from the dashboard frees the slot.
Stream answers from anywhere.
Every chatbot is reachable over a simple POST endpoint that streams tokens via Server-Sent Events. Drop it into your app, Slack bot, CLI — whatever.
curl -N "https://api.knot.ai/chat" \
-H "Content-Type: application/json" \
-H "x-chatbot-id: cb_abc123" \
-d '{
"message": "What is your refund policy?",
"session_id": "anon-9f23"
}'const res = await fetch("/api/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-chatbot-id": "cb_abc123",
},
body: JSON.stringify({ message }),
});
const reader = res.body!.getReader();
const dec = new TextDecoder();
while (true) {
const { value, done } = await reader.read();
if (done) break;
process.stdout.write(dec.decode(value));
}CRUD for chatbots, knowledge, conversations, embedded sites. Bearer-token auth.
Token-by-token responses with retries, abort, and structured event types.
Push every conversation, message, or fallback event into your stack in real time.
See what your bot is actually doing.
Conversations, messages, fallback rate, and every embedded site appear in real time under Analytics. Filter by time, source, or origin.
Isolation, end to end.
Every database table enforces row-level isolation scoped to the signed-in user. No bypass route — admin credentials never leave the backend.
Each chatbot writes & reads inside its own vector namespace. Cross-tenant retrieval is structurally impossible.
Restrict the chat endpoint to a list of trusted origins. Empty list = open; one entry = locked down.
Pro and Enterprise can route everything through their own provider keys — we never see the prompts or responses on the LLM side.