> ## Documentation Index
> Fetch the complete documentation index at: https://docs.modulex.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# modulexdb — the ModuleX-managed vector store

> modulexdb is the ModuleX-managed vector store: a fully hosted vector store with managed embeddings, used as the knowledge provider for a knowledge base or a workflow knowledge node. Reference for the provider config (every field, type, and default), the credit cost of ingest and retrieval, and the billing gate that returns 402/403/429.

export const MediaEmbed = ({id, type = 'screenshot', caption = '', ext, ratio = '16 / 9'}) => {
  const isVideo = type === 'video' || type === 'app_video';
  const resolvedExt = ext || (isVideo ? 'mp4' : type === 'screenshot' ? 'webp' : 'svg');
  const src = 'https://media.modulex.dev/' + id + '.' + resolvedExt;
  const [status, setStatus] = useState('loading');
  const [isDev, setIsDev] = useState(false);
  const [inView, setInView] = useState(false);
  const boxRef = useRef(null);
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const h = window.location.hostname;
    setIsDev(h === 'localhost' || h === '127.0.0.1' || h.endsWith('.mintlify.app'));
  }, []);
  useEffect(() => {
    if (inView) return;
    if (typeof IntersectionObserver === 'undefined') {
      setInView(true);
      return;
    }
    const el = boxRef.current;
    if (!el) return;
    const io = new IntersectionObserver(entries => {
      if (entries.some(e => e.isIntersecting)) {
        setInView(true);
        io.disconnect();
      }
    }, {
      rootMargin: '300px'
    });
    io.observe(el);
    return () => io.disconnect();
  }, [inView]);
  if (status === 'missing') {
    if (!isDev) return null;
    return <div style={{
      display: 'flex',
      flexDirection: 'column',
      justifyContent: 'center',
      gap: '0.4rem',
      padding: '1rem 1.25rem',
      margin: '1.25rem 0',
      width: '100%',
      aspectRatio: ratio,
      boxSizing: 'border-box',
      border: '1px dashed rgba(128,128,128,0.45)',
      borderRadius: '0.75rem',
      background: 'rgba(128,128,128,0.06)',
      color: 'currentColor',
      fontSize: '0.85rem',
      lineHeight: 1.45
    }}>
        <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: '0.5rem',
      opacity: 0.75
    }}>
          <span aria-hidden="true">🎬</span>
          <code style={{
      fontSize: '0.75rem'
    }}>{id}</code>
          <span style={{
      fontSize: '0.65rem',
      textTransform: 'uppercase',
      letterSpacing: '0.04em',
      padding: '0.1rem 0.4rem',
      borderRadius: '0.4rem',
      background: 'rgba(128,128,128,0.18)'
    }}>
            {type}
          </span>
        </div>
        <div style={{
      opacity: 0.9
    }}>{caption || 'Media not uploaded yet.'}</div>
        <div style={{
      fontSize: '0.7rem',
      opacity: 0.5
    }}>
          Upload to R2 as <code>{id}.{resolvedExt}</code> — preview only, hidden in production.
        </div>
      </div>;
  }
  const mediaStyle = {
    display: status === 'loaded' ? 'block' : 'none',
    width: '100%',
    height: 'auto',
    borderRadius: '0.75rem'
  };
  const media = isVideo ? <video src={inView ? src : undefined} autoPlay loop muted playsInline preload="metadata" onLoadedData={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} /> : <img src={inView ? src : undefined} alt={caption} onLoad={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} />;
  return <figure style={{
    margin: '1.25rem 0'
  }}>
      <div ref={boxRef} style={status === 'loaded' ? {
    width: '100%'
  } : {
    width: '100%',
    aspectRatio: ratio,
    borderRadius: '0.75rem',
    background: 'rgba(128,128,128,0.06)'
  }}>
        {media}
      </div>
      {status === 'loaded' && caption ? <figcaption style={{
    marginTop: '0.5rem',
    textAlign: 'center',
    fontSize: '0.85rem',
    opacity: 0.7
  }}>
          {caption}
        </figcaption> : null}
    </figure>;
};

`modulexdb` is the **ModuleX-managed vector store** — the built-in knowledge provider you
select when you want ModuleX to host the vectors and run the embeddings for you, with no
external vector database to provision. It is one of the [knowledge
providers](/integrations/knowledge-providers/overview) ModuleX can retrieve from; the others
([Qdrant](/integrations/knowledge-providers/qdrant),
[Pinecone](/integrations/knowledge-providers/pinecone),
[MongoDB Atlas](/integrations/knowledge-providers/mongodb-atlas), and
[Weaviate](/integrations/knowledge-providers/weaviate)) are bring-your-own-key (BYOK) stores
that you connect with your own credentials.

Choosing `modulexdb` is the difference between **managed** and **BYOK** retrieval. When a
[knowledge base](/platform/knowledge/overview) embeds on the managed pool, ModuleX
provisions the embedding model, stores the vectors in the managed vector store, serves retrieval, and
**meters that work in [credits](/billing/credits)**. BYOK providers are **never credited**
— that usage is billed by your upstream vector store and embedding provider.

<Note>
  This page is the **provider-catalog entry** for `modulexdb`: how to select it as a provider
  for a knowledge base and for a [workflow knowledge node](/workflow-builder/nodes/knowledge),
  what it costs, and how the billing gate behaves. The exhaustive reference for the managed
  store itself — the full embedding and chunking schema, the ingest and retrieval pipelines,
  document and chunk records, and the per-operation REST surface — is
  [Managed knowledge (modulexdb)](/platform/knowledge/managed). Read that page for the deep
  mechanics; this page tells you how to wire `modulexdb` in.
</Note>

## When to choose modulexdb

<CardGroup cols={2}>
  <Card title="Managed — modulexdb" icon="database">
    ModuleX hosts the vectors in the managed vector store and provisions the embedding model. No external
    store to run. Ingest and retrieval are billed in credits. Best when you want RAG to work
    out of the box.
  </Card>

  <Card title="BYOK — Qdrant, Pinecone, Atlas, Weaviate" icon="key">
    You bring the vector store and the embedding credential. ModuleX queries it on your
    behalf. Usage is not credited by ModuleX — your provider bills you directly. Best when
    you already run a vector database.
  </Card>
</CardGroup>

A knowledge base is **managed** when its `embedding_config.integration_name` is `modulexai`
(the managed integration name on the wire). The provider name `modulexdb` is how the same
managed store is referenced from a [knowledge node](/workflow-builder/nodes/knowledge) and
in the provider catalog. Both point at the same hosted managed vector store; everything on this
page about credit cost and the billing gate applies **only** to it.

<MediaEmbed id="MX-MEDIA-4120" type="image" caption={"Managed vs BYOK knowledge provider decision diagram for ModuleX."} />

## Selecting modulexdb for a knowledge base

You select the managed store at the knowledge-base level through `embedding_config`. Set
`integration_name` to `modulexai` and ModuleX treats the knowledge base as managed; on
create it also auto-creates a linked credential so [workflow knowledge
nodes](/workflow-builder/nodes/knowledge) can reference the knowledge base by
`credential_id`.

<ParamField path="embedding_config.integration_name" type="string" default="openai">
  The ModuleX integration that owns the embedding pool. Set to `modulexai` to make the
  knowledge base **managed** (`modulexdb`, billed in credits). Any other value — for example
  `openai` or `cohere` — is treated as BYOK and is not credited. This single field is what
  decides managed vs BYOK.
</ParamField>

<ParamField path="embedding_config.provider_id" type="string" default="openai">
  The actual embedding provider behind the managed pool. Validated against `openai`,
  `cohere`, `azure`, `huggingface`, but only `openai` and `cohere` have an embedding
  implementation; any other value raises `Unsupported embedding provider` at embed time.
  Also accepted under the key `provider`.
</ParamField>

<ParamField path="embedding_config.model_id" type="string" default="text-embedding-3-small">
  The embedding model. Also accepted under the key `model`. For managed knowledge bases the
  model resolves through the ModuleX model pool so that ingest-time and search-time vectors
  come from the same model.
</ParamField>

<ParamField path="embedding_config.dimension" type="integer" default="1536">
  The embedding vector dimension. Range `64`–`4096`. The embedding vector is sized for the
  default `1536` (the `text-embedding-3-small` dimension). Out-of-range values are rejected
  at create or update with a `KnowledgeBaseValidationError` → `400`.
</ParamField>

<ParamField path="embedding_config.credential_id" type="string" required={false}>
  The embedding credential. Also accepted as `provider_credential_id`. If omitted, ModuleX
  auto-discovers an org credential whose integration exposes an embedding-capable model. If
  none exists, create fails with `NoEmbeddingCredentialError` → `400`.
</ParamField>

<Warning>
  **Two accepted key spellings.** ModuleX reads `embedding_config` defensively: `provider` or
  `provider_id`, `model` or `model_id`, `provider_credential_id` or `credential_id`. The
  managed-vs-BYOK decision is made **only** on `integration_name == "modulexai"`, so a managed
  knowledge base must set `integration_name`.
</Warning>

A managed `embedding_config` looks like this:

```json theme={null}
{
  "integration_name": "modulexai",
  "provider_id": "openai",
  "model_id": "text-embedding-3-small",
  "dimension": 1536,
  "credential_id": "a1b2c3d4-0000-4000-8000-000000000001"
}
```

For the chunking schema, document and chunk records, storage backends, and the full
ingest and retrieval pipelines, see
[Managed knowledge (modulexdb)](/platform/knowledge/managed).

## Selecting modulexdb in a workflow knowledge node

A [knowledge node](/workflow-builder/nodes/knowledge) retrieves from a provider inside a
running workflow. To retrieve from the managed store, set the node's `provider_type` to
`modulexdb` and point `credential_id` at the managed knowledge base's linked credential.
`modulexdb` is the **default** `provider_type` for a knowledge node.

<ParamField path="credential_id" type="string" required>
  The credential ID for the knowledge base. For `modulexdb` this is the credential ModuleX
  auto-created when the managed knowledge base was created. ModuleX resolves the knowledge
  base from the credential's stored `knowledge_base_id`.
</ParamField>

<ParamField path="provider_type" type="string" default="modulexdb">
  The knowledge provider. One of `modulexdb`, `qdrant`, `pinecone`, `weaviate`,
  `mongodb_atlas`. Use `modulexdb` for the managed store. The external values require a
  BYOK credential and, for most of them, a `collection_name`.
</ParamField>

<ParamField path="top_k" type="integer" default="5">
  Number of results to retrieve. Range `1`–`20`.
</ParamField>

<ParamField path="min_score" type="number" default="0.3">
  Minimum cosine-similarity score threshold. Range `0.0`–`1.0`. Matches below this score are
  dropped.
</ParamField>

<ParamField path="max_tokens" type="integer" default="2000">
  Maximum tokens in the formatted context string, when the node returns a RAG context.
  Range `100`–`8000`.
</ParamField>

<ParamField path="collection_name" type="string" required={false}>
  Collection or index name. **Not used** for `modulexdb` (the managed store needs no
  collection). Required for external providers such as Qdrant and Pinecone.
</ParamField>

<ParamField path="namespace" type="string" required={false}>
  Namespace for Pinecone or similar providers. **Not used** for `modulexdb`.
</ParamField>

<ParamField path="embedding_config" type="object" required={false}>
  Embedding configuration for external providers that do not embed internally. **Not used**
  for `modulexdb`, which carries its own `embedding_config` on the knowledge base.
</ParamField>

A managed knowledge-node config:

```json theme={null}
{
  "credential_id": "939f74dc-7b2f-473c-b87d-b95c30c32fd3",
  "provider_type": "modulexdb",
  "top_k": 5,
  "min_score": 0.3
}
```

## Credit cost of managed knowledge

`modulexdb` is the only knowledge provider that consumes [credits](/billing/credits). A
credit is the managed-usage billing unit: \*\*100 credits = $1.00** (`1` credit = `$0.01\`).
Two operations are metered, each as a flat base credit plus the input-only embedding token
cost.

| Operation       | Flat base credit | Plus                                                                            | When it is charged                                                                                        |
| --------------- | :--------------: | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| **File ingest** | `1` per document | the document's embedding token cost (input-only), recorded by the ingest worker | Once per document, idempotent on the document ID. A retry of an unchanged document is **not** re-charged. |
| **Retrieval**   |   `1` per call   | the query-embedding token cost (input-only), recorded on success                | Once per `search`, `hybrid-search`, `retrieve-context`, or multi-knowledge-base search.                   |

<Note>
  A multi-knowledge-base search charges **one** retrieval base if **any** queried knowledge
  base is managed, regardless of order. Creating, listing, or updating a knowledge base is
  **not** credit-gated.
</Note>

The embedding token cost uses the standard token-metering formula with input tokens only
(embeddings have no completion tokens): `cost = prompt_tokens · in_rate / 1e6 · MARGIN ·
SCALE`, where `MARGIN` is `1.05` (a 5% system margin) and `SCALE` is `100`. BYOK
providers run the same searches but record **no** credit cost. For the full credit model,
see [Credits & metering](/billing/credits); for what each plan allows, see
[Plans & pricing](/billing/plans).

## The billing gate (402 / 403 / 429)

Managed ingest and managed retrieval pass through the ModuleX billing admission gate
**before** any embedding runs. The gate fails closed: when your plan allowance or wallet is
exhausted, a quota is exceeded, or a rate limit is hit, it returns a flat `DenialEnvelope`
and **no document or search result is produced**.

The `DenialEnvelope` is a flat object — there is no `detail` wrapper — of the shape
`{code, layer, key, current, limit, reason}`:

<ResponseField name="code" type="string">
  The machine-readable denial reason, for example `credit_plan_exhausted`, `quota_exceeded`,
  or `rate_limit_exceeded`.
</ResponseField>

<ResponseField name="layer" type="string">
  The gate layer that denied the call. Maps to the HTTP status: `credit` → `402`, `wallet` →
  `402`, `quota` → `403`, `rate` → `429`.
</ResponseField>

<ResponseField name="key" type="string | null">
  The denied resource key, for example the organization UUID or the rate class. May be
  `null`.
</ResponseField>

<ResponseField name="current" type="number | null">
  The current usage at the time of denial. May be `null`.
</ResponseField>

<ResponseField name="limit" type="number | null">
  The limit that was hit. May be `null`.
</ResponseField>

<ResponseField name="reason" type="string">
  The denial reason, mirroring `code`.
</ResponseField>

<CodeGroup>
  ```json 402 — plan credits exhausted theme={null}
  {
    "code": "credit_plan_exhausted",
    "layer": "credit",
    "key": "<org_uuid>",
    "current": null,
    "limit": 5000.0,
    "reason": "credit_plan_exhausted"
  }
  ```

  ```json 403 — quota exceeded theme={null}
  {
    "code": "quota_exceeded",
    "layer": "quota",
    "key": "<org_uuid>",
    "current": null,
    "limit": null,
    "reason": "quota_exceeded"
  }
  ```

  ```json 429 — rate limited theme={null}
  {
    "code": "rate_limit_exceeded",
    "layer": "rate",
    "key": "api",
    "current": 500,
    "limit": 500,
    "reason": "rate_limit_exceeded"
  }
  ```
</CodeGroup>

A `429` carries `Retry-After` (default `60`) and `X-RateLimit-Limit` / `X-RateLimit-Remaining`
/ `X-RateLimit-Reset` headers.

<Warning>
  **Two different denial shapes coexist for managed knowledge.** The credit, wallet, quota,
  and rate gate denials use the flat `DenialEnvelope` above. Document-level limits — a file
  larger than your plan's `max_file_size_bytes`, exceeding the documents-per-knowledge-base
  cap, or running out of storage quota — are raised as a `KnowledgeBaseQuotaExceededError` →
  `403` with the **ordinary** `{detail}` shape, **not** the `DenialEnvelope`. Branch on both.
  See [Usage gating & limits](/billing/usage-gating) and
  [Errors & status codes](/api-reference/errors).
</Warning>

## Worked example — search a managed knowledge base

Every request authenticates with `Authorization: Bearer mx_live_…` plus the
`X-Organization-ID` header (see [Authentication](/api-reference/authentication)). Searching a
managed knowledge base reserves `1` retrieval credit before the query is embedded.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.modulex.dev/knowledge-bases/7c1e.../search \
    -H "Authorization: Bearer mx_live_xxx" \
    -H "X-Organization-ID: org_123" \
    -H "Content-Type: application/json" \
    -d '{"query":"how to install","top_k":5,"min_score":0.3}'
  ```

  ```python Python theme={null}
  import asyncio
  from modulex import Modulex

  mx = Modulex(api_key="mx_live_xxx", organization_id="org_123")

  async def main():
      result = await mx.knowledge_bases.search(
          "7c1e...",
          query="how to install",
          top_k=5,
          min_score=0.3,
      )
      print(result)

  asyncio.run(main())
  ```

  ```javascript JavaScript theme={null}
  import { Modulex } from "modulex-js";

  const mx = new Modulex({
    apiKey: "mx_live_xxx",
    organizationId: "org_123",
  });

  const result = await mx.knowledgeBases.search("7c1e...", {
    query: "how to install",
    topK: 5,
    minScore: 0.3,
  });
  console.log(result);
  ```
</CodeGroup>

<Note>
  The SDK method names and parameter casing for the knowledge-base search operation are not
  fully pinned in the research base. The cURL request and its body are verified against the
  backend; the Python and JavaScript snippets above show the standard ModuleX client shape and
  should be confirmed against the [JavaScript SDK](/sdks/javascript) and
  [Python SDK](/sdks/python) references before relying on the exact method names. {/* TODO: confirm knowledge-base search SDK method names/casing against modulex-js and modulex-python */}
</Note>

A successful response returns the matching chunks with cosine-similarity scores. The full
request and response schema for every managed knowledge operation — search, hybrid search,
retrieve-context, multi-knowledge-base search, ingest, and document management — lives in
[Managed knowledge (modulexdb)](/platform/knowledge/managed).

## Limits

These document limits apply to every knowledge base, managed or BYOK.

| Limit                        | Value                                                                                       |
| ---------------------------- | ------------------------------------------------------------------------------------------- |
| Supported file types         | `pdf`, `docx`, `doc`, `txt`, `md`, `html`, `csv`, `json`, `xlsx`, `pptx`                    |
| Documents per knowledge base | `500`                                                                                       |
| Per-file size cap            | Your plan's `max_file_size_bytes` (Free 10 MB, Pro 50 MB, Max 100 MB, Enterprise unlimited) |
| Total org storage            | Your plan's storage entitlement (Free 1 GiB, Pro 50 GiB, Max 500 GiB, Enterprise unlimited) |

<Warning>
  **The per-file cap is a plan entitlement, not a fixed 50 MB.** The
  `/knowledge-bases/info/supported-file-types` endpoint advertises 50 MB as a fallback, but
  the enforced cap is your plan value. See [Managing documents](/platform/knowledge/documents).
</Warning>

## Related pages

<CardGroup cols={2}>
  <Card title="Managed knowledge (modulexdb)" icon="book" href="/platform/knowledge/managed">
    The full technical reference: embedding and chunking schema, ingest and retrieval
    pipelines, and the per-operation REST surface.
  </Card>

  <Card title="Knowledge providers" icon="layer-group" href="/integrations/knowledge-providers/overview">
    Compare modulexdb with the BYOK vector stores.
  </Card>

  <Card title="Knowledge node" icon="diagram-project" href="/workflow-builder/nodes/knowledge">
    Retrieve from modulexdb inside a workflow.
  </Card>

  <Card title="Credits & metering" icon="coins" href="/billing/credits">
    What a credit is and exactly what managed knowledge consumes.
  </Card>
</CardGroup>
