Product guide
The built-in API cards
The two key-authenticated API cards — one to push documents in, one to ask questions — set up from the console.
Ingestion API — push documents in
The Ingestion API lets your own application push documents into the knowledge base over HTTP, instead of a connector pulling them. It's a source like any other — what it ingests is chunked, embedded, access-controlled, analysed and retained exactly the same way. This article is the complete reference.
Setup
- Documents → Ingestion API: name it, and choose which groups may read what it ingests (that becomes each document's default access).
- Open the source and copy its endpoint and key from “API endpoint & key”. Rotate issues a new key and invalidates the old at once.
Authentication
Send the key in an Authorization: Bearer header on every request. The key belongs to this one source — it can ingest, never message. A missing or wrong key returns 401.
Endpoints
- POST /api/v1/ingest/documents — create or replace a document (external_id in the body)
- PUT /api/v1/ingest/documents/{external_id} — create or replace by id
- POST /api/v1/ingest/documents/batch — up to 100 at once ({"documents": [...]})
- GET /api/v1/ingest/documents — list with indexing status (query: limit, offset, prefix)
- GET /api/v1/ingest/documents/{external_id} — one document and its status
- DELETE /api/v1/ingest/documents/{external_id} — remove it (?purge=true erases immediately and permanently)
- POST /api/v1/ingest/sync — re-index now
- GET /api/v1/ingest/status — store and index counts
Document fields
| external_id | Your stable id for the document (1–512 chars: letters, digits, . _ : / -, starting alphanumeric). Send the same id again to update the document in place. |
|---|---|
| title | Optional display title. |
| text | Inline content — markdown, HTML or plain text. Provide exactly one of text or content_base64. |
| content_base64 | Base64-encoded bytes for binary formats (PDF, DOCX…). 50 MB per document, 100 MB per request. |
| filename / content_type | Optional hints for format detection; derived from external_id and content when omitted. |
| acl | Optional list of groups (e.g. ["grp:support"]). Named groups must already exist. Omit it to use the source's own groups. |
| metadata | Optional free-form JSON stored with the document. |
Example
curl -X POST <base>/api/v1/ingest/documents \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"external_id":"kb/refunds",
"title":"Refund policy",
"text":"# Refunds\nWe refund within 30 days.",
"acl":["grp:support"]}'
Behaviour worth knowing
- Writes return 202 with a queued indexing job — pushed documents become searchable within moments, and GET shows each document's indexing status.
- DELETE tombstones the document; ?purge=true is the GDPR path — content and index entries are erased at once.
- Rate limit: 300 requests per minute per key (429 when exceeded). Oversized requests return 413.
- Every push and delete is recorded in the audit log.
Machine-readable spec for Postman/codegen: /api/v1/openapi.json.
Messaging API — ask over HTTP
The Messaging API lets your own application ask the assistant over HTTP and get grounded, cited answers — the programmatic sibling of the website widget. Every answer is access-controlled and audited exactly like the web chat. This article is the complete reference.
Two kinds of key
- The channel's own key (shown on the card) answers as a guest, capped at the guest access groups you choose — with none chosen it stays silent. Use it for app-wide or anonymous access.
- A person's own key (Users → Edit → Chat channels → Generate key) answers with that user's own document access, exactly as if they asked in the web chat. Use it so each person sees only what they're allowed to.
Setup
- Chat channels → Messaging API: name it, and pick the guest access groups the shared key may answer from.
- For per-person access, open Users → Edit → Chat channels and Generate a key for each person; copy it from there.
- Send the key in an Authorization: Bearer header. A messaging key can never ingest.
Endpoints
- POST /api/v1/messages — ask a question; a cited answer or an abstention
- POST /api/v1/messages/stream — the same, streamed as Server-Sent Events (delta / reset / final events)
- GET /api/v1/conversations — list the caller's conversations
- GET /api/v1/conversations/{id} — a conversation's messages and citations
- DELETE /api/v1/conversations/{id} — erase a conversation
Message fields
| text | The question, in any language. |
|---|---|
| end_user | Optional caller id (1–128 chars). With the shared channel key it keeps each end user's conversation memory separate; with a personal key it is ignored — the key already is the person. |
| conversation_id | Pass the id from a previous answer to continue that conversation. |
The answer
Responses carry the answer text, abstained (true when the honest answer was “not in the knowledge base”), conversation_id, and citations — the numbered sources behind the text. Personal-key conversations are the same ones the person sees in the web chat.
Example
curl -X POST <base>/api/v1/messages \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"text":"What is the refund window?",
"end_user":"u-4471"}'
Behaviour worth knowing
- Rate limit: 60 messages per minute per channel and end user (429 when exceeded).
- A guest key with no guest groups configured answers with the abstention — deliberately.
- Every question is audited with its retrieved and cited passages, like every other surface.
Machine-readable spec for Postman/codegen: /api/v1/openapi.json.