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.

POST 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

GET / POST 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)

GET 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

Outbound POST

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.