Knowledge Base & Embeddings
This content is not available in your language yet.
A Knowledge Base is a named container of chunked, embedded text that a workflow’s LLM node can retrieve against at runtime (RAG). This page is the exhaustive field-by-field reference for all fourteen knowledge-base and embedding operations. For a conceptual walkthrough of how retrieval fits into a workflow, see Knowledge Base; for using the raw embedding endpoint outside the platform’s own retrieval path, see Embeddings.
All operations on this page except embed require a valid JWT (Authorization: Bearer <token>) issued to a user belonging to the tenant that owns the knowledge base — see Authentication. embed uses a separate X-Api-Key header instead (see below). Every knowledge base, document, and chunk is scoped to the caller’s tenant.
Every request in this reference must include the x-huat-platform: customer header in addition to standard GraphQL headers.
The KnowledgeBaseDto type
Section titled “The KnowledgeBaseDto type”| Field | Type | Notes |
|---|---|---|
id | Int! | |
name | String! | |
description | String | |
createdAt | DateTime! | |
updatedAt | DateTime! |
The KnowledgeDocumentDto type
Section titled “The KnowledgeDocumentDto type”| Field | Type | Notes |
|---|---|---|
id | Int! | |
fileName | String! | |
mimeType | String! | |
fileSizeBytes | Int! | |
parseStatus | String! | PENDING | PARSING | READY | FAILED. See the parse lifecycle below. |
parseError | String | Set only when parseStatus is FAILED. |
rawText | String! | The document’s full extracted/stored text. Only ever populated by the singular knowledgeDocument(id) query below — knowledgeDocuments (the list query) never selects it, so listing a knowledge base with many/large documents doesn’t pay for fetching all of their text. Empty while parseStatus is PENDING/PARSING. |
createdAt | DateTime! | |
updatedAt | DateTime! |
The KnowledgeChunkPreviewDto type
Section titled “The KnowledgeChunkPreviewDto type”Returned only by retrieveChunks — a preview of a single retrieved chunk, not a persisted, independently-queryable resource.
| Field | Type | Notes |
|---|---|---|
chunkId | Int! | |
documentId | Int! | The source document this chunk came from. |
content | String! | The chunk’s raw text. |
score | Float! | Cosine similarity to the query, higher is more relevant. |
The parseStatus lifecycle
Section titled “The parseStatus lifecycle”A document’s parseStatus moves through up to four states, depending on how it was created:
- Inline text (via
ingestDocument) — chunked, embedded, and persisted synchronously.parseStatusisREADYimmediately; there is nothing to poll. - Uploaded file (via
requestKnowledgeDocumentUpload+confirmKnowledgeDocumentUpload) — parses asynchronously:PENDING(row created, job enqueued) →PARSING(job running) →READY(chunks embedded and available toretrieveChunks), orFAILEDwithparseErrorpopulated if parsing errors out.
There is no subscription for parse completion — poll knowledgeDocuments(knowledgeBaseId) and check the parseStatus field on the document you just uploaded, or simply refetch after a few seconds.
Queries
Section titled “Queries”knowledgeBases
Section titled “knowledgeBases”All knowledge bases owned by the current tenant.
Auth: JWT
knowledgeBases: [KnowledgeBaseDto!]!Request
query ListKnowledgeBases { knowledgeBases { id name description }}POST /graphqlContent-Type: application/jsonAuthorization: Bearer <jwt>x-huat-platform: customerResponse
{ "data": { "knowledgeBases": [ { "id": 5, "name": "Product Docs", "description": "Internal product documentation" }, { "id": 6, "name": "Support FAQ", "description": null } ] }}knowledgeDocuments
Section titled “knowledgeDocuments”All documents in a knowledge base owned by this tenant, most recent first. Includes parseStatus — poll or refetch this after confirmKnowledgeDocumentUpload to see PENDING → PARSING → READY (or FAILED, with parseError set) for an uploaded file. Inline-text documents (via ingestDocument) are READY immediately.
Auth: JWT
knowledgeDocuments(knowledgeBaseId: Int!): [KnowledgeDocumentDto!]!Request
query ListKnowledgeDocuments($knowledgeBaseId: Int!) { knowledgeDocuments(knowledgeBaseId: $knowledgeBaseId) { id fileName mimeType fileSizeBytes parseStatus parseError }}{ "knowledgeBaseId": 5 }Response
{ "data": { "knowledgeDocuments": [ { "id": 101, "fileName": "product-manual.pdf", "mimeType": "application/pdf", "fileSizeBytes": 843201, "parseStatus": "READY", "parseError": null }, { "id": 102, "fileName": "release-notes.pdf", "mimeType": "application/pdf", "fileSizeBytes": 120044, "parseStatus": "PARSING", "parseError": null } ] }}knowledgeDocument
Section titled “knowledgeDocument”A single document owned by this tenant, including its full rawText — unlike knowledgeDocuments above, which never selects this field. Use this to fetch a document’s content for preview or editing (see updateKnowledgeDocumentText below).
Auth: JWT
knowledgeDocument(id: Int!): KnowledgeDocumentDto!Request
query GetKnowledgeDocument($id: Int!) { knowledgeDocument(id: $id) { id fileName rawText parseStatus }}{ "id": 101 }Response
{ "data": { "knowledgeDocument": { "id": 101, "fileName": "product-manual.pdf", "rawText": "Chapter 1: Getting Started\n\nTo reset your password, go to Settings > Security...", "parseStatus": "READY" } }}retrieveChunks
Section titled “retrieveChunks”Diagnostic/test query: embeds query and returns the topK (max 20) most semantically similar chunks from a knowledge base owned by this tenant, ordered by cosine similarity (most relevant first). This is the same retrieval path an LLM workflow node with knowledgeBaseId set uses internally — use this query to sanity-check what a workflow node would actually retrieve for a given user query, before wiring it into a live workflow.
Auth: JWT
retrieveChunks(knowledgeBaseId: Int!, query: String!, topK: Int): [KnowledgeChunkPreviewDto!]!Arguments
| Argument | Type | Required | Notes |
|---|---|---|---|
knowledgeBaseId | Int! | yes | |
query | String! | yes | The text to embed and search against. |
topK | Int | no | Max 20. Defaults to a small number if omitted — pass it explicitly if you need a specific count. |
Request
query RetrieveChunks($knowledgeBaseId: Int!, $query: String!, $topK: Int) { retrieveChunks( knowledgeBaseId: $knowledgeBaseId query: $query topK: $topK ) { chunkId documentId content score }}{ "knowledgeBaseId": 5, "query": "How do I reset my password?", "topK": 3}Response
{ "data": { "retrieveChunks": [ { "chunkId": 5501, "documentId": 101, "content": "To reset your password, go to Settings > Security and click 'Reset Password'...", "score": 0.87 }, { "chunkId": 5502, "documentId": 101, "content": "Password reset links expire after 24 hours...", "score": 0.79 } ] }}For the conceptual version of how retrieval feeds a workflow’s LLM node, see Knowledge Base.
API-key-tier: embeds each string in texts (same order in, same order out) using the same model/dimensions as this tenant’s knowledge base (gemini-embedding-001, 768 dims) — a drop-in source for a caller building their own vector index outside Wetel. Max 100 texts per call. usage.costUsd reflects the embedding model’s public paid-tier rate; inputTokens is a character-length estimate, not an exact tokenizer count, so costUsd is an estimate too.
Auth: API key (X-Api-Key header) — not a JWT. See Embeddings for how to generate a key.
embed(texts: [String!]!): EmbedResultDto!EmbedResultDto fields
| Field | Type | Notes |
|---|---|---|
vectors | [[Float!]!]! | One embedding vector per input text, same order as texts. Always fully populated — never contains null entries. |
usage | EmbedUsageDto! | { inputTokens, outputTokens, costUsd }. |
Request
query Embed($texts: [String!]!) { embed(texts: $texts) { vectors usage { inputTokens outputTokens costUsd } }}{ "texts": ["hello world", "a second string to embed"] }POST /graphqlContent-Type: application/jsonX-Api-Key: <api-key>x-huat-platform: customerResponse
{ "data": { "embed": { "vectors": [ [0.0123, -0.0456, 0.0789], [-0.0034, 0.0912, 0.0201] ], "usage": { "inputTokens": 6, "outputTokens": 0, "costUsd": 0.0000012 } } }}Note: the response above truncates each vector to 3 dimensions for readability — real vectors are 768-dimensional.
Mutations
Section titled “Mutations”createKnowledgeBase
Section titled “createKnowledgeBase”Creates a new named knowledge base container for this tenant. Subject to the plan’s max-knowledge-base quota.
Auth: JWT
createKnowledgeBase(input: CreateKnowledgeBaseInput!): KnowledgeBaseDto!CreateKnowledgeBaseInput fields
| Field | Type | Required |
|---|---|---|
name | String! | yes |
description | String | no |
Request
mutation CreateKnowledgeBase($input: CreateKnowledgeBaseInput!) { createKnowledgeBase(input: $input) { id name description }}{ "input": { "name": "Product Docs", "description": "Internal product documentation" }}POST /graphqlContent-Type: application/jsonAuthorization: Bearer <jwt>x-huat-platform: customerResponse
{ "data": { "createKnowledgeBase": { "id": 5, "name": "Product Docs", "description": "Internal product documentation" } }}deleteKnowledgeBase
Section titled “deleteKnowledgeBase”Soft-deletes a knowledge base for this tenant. Does not cascade-delete its documents or chunks — this is documented, intentional behavior, not an oversight. After deleting a knowledge base, its documents and their chunks remain in storage and are simply no longer reachable through a live knowledge base row; plan for this if you need to reclaim storage or comply with a deletion request (delete documents individually beforehand, or handle cleanup out of band).
Auth: JWT
deleteKnowledgeBase(id: Int!): Boolean!Request
mutation DeleteKnowledgeBase($id: Int!) { deleteKnowledgeBase(id: $id)}{ "id": 6 }Response
{ "data": { "deleteKnowledgeBase": true } }ingestDocument
Section titled “ingestDocument”Ingests inline pasted text into a knowledge base — chunks, embeds, and persists it synchronously, subject to plan quotas (chunk count and storage MB). Text only, max 500KB. For a real PDF/DOCX file, use requestKnowledgeDocumentUpload + confirmKnowledgeDocumentUpload instead — that path parses asynchronously. Returns the number of chunks created.
Auth: JWT
ingestDocument(input: IngestDocumentInput!): Int!IngestDocumentInput fields
| Field | Type | Required | Notes |
|---|---|---|---|
knowledgeBaseId | Int! | yes | |
fileName | String! | yes | A display label — no real file is uploaded for this path. |
text | String! | yes | Max 500KB. |
Request
mutation IngestDocument($input: IngestDocumentInput!) { ingestDocument(input: $input)}{ "input": { "knowledgeBaseId": 5, "fileName": "faq-snippet.txt", "text": "Q: How do I reset my password?\nA: Go to Settings > Security and click 'Reset Password'." }}Response
{ "data": { "ingestDocument": 2 } }requestKnowledgeDocumentUpload
Section titled “requestKnowledgeDocumentUpload”Step 1 of file upload. Validates the knowledge base’s ownership and a soft (non-authoritative) quota pre-check, then returns a presigned PUT URL (15 minute expiry) plus the objectStorageKey to use when confirming. PDF, DOCX, Markdown, CSV, or XLSX, max 20MB (Markdown/CSV/XLSX added 2026-09-17). Rate-limited (10/min per client).
The browser (or your server) then PUTs the raw file bytes directly to uploadUrl — they never pass through the Wetel API server.
Auth: JWT
requestKnowledgeDocumentUpload(input: RequestKnowledgeDocumentUploadInput!): RequestKnowledgeDocumentUploadResult!RequestKnowledgeDocumentUploadInput fields
| Field | Type | Required | Notes |
|---|---|---|---|
knowledgeBaseId | Int! | yes | |
fileName | String! | yes | |
mimeType | String! | yes | One of: application/pdf, DOCX’s application/vnd.openxmlformats-officedocument.wordprocessingml.document, text/markdown, text/csv, or XLSX’s application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (last three added 2026-09-17). |
declaredSizeBytes | Int! | yes | Max 20MB. The real uploaded size is verified server-side in step 2 — this value is only used for the soft pre-check. |
RequestKnowledgeDocumentUploadResult fields
| Field | Type | Notes |
|---|---|---|
uploadUrl | String! | Presigned PUT URL, expires in 15 minutes. |
objectStorageKey | String! | Pass this back unchanged to confirmKnowledgeDocumentUpload. |
Request
mutation RequestUpload($input: RequestKnowledgeDocumentUploadInput!) { requestKnowledgeDocumentUpload(input: $input) { uploadUrl objectStorageKey }}{ "input": { "knowledgeBaseId": 5, "fileName": "product-manual.pdf", "mimeType": "application/pdf", "declaredSizeBytes": 843201 }}Response
{ "data": { "requestKnowledgeDocumentUpload": { "uploadUrl": "https://storage.example.com/knowledge-uploads/tenant-9/abc123?X-Signature=...", "objectStorageKey": "knowledge-uploads/tenant-9/abc123" } }}Step 1.5 — the browser upload itself (not a Wetel API call):
PUT https://storage.example.com/knowledge-uploads/tenant-9/abc123?X-Signature=...Content-Type: application/pdf
<raw file bytes>confirmKnowledgeDocumentUpload
Section titled “confirmKnowledgeDocumentUpload”Step 2 of file upload. Call this after the browser finishes PUTting the file to the URL from requestKnowledgeDocumentUpload. Verifies the upload actually completed, reserves storage quota against the real file size, creates the document row (parseStatus: PENDING), and enqueues async parsing. Poll the knowledgeDocuments query afterward to see parseStatus transition to READY (or FAILED with a parseError).
Auth: JWT
confirmKnowledgeDocumentUpload(input: ConfirmKnowledgeDocumentUploadInput!): ConfirmKnowledgeDocumentUploadResult!ConfirmKnowledgeDocumentUploadInput fields
| Field | Type | Required | Notes |
|---|---|---|---|
knowledgeBaseId | Int! | yes | |
fileName | String! | yes | |
mimeType | String! | yes | |
objectStorageKey | String! | yes | The value returned by requestKnowledgeDocumentUpload. |
ConfirmKnowledgeDocumentUploadResult fields
| Field | Type | Notes |
|---|---|---|
documentId | Int! | |
parseStatus | String! | Always PENDING on this response — the row was just created. |
Request
mutation ConfirmUpload($input: ConfirmKnowledgeDocumentUploadInput!) { confirmKnowledgeDocumentUpload(input: $input) { documentId parseStatus }}{ "input": { "knowledgeBaseId": 5, "fileName": "product-manual.pdf", "mimeType": "application/pdf", "objectStorageKey": "knowledge-uploads/tenant-9/abc123" }}Response
{ "data": { "confirmKnowledgeDocumentUpload": { "documentId": 101, "parseStatus": "PENDING" } }}After this call, poll knowledgeDocuments(knowledgeBaseId: 5) and check parseStatus on document 101 until it reaches READY (or FAILED).
deleteKnowledgeDocument
Section titled “deleteKnowledgeDocument”Soft-deletes a single document — and, unlike deleteKnowledgeBase above, its chunks too — releasing the tenant’s chunk-count and storage quota reservation. Does not delete the knowledge base itself.
Auth: JWT
deleteKnowledgeDocument(id: Int!): Boolean!Request
mutation DeleteKnowledgeDocument($id: Int!) { deleteKnowledgeDocument(id: $id)}{ "id": 101 }Response
{ "data": { "deleteKnowledgeDocument": true } }resyncKnowledgeDocument
Section titled “resyncKnowledgeDocument”Re-runs ingestion for an existing document, using its current stored content — no new input required:
- A
FAILEDfile upload (one that still has its original uploaded bytes) is re-queued for a fresh extract+chunk+embed attempt —parseStatusgoes back toPENDING, same as a first upload. - A
READYdocument (of any origin) is re-chunked and re-embedded in place from its ownrawText— useful after a chunking/embedding change, without re-uploading or re-pasting anything. - Rejected with a validation error if the document is currently
PENDINGorPARSING.
Auth: JWT
resyncKnowledgeDocument(id: Int!): Boolean!Request
mutation ResyncKnowledgeDocument($id: Int!) { resyncKnowledgeDocument(id: $id)}{ "id": 102 }Response
{ "data": { "resyncKnowledgeDocument": true } }updateKnowledgeDocumentText
Section titled “updateKnowledgeDocumentText”Overwrites a document’s own text and re-chunks/re-embeds it in place, subject to plan quotas — the “edit” counterpart to resyncKnowledgeDocument above (which re-runs with the SAME text; this replaces it). Works for a document of any origin — file upload, pasted text, or URL ingest — once it’s been ingested at least once, since they all converge on the same rawText storage. A FAILED document can also be edited this way: fixing bad or missing content by hand is a valid recovery path distinct from resyncKnowledgeDocument’s “just retry the same bytes.” Rejected if the document is currently PENDING or PARSING.
Auth: JWT
updateKnowledgeDocumentText(id: Int!, text: String!): Boolean!Request
mutation UpdateKnowledgeDocumentText($id: Int!, $text: String!) { updateKnowledgeDocumentText(id: $id, text: $text)}{ "id": 101, "text": "Chapter 1: Getting Started\n\nTo reset your password, go to Settings > Security and click 'Reset Password'. Links expire after 24 hours."}Response
{ "data": { "updateKnowledgeDocumentText": true } }ingestDocumentFromUrl
Section titled “ingestDocumentFromUrl”Ingests a single web page into a knowledge base: fetches url, extracts its text (HTML pages are stripped to plain text; text/plain pages are used as-is), then chunks/embeds/persists it synchronously, subject to plan quotas — same return shape as ingestDocument. Single page only — does not follow links. Rate-limited (10/min per client) since it triggers a real outbound fetch. Blocked for any URL that resolves to a private/internal/reserved IP address range (loopback, RFC 1918 private ranges, link-local/cloud-metadata addresses, etc.) — this is a deliberate SSRF protection, not a bug, and there is no way to override it.
Auth: JWT
ingestDocumentFromUrl(input: IngestDocumentFromUrlInput!): Int!IngestDocumentFromUrlInput fields
| Field | Type | Required | Notes |
|---|---|---|---|
knowledgeBaseId | Int! | yes | |
url | String! | yes | Must be http:// or https://. |
fileName | String | no | Display label. Defaults to the fetched page’s own <title>, or its hostname if no title is found. |
Request
mutation IngestDocumentFromUrl($input: IngestDocumentFromUrlInput!) { ingestDocumentFromUrl(input: $input)}{ "input": { "knowledgeBaseId": 5, "url": "https://example.com/help/password-reset" }}Response
{ "data": { "ingestDocumentFromUrl": 3 } }See also
Section titled “See also”- Knowledge Base — conceptual guide to RAG retrieval in workflows
- Embeddings — using
embedto build your own vector index - Evaluation & Export
- Avatar Config
- API Reference: Overview