---
title: "Run a SQL query"
method: POST
path: "/v1/workspaces/{id}/tools/run-sql"
tags: ["Workspaces"]
---

# Run a SQL query

`POST /v1/workspaces/{id}/tools/run-sql`

## Request

- Base URL: `https://console.nace.ai`
- URL: `https://console.nace.ai/v1/workspaces/{id}/tools/run-sql`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/nace/apis/drex-api/docs/v1/workspaces/:id/tools/run-sql/post.ts> (a function with typed inputs; its response is checked against the schema)

Runs one read-only `SELECT` (DuckDB dialect) over the workspace's tables and returns a preview of the result. Table names come from `locate`'s `tables`, `read-file`'s `sql_tables` and the refusal of a query naming an unknown table, which lists them all. Every result is kept: `result.handle` (`res_…`) is a table the next query in this workspace may join, total or page with `LIMIT`/`OFFSET`, and `result_citation.result_file` is the whole result as a Parquet file, downloadable from its `download_url` without the API key until `download_url_expires_at`; it is not one of the workspace's files. A statement that isn't a read is refused. File reads and SQL queries together are limited to 600 per account every 10 minutes. Free.

## Path parameters

- `id` string, required

## Headers

- `Idempotency-Key` string

## Request body

- RunSqlRequest
  - `sql` string, required: One read-only `SELECT` (DuckDB dialect) over the workspace's tables and earlier `res_…` results.

## Response `200`

The answer.

- RunSqlResponse
  - `sql` string, required: The statement that ran, normalized.
  - `duplicate` boolean: True when an earlier identical query's stored result answered it.
  - `result` SqlResult, required
    - `handle` string, required: The result's `res_…` name: a table the next query in this workspace may read.
    - `row_count` integer, required: Rows in the whole result.
    - `columns` SqlResultColumn[]
      - `name` string, required
      - `data_type` string, required
    - `rows` object[]: The first rows, one object each, keyed by column.
    - `preview_truncated` boolean: True when `rows` holds fewer rows than the result.
    - `path` string, nullable
  - `source_paths` string[]: The files the query read.
  - `result_citation` SqlResultCitation
    - `result_file` SqlResultFile, required
      - `file_id` string, required: The stored result's id. It is not one of the workspace's files: read the result through `download_url`, or query its `handle`.
      - `handle` string, required
      - `path` string, required
      - `file_name` string, required
      - `format` 'parquet', required
      - `row_count` integer, required
      - `download_url` string, required: The whole result; works without the API key until `download_url_expires_at`.
      - `preview_url` string, required
      - `download_url_expires_at` string, date-time, required
    - `source_paths` string[], required
    - `sql` string, required
    - `grounding` object, nullable: The source rows behind the result, when they could be traced.
  - `result_materialization_error` string, nullable
  - `job_id` string, nullable: The job the call ran as; `GET /v1/documents/jobs/{id}` reads it.

## Other responses

- `401`: Missing or invalid API key (`authentication_error`, code `invalid_api_key`).
- `403`: The query reads a file the key can't read (`permission_error`, code `access_denied`).
- `404`: No workspace with this id that the key may use (`not_found_error`, code `workspace_not_found`), or Workspaces are off on this deployment (`not_found`).
- `422`: The body is invalid, or the document service refused it (`invalid_request_error`); the message says why. The workspace is checked first, so an id the key can't use answers `404` whatever the body.
- `429`: Over the account's requests per minute, or over 600 file reads and SQL queries per account every 10 minutes, together (`rate_limit_error`, code `rate_limited`).
- `500`: Something failed on Drex's side (`internal_error`).
- `502`: The document service refused Drex's own request (`upstream_error`, code `ndi_refused_drex`). Retry later.
- `503`: The document service is unavailable, or did not answer in time (`service_unavailable`). Retry with the same `Idempotency-Key`.
- `504`: The document service timed out (`upstream_error`). Retry with the same `Idempotency-Key`.

---

[API](https://skmtc.dev/nace/apis/drex-api.md) - [All operations](https://skmtc.dev/nace/apis/drex-api/llms.txt) - [OpenAPI document](https://skmtc.dev/nace/apis/drex-api/revisions/a0e62d925a61?raw)
