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

# Knowledge bases: upload & search

> Upload documents to a knowledge base, wait for ingestion, then search

Knowledge bases ingest documents asynchronously (parse → chunk → embed) and let
you search the result:

* **Upload** — `POST /v1/knowledge-bases/{kb_id}/upload_train` (multipart). Returns run ids you can poll.
* **Search** — `POST /v1/knowledge-bases/{kb_id}/search`.

Replace `kb_id` and `your_api_key`. Use the `prefix` parameter to organise and
scope documents into folders.

## Upload documents and wait for ingestion

<Note>
  Upload returns immediately with run ids; ingestion runs in the background.
  Poll the training runs (SDK `get_runs`, or the
  [running jobs](/api-reference/v1/knowledge-base/running-jobs) endpoint) until
  they complete before searching. Don't set `Content-Type` yourself on the
  upload — let your HTTP client set the multipart boundary.
</Note>

<CodeGroup>
  ```python Python SDK theme={null}
  # pip install noxus-sdk
  from pathlib import Path
  import time
  from noxus_sdk.client import Client

  client = Client(api_key="your_api_key")
  kb = client.knowledge_bases.get(knowledge_base_id="kb_id")

  run_ids = kb.upload_document(files=[Path("path/to/document.pdf")], prefix="/")
  print(f"ingestion started: {run_ids}")

  # Wait for ingestion to finish
  while any(
      r.status not in ("completed", "failed")
      for r in kb.get_runs(run_ids=",".join(run_ids))
  ):
      time.sleep(3)
  print("ingestion done")
  ```

  ```python Python REST theme={null}
  import requests

  base = "https://backend.noxus.ai"

  files = [("files", ("document.txt", open("path/to/document.txt", "rb"), "text/plain"))]
  resp = requests.post(
      f"{base}/v1/knowledge-bases/kb_id/upload_train",
      headers={"X-API-KEY": "your_api_key"},  # no Content-Type — requests sets multipart
      files=files,
      params={"prefix": "/"},
  )
  print(resp.json())  # run ids to poll for ingestion status
  ```

  ```javascript Node theme={null}
  import fs from "fs";

  const base = "https://backend.noxus.ai";

  const form = new FormData();
  form.append("files", new Blob([fs.readFileSync("path/to/document.txt")]), "document.txt");

  const resp = await fetch(`${base}/v1/knowledge-bases/kb_id/upload_train?prefix=/`, {
    method: "POST",
    headers: { "X-API-KEY": "your_api_key" }, // fetch sets the multipart boundary
    body: form,
  });
  console.log(await resp.json()); // run ids
  ```

  ```bash cURL theme={null}
  curl -X POST "https://backend.noxus.ai/v1/knowledge-bases/kb_id/upload_train?prefix=/" \
    -H "X-API-KEY: your_api_key" \
    -F "files=@path/to/document.txt"
  ```
</CodeGroup>

## Search the knowledge base

<Note>
  Runs a semantic / hybrid query (depending on the KB's retrieval settings) over
  the ingested content and returns the matching chunks with their source
  documents. Scope the search with `prefix`.
</Note>

<CodeGroup>
  ```python Python SDK theme={null}
  from noxus_sdk.client import Client

  client = Client(api_key="your_api_key")
  kb = client.knowledge_bases.get(knowledge_base_id="kb_id")

  for result in kb.search(query="Your search query", prefix="/"):
      print(result.document_source.name)
      print(result.content)
  ```

  ```python Python REST theme={null}
  import requests

  resp = requests.post(
      "https://backend.noxus.ai/v1/knowledge-bases/kb_id/search",
      params={"query": "Your search query", "prefix": "/"},
      headers={"X-API-KEY": "your_api_key", "Content-Type": "application/json"},
  )
  for result in resp.json():
      print(result["document_source"]["name"])
      print(result["content"])
  ```

  ```javascript Node theme={null}
  const params = new URLSearchParams({ query: "Your search query", prefix: "/" });
  const resp = await fetch(
    `https://backend.noxus.ai/v1/knowledge-bases/kb_id/search?${params}`,
    {
      method: "POST",
      headers: { "X-API-KEY": "your_api_key", "Content-Type": "application/json" },
    }
  );
  for (const result of await resp.json()) {
    console.log(result.document_source.name);
    console.log(result.content);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST "https://backend.noxus.ai/v1/knowledge-bases/kb_id/search?query=Your%20search%20query&prefix=/" \
    -H "X-API-KEY: your_api_key" \
    -H "Content-Type: application/json"
  ```
</CodeGroup>

## Async / await with the SDK

<Note>
  Use the `a`-prefixed coroutines (`aget`, `aupload_document`, `aget_runs`,
  `asearch`) from async code so the event loop stays responsive.
</Note>

```python Python SDK theme={null}
import asyncio
from pathlib import Path
from noxus_sdk.client import Client


async def main():
    client = Client(api_key="your_api_key")
    kb = await client.knowledge_bases.aget(knowledge_base_id="kb_id")

    await kb.aupload_document(files=[Path("path/to/document.pdf")], prefix="/")

    results = await kb.asearch(query="Your search query", prefix="/")
    for r in results:
        print(r.document_source.name, r.content)


asyncio.run(main())
```
