> ## 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.

# Query tables

> Ask one question across spreadsheets, or run a guarded SELECT

`query_tables` answers one natural-language question over uploaded
workbooks. `run_sql` is the fast lane when you already have a SELECT.
**`run_sql` is Python-only** in the SDK; TypeScript callers POST
`/v1/workspaces/{id}/tools/run-sql`.

<Tabs>
  <Tab title="Python">
    ```python theme={"dark"}
    from ndi_sdk import NdiClient

    with NdiClient() as client:
        workspace_id = "550e8400-e29b-41d4-a716-446655440001"
        answer = client.tools.query_tables(
            workspace_id,
            paths=["books/ledger.xlsx", "books/trial-balance.xlsx"],
            query="Which accounts increased more than 10 percent?",
        )
        print(answer.answer)
        rows = client.tools.run_sql(
            workspace_id,
            sql="SELECT account, amount FROM ledger LIMIT 20",
        )
        print(rows)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={"dark"}
    import { NdiClient } from "ndi-sdk";

    const client = new NdiClient();
    const workspaceId = "550e8400-e29b-41d4-a716-446655440001";
    const answer = await client.tools.queryTables(workspaceId, {
      paths: ["books/ledger.xlsx", "books/trial-balance.xlsx"],
      query: "Which accounts increased more than 10 percent?",
    });
    console.log(answer.answer);

    const sql = await fetch(`${process.env.NDI_BASE_URL}/v1/workspaces/${workspaceId}/tools/run-sql`, {
      method: "POST",
      headers: {
        "X-API-Key": process.env.NDI_API_KEY ?? "",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ sql: "SELECT account, amount FROM ledger LIMIT 20" }),
    });
    console.log(await sql.json());
    ```
  </Tab>

  <Tab title="curl">
    ```bash theme={"dark"}
    curl -s -X POST "$NDI_BASE_URL/v1/workspaces/$WS/tools/query-tables" \
      -H "X-API-Key: $NDI_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"paths":[{"path":"books/ledger.xlsx"}],"query":"Which accounts increased more than 10 percent?"}'

    curl -s -X POST "$NDI_BASE_URL/v1/workspaces/$WS/tools/run-sql" \
      -H "X-API-Key: $NDI_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"sql":"SELECT account, amount FROM ledger LIMIT 20"}'
    ```
  </Tab>
</Tabs>

Workbooks must be ingested first so parquet tables exist. The response keeps
the full result in scratch storage and returns the answer, citations,
unavailable sources, and a bounded preview.

`run_sql` is read-only. The full result is retained as parquet
(`result_citation.result_file.download_url`); its `res_…` handle is a
registered table on the next call.

Use [qa-file](/guides/file-tools) for PDFs and other documents, not
spreadsheets.
