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

# Workspaces

> Create a corpus, upload files, ingest, and search

Uploading registers a ledger row. Ingestion is a separate, billable call.

```python theme={"dark"}
from ndi_sdk import NdiClient

with NdiClient() as client:
    workspace = client.workspaces.create(name="fy25-audit")
    client.jobs.wait(
        client.files.upload(
            workspace.workspace_id,
            "report.pdf",
            path="reports/report.pdf",
        ).job_id
    )
    client.jobs.wait(
        client.ingestion.ingest(workspace.workspace_id, path_prefix="reports/").job_id,
        timeout=600,
    )
    hits = client.tools.hybrid_search(
        workspace.workspace_id,
        query="total liabilities at year end",
        k=5,
    )
    for hit in hits.hits:
        print(hit.path, hit.snippet)
```

`client.upload_and_ingest(...)` collapses upload + ingest for one file.
`files.upload` switches to a resumable session automatically at **32 MiB**.

## Workspaces

```text theme={"dark"}
def create(*, name: str, domain_slug: str = "generic", access: AccessConfig | None = None, ...) -> Workspace
def get(workspace_id) -> Workspace
def list(*, name_contains=None, cursor=None, limit=None) -> Page[Workspace]
def iter_all(*, name_contains=None) -> Iterator[Workspace]
def stats(workspace_id) -> WorkspaceStats
def delete(workspace_id, *, confirm_name: str) -> Job
```

`access.labels` is a list of `{name, description}` catalog objects.

## Files and ingestion

```text theme={"dark"}
client.files.upload(workspace_id, content, *, path: str, ...)
client.files.upload_chunked(...)
client.files.create_upload_grant(workspace_id, *, path=None, max_bytes=None, ...)
client.ingestion.ingest(workspace_id, *, file_ids=None, path_prefix=None, stale_only=False, ...)
client.ingestion.reconcile(workspace_id, *, auto_ingest=False, ...)
client.ingestion.build_knowledge_graph(workspace_id)
```

## Search and tools

```text theme={"dark"}
client.tools.hybrid_search(workspace_id, *, query: str, k: int = 10, path_prefix=None)
client.tools.qa_file(workspace_id, *, path: str, query: str)
client.tools.query_tables(workspace_id, *, paths: list[str], query: str)
client.tools.run_sql(workspace_id, *, sql: str)          # Python only
client.search.fact(workspace_id, *, query: str, ...)
client.search.deep(workspace_id, *, query: str, session_id=None, ...)
client.search.filtered(workspace_id, *, query: str, ...)  # Python only
```

`qa_file` is for documents, images, and recordings — not Excel. Use
`query_tables`. Deep search is one question per `session_id`.

See [Workspace](/guides/workspace), [Search](/guides/search), and
[File tools](/guides/file-tools).
