Developers
An API. Not a dashboard locked behind a login.
Everything you can do in the FlowChat admin panel, you can do via REST. Chat is SSE-streamed. Webhooks are HMAC-signed. Widget keys are KV-cached at the edge and revocable in <60s.
API surface
Four endpoints. One widget. One webhook channel.
https://chat.flowchat.com/v1/chat Chat (HTTP + SSE)
Same endpoint the embeddable widget uses. Streams answer tokens as SSE; emits the same retrieval/generation/NLI events the live demo on the homepage visualises.
Auth X-FlowChat-Key header
https://api.flowchat.com/v1/sources Sources
List, create, recrawl, revoke. Triggering a recrawl writes to the Cloudflare ingest-requests queue and returns a job ID you can poll.
Auth Bearer token (admin API key)
https://api.flowchat.com/v1/usage Usage events
Per-tenant query/cost rollups, paginated by day. The same data drives Stripe metered billing on the Cashier integration.
Auth Bearer token
— Webhooks
FlowChat → your endpoint. Events: source.crawl.completed, source.crawl.failed, source.revoked, version.indexed, version.failed. Signed HMAC-SHA256 of {timestamp}.{body}.
Auth HMAC-SHA256 (shared secret)
Widget integration
Two lines of HTML.
The widget is a vanilla Web Component, ~22KB gzip, served from Cloudflare's edge. Drop it on any page; theme it via the eight CSS custom properties documented on /product/widget.
<script src="https://widget.flowchat.com/v1.js" defer></script>
<flowchat-widget
data-key="kbk_live_xxxxxxxx"
data-source="docs"
data-locale="en"
></flowchat-widget> SSE event contract
The chat stream emits structured events.
Every retrieval, generation, citation, and verification step is a named event on the SSE stream. The live demo on the homepage subscribes to the same stream and animates the Source Trail panel from it.
event: retrieval.started
data: {"query":"How do you handle hallucinations?"}
event: retrieval.reranked
data: {"chunks":[{"id":"chk_grnd1","url":"/product/ground","score":0.94}, ...]}
event: generation.token
data: {"text":"Three"}
event: generation.cited
data: {"ref":1,"chunkId":"chk_grnd1"}
event: nli.verified
data: {"ref":1,"ok":true}
event: stream.done
data: {"refusal":false} Webhook signatures
HMAC-SHA256, timestamp-prefixed.
Verify webhook authenticity by computing
HMAC-SHA256(secret, timestamp + "." + body) and comparing
it to the X-FlowChat-Signature header in constant time.
Reject events older than 5 minutes to prevent replay.
// Node example
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(body, headers, secret) {
const ts = headers["x-flowchat-timestamp"];
const sig = headers["x-flowchat-signature"];
const expected = createHmac("sha256", secret)
.update(`${ts}.${body}`)
.digest("hex");
return timingSafeEqual(
Buffer.from(sig, "hex"),
Buffer.from(expected, "hex"),
) && Date.now() - Number(ts) * 1000 < 5 * 60 * 1000;
} Build something.
Trial keys are issued at sign-up. The first crawl is free; everything after is metered against your plan.