API Reference

Knowledge Base API

Programmatic access to your knowledge bases. Query endpoints return answers with clickable citations, streamed via Server-Sent Events or as a single JSON response. Bearer-token auth; one token per wiki.

Keys

Authentication

The API uses Bearer-token auth. Tokens are wiki-scoped — one token grants access to exactly one wiki, and you can mint as many tokens per wiki as you need.

To create a token, sign in, navigate to /w/<slug>/settings, and use the API keys panel. Tokens look like ke_<wiki-slug>_<32 hex> — the slug prefix is for debuggability; the request path is the actual source of truth for which wiki you're hitting.

Authentication headerhttp
Authorization: Bearer ke_ai-regulation_77a380f949077759d4205212fe84e9e4
Tokens are stored server-side as SHA-256 hashes — we can't show you a token after it's created. If you lose one, rotate via the same UI.
POST /api/v1/wikis/{slug}/query

Query — synchronous JSON

Blocks until the full answer + citations are ready, then returns a single JSON response. Use this for server-to-server integrations or automations where you don't need streaming.

Request

httphttp
POST https://knowledge-base.automatons.com.au/api/v1/wikis/{slug}/query
Authorization: Bearer ke_...
Content-Type: application/json

{
  "question": "When did the EU AI Act enter into force?"
}

Response — 200

jsonjson
{
  "answer": "The EU AI Act entered into force on August 1, 2024...",
  "citations": [
    {
      "slug": "eu-ai-act-regulation-2024-1689",
      "title": "EU AI Act (Regulation (EU) 2024/1689)",
      "type": "source",
      "url": "/w/ai-regulation/page/eu-ai-act-regulation-2024-1689"
    }
  ],
  "usage": {
    "retrievedPages": 8,
    "inputTokens": null,
    "outputTokens": null
  }
}
usage.inputTokens and usage.outputTokens are reserved for future use — currently null. Token counts will land alongside per-query cost reporting in a later release.
POST /api/v1/wikis/{slug}/query/stream

Query — Server-Sent Events

Returns Server-Sent Events so the client can render progressively. Citations arrive first (before the first token) so your source chips can render while the answer is still being generated.

Wire format

Three event types, terminated by the done event:

ssesse
event: citations
data: [{"slug": "eu-ai-act-regulation-2024-1689", "title": "EU AI Act", "type": "source", "url": "/w/ai-regulation/page/eu-ai-act-regulation-2024-1689"}]

event: token
data: {"content": "The"}

event: token
data: {"content": " EU AI Act entered"}

event: token
data: {"content": " into force on August 1, 2024..."}

event: done
data: {"usage": {"retrievedPages": 8, "inputTokens": null, "outputTokens": null}}
Every SSE frame terminates with a blank line (\n\n). Frames without the terminator won't be parsed by browser EventSource. If you're writing a custom parser, handle the trailing newline explicitly.

On error, a fourth event is emitted mid-stream before the connection closes:

ssesse
event: error
data: {"error": "Query failed: ..."}
Quick starts

Code examples

Minimum-viable snippets for three languages. For larger integrations grab the SDK at packages/sdk/ on GitHub.

curl

bashbash
curl -sN -X POST \
  'https://knowledge-base.automatons.com.au/api/v1/wikis/ai-regulation/query/stream' \
  -H 'Authorization: Bearer ke_ai-regulation_...' \
  -H 'Content-Type: application/json' \
  -H 'Accept: text/event-stream' \
  -d '{"question":"When did the EU AI Act enter into force?"}'

TypeScript (fetch + streaming)

typescripttypescript
const res = await fetch(
  "https://knowledge-base.automatons.com.au/api/v1/wikis/ai-regulation/query/stream",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.KB_API_KEY}`,
      "Content-Type": "application/json",
      Accept: "text/event-stream",
    },
    body: JSON.stringify({ question: "..." }),
  },
);

const reader = res.body!.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  // Frames end with \n\n — parse as you go.
  const frames = buffer.split("\n\n");
  buffer = frames.pop() ?? "";
  for (const frame of frames) handleFrame(frame);
}

Python (requests, non-streaming)

pythonpython
import os, requests

r = requests.post(
    "https://knowledge-base.automatons.com.au/api/v1/wikis/ai-regulation/query",
    headers={
        "Authorization": f"Bearer {os.environ['KB_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={"question": "When did the EU AI Act enter into force?"},
    timeout=60,
)
r.raise_for_status()
data = r.json()

print(data["answer"])
for c in data["citations"]:
    print(f"  → {c['title']} ({c['slug']})")
Reference

Error codes

Non-2xx responses carry an error field with a human-readable message. The HTTP status indicates the class:

StatusMeaningAction
400Malformed request body or missing questionFix the payload
401Missing or invalid Bearer tokenRotate via wiki settings
403Token doesn't grant access to this wikiCheck the slug in the path matches the token's wiki
404Wiki slug not foundVerify the wiki exists and is visible to the token
429Rate limit exceeded (anonymous quota, not applicable to API-key callers)Slow down; API-key clients should not see this
500Retrieval or generation errorRetry with backoff; contact support if persistent
Fair use

Rate limits

No hard per-key rate limit today — the product is in early access and limits are on the honor system. Expect the following once Pro / Teams billing lands:

  • Free tier: ~60 queries / hour per wiki, soft-enforced.
  • Pro tier: ~600 queries / hour, burstable.
  • Teams tier: custom — contact us for the profile that fits your traffic.

If you're planning to embed the widget on a high-traffic site, reach out before launching so we can provision accordingly.

Integration

Next steps