A knowledge base has its own embedding and chunking
configuration — the unit that retrieval searches over. A document is one uploaded
file; ingest splits it into chunks, each carrying a vector embedding. The vocabulary
on this page matches the glossary.
Before you start
Every endpoint on this page lives under the/knowledge-bases router and is org-scoped
and admin-gated. You need:
- A ModuleX API key (
mx_live_…). Get one from the app or see Authentication. - The owner or admin role in the organization. Every knowledge route depends on
organization_admin_required, so a non-admin caller is rejected with403. The legacymemberrole is retired — see Roles & permissions. - The base URL
https://api.modulex.dev. There is no/v1path segment — paths are exactly/knowledge-bases/....
X-API-KEY as an
alternative to the bearer token):
Step 1 — choose managed or BYOK
The single decision that drives cost is whether the knowledge base is managed or BYOK (bring your own key). It is set byembedding_config.integration_name:
Managed (modulexdb)
Set
integration_name to modulexai. ModuleX provisions the embedding provider and
stores vectors in its managed store. Ingest and retrieval are billed in credits.
See modulexdb (managed).BYOK
Point
embedding_config at one of your own LLM-provider credentials (for example your
own OpenAI or Cohere key). Ingest and retrieval are uncosted by ModuleX — you pay
the provider directly. See Knowledge providers.Only managed knowledge bases (those whose
embedding_config.integration_name is
modulexai) are metered. BYOK retrieval and ingest consume no ModuleX credits — they
are analytics-only. The credit columns throughout this page apply to managed knowledge
bases only.embedding_config.credential_id entirely, ModuleX auto-discovers an
org credential that exposes an embedding-capable model (it looks for an llm_provider
credential whose integration has a model flagged is_embedding). If none exists, create
fails — see the errors below.
Embedding-config key drift. Two key conventions coexist in the backend and both are
read defensively. The model-level default uses
provider + model_id; the service
default uses integration_name + provider_id + model_id + credential_id. When you
write embedding_config, the embed code accepts either provider or provider_id,
either model or model_id, and either provider_credential_id or credential_id.
Pick one convention and stay consistent. Managed is detected specifically on
integration_name == "modulexai".Step 2 — create the knowledge base
POST /knowledge-bases creates the base and returns 201 Created. There is no credit
gate on create. On success ModuleX also auto-creates a linked internal credential (the
“native KB = credential” link) so a knowledge node
can reference the base, and sets status to active.
Request fields
string
required
Display name, 1–255 characters.
string
Optional free-text description.
object
Per-knowledge-base embedding settings. Omit it to auto-discover an embedding credential
and use the defaults below.
object
Per-knowledge-base chunking settings used by the ingest pipeline.
Create a knowledge base
The JS SDK takes camelCase method arguments but returns snake_case fields (so the response
id/created_at stay snake_case); the Python SDK is snake_case both ways. Nested config
keys like integration_name and model_id are already snake_case on both sides.Response (201 Created)
string
The knowledge-base UUID.
string
Owning organization.
string
Creator user id.
string
The auto-created internal credential that links this base to workflow nodes.
string
The display name.
string
The description, or
null.object
The resolved embedding settings.
object
The resolved chunking settings.
string
One of
active, processing, error, archived. New bases are active.integer
Document count (rolled up).
integer
Chunk count across documents.
integer
Token count across documents.
string
Creation timestamp.
string
Last-update timestamp.
Example response
Create errors
The knowledge-base count quota is a plan entitlement (
max_knowledge_bases):
unlimited for admin and Enterprise, Max 50, Pro 3, Free uses the config default. Quota
counts non-archived bases — archiving a base frees a slot. Quota and storage denials
use the plain 403 {"detail": ...} shape, not the billing
DenialEnvelope.Step 3 — ingest documents
Upload a file withPOST /knowledge-bases/{knowledge_base_id}/documents as
multipart/form-data. The upload returns 201 with the document in pending status; a
background worker then runs the parse-chunk-embed pipeline asynchronously. You poll the
document status until it reaches completed or failed.
Form parts
file
required
The document to ingest. Supported types:
pdf, docx, doc, txt, md, html,
csv, json, xlsx, pptx. The type is resolved from the extension first, then the
MIME type.string
Optional JSON string of arbitrary metadata. Invalid JSON returns
400 with
{"detail": "Invalid metadata JSON"}.Deduplication. ModuleX computes a content hash of the file. Uploading the same content to
the same base again returns
400 (Duplicate file...). To re-ingest changed content,
delete the existing document first.Upload a document
Upload response (201 Created)
The upload endpoint returns the router DocumentResponse shape:
string
Document UUID.
string
Parent base.
string
Original filename.
string
Resolved type (for example
pdf).integer
File size in bytes.
string
Lifecycle status;
pending immediately after upload.integer
Chunks produced;
0 until ingest completes.integer
Tokens counted;
0 until ingest completes.string
Failure reason, or
null.string
Upload timestamp.
Example response
What the worker does
The backgroundingest_document task (retried up to 3 times) drives the document from
pending to a terminal state:
1
Parse
Decodes text formats; uses
pypdf for PDF, python-docx for Word, and the
unstructured library for HTML and unknown types.2
Chunk
Splits text per
chunking_config, recording token_count, start_char, and
end_char for each chunk.3
Embed
Generates embeddings with OpenAI or Cohere. A managed base routes through the same
underlying model used at query time, so ingest-time and search-time vectors match.
4
Persist
Writes chunk rows with their vectors, sets the document
completed, and updates
chunk_count and token_count. On any exception the document is set failed with an
error_message and the task retries.pending → processing → completed | failed, and a
failed document can be returned to pending with retry.
Poll document status
GET /knowledge-bases/{kb_id}/documents/{document_id}/status returns a status dict whose
extra fields vary by state. Poll it until status is completed or failed.
Example response (completed)
Status-by-status fields
Status-by-status fields
pending—message: "Waiting to be processed".processing— addsprocessing_started_at.completed— addsprocessing_completed_at,chunk_count,token_count.failed— addserrorwith the failure reason.
Retry a failed document
POST /knowledge-bases/{kb_id}/documents/{document_id}/retry re-enqueues ingest. It is
valid only when the document status is failed (otherwise 400); it resets the
document to pending and clears the error and timestamps. There is no credit gate on
retry — the per-chunk embedding cost is keyed on {doc_id}:embedding:{token_count}, so an
unchanged reprocess does not re-charge.
Other document operations
Ingest errors
Step 4 — query the knowledge base
ModuleX offers four retrieval modes. All reserve 1 retrieval credit on a managed base (see Costs) and accept the same auth headers. Pick the mode that fits:Vector search
POST /knowledge-bases/{kb_id}/search — semantic (cosine) similarity over one base.Multi-base search
POST /knowledge-bases/search — the same query across several bases, merged by score.Hybrid search
POST /knowledge-bases/{kb_id}/hybrid-search — vector plus keyword full-text ranking.Retrieve context
POST /knowledge-bases/{kb_id}/retrieve-context — a single token-budgeted RAG context string.Vector search
string
required
The search text (minimum length 1).
integer
default:"5"
Number of results, 1–50.
number
default:"0.0"
Cosine-similarity floor, 0.0–1.0. Computed as
1 - distance.object
Optional filter; supports
document_id or document_ids to scope to specific documents.boolean
default:"true"
Return chunk text in each match.
boolean
default:"true"
Return chunk metadata in each match.
string
The query you sent.
string
The base searched.
integer
The requested result count.
integer
Number of matches returned.
array
Ranked matches, highest score first.
Example response
Multi-base search
POST /knowledge-bases/search runs the query across several bases and merges results by
score. It takes knowledge_base_ids (array of UUIDs, required), query (required),
top_k (1–50, default 5), and min_score (0.0–1.0, default 0.0). Bases your org cannot
access are silently skipped. The response is
{ "query", "knowledge_bases_searched", "top_k", "total_matches", "matches" }.
Billing reserves one retrieval credit if any queried base is managed (regardless
of ordering). One known in-code limitation: the per-base query-embedding token cost is
recorded for the last searched base only.
Hybrid search
POST /knowledge-bases/{kb_id}/hybrid-search blends semantic similarity with keyword
full-text ranking.
string
required
The search text.
integer
default:"5"
Number of results, 1–50.
number
default:"0.3"
Weight of the keyword score, 0.0–1.0.
number
default:"0.7"
Weight of the semantic score, 0.0–1.0.
number
default:"0.0"
Combined weighted-score floor, 0.0–1.0.
object
Optional document filter, as in vector search.
semantic_score and keyword_score alongside the combined score, and
the response echoes search_type: "hybrid" and the weights you used.
Retrieve context (for RAG)
POST /knowledge-bases/{kb_id}/retrieve-context returns a single ready-to-prompt string
instead of a match array — ideal for feeding an LLM.
string
required
The search text.
integer
default:"2000"
Token budget for the assembled context, 100–10000.
integer
default:"10"
Chunks to consider, 1–50.
number
default:"0.3"
Cosine-similarity floor, 0.0–1.0.
[Source: <filename>, Chunk <n>] header and joined by a separator. The
response is { "context": "<string>", "query": "<query>" }.
Query from a workflow or agent
Inside a workflow, a knowledge node retrieves from a base by its linked credential and returnschunks, context, or both (set by the
node’s output_format). The Assistant retrieves through its own search_knowledge tool.
Both reuse the same managed-billing path as the REST endpoints, so the credit costs below
apply identically.
Search errors
Step 5 — costs
Cost depends entirely on the managed-vs-BYOK choice from Step 1. For the full credit model, see Credits & metering; for how the gate denies calls, see Usage gating & limits.
A credit is the managed-usage unit: 100 credits = $1.00 (1 credit = $0.01). The
gate works reserve → record → release: it reserves the credit before doing the work
and records it on success, so an exhausted balance is rejected before any document is
written or any embedding is generated.
Manage and clean up
Supported file types — no auth.
GET /knowledge-bases/info/supported-file-types is the
one knowledge endpoint with no authentication. It returns the 10 supported types and the
fallback max_file_size_bytes (52428800) / max_file_size_mb (50.0). Remember that the
enforced per-file cap is your plan entitlement, not this advertised 50 MB.Next steps
Knowledge & RAG
The conceptual model: knowledge bases, managed vs BYOK, ingest and retrieval.
Knowledge overview
Manage knowledge bases, documents, and processing in the app.
Knowledge node
Retrieve from a base inside a workflow.
Credits & metering
Exactly what consumes credits, and the reserve-record-release lifecycle.