curl --request POST \
--url https://ndi-api.nace.ai/v1/workspaces/{workspace_id}/tools/query-tables \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"paths": [
{
"path": "<string>",
"component": "<string>"
}
],
"query": "<string>"
}
'{
"answer": "<string>",
"citations": [],
"confidence": "certain",
"error": "<string>",
"job_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"result_citations": [],
"result_materialization_error": "<string>",
"structured_answer": "<unknown>",
"tables": [],
"timed_out": false,
"unavailable": []
}{
"created_at": "2023-11-07T05:31:56Z",
"job_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"kind": "parse",
"status": "queued",
"cost": {
"lines": [
{
"amount_usd": "<string>",
"execution": "fresh",
"operation": "parse",
"quantity": 1,
"unit": "page",
"unit_price_usd": "<string>",
"reuse_reason": "reused_parse"
}
],
"pricing_version": "<string>",
"total_usd": "<string>",
"currency": "USD"
},
"credit_schedule_version": 123,
"credits": 123,
"deleted_at": "2023-11-07T05:31:56Z",
"effort": "<string>",
"error": {
"code": "invalid_request",
"message": "<string>",
"retryable": true,
"detail": {},
"request_id": "<string>"
},
"finished_at": "2023-11-07T05:31:56Z",
"force": true,
"idempotency_key": "<string>",
"name": "<string>",
"payload_expires_at": "2023-11-07T05:31:56Z",
"progress": {
"items_done": 0,
"items_failed": 0,
"items_total": 123,
"knowledge_graph": {
"countable": true,
"phase_count": 123,
"phase_index": 123,
"documents": 123,
"mentions": 123,
"step": "<string>",
"step_done": 123,
"step_total": 123
},
"routing": {
"final": "fact",
"reason": "<string>",
"router_model": "<string>",
"selected": "fact",
"delegated_wall_ms": 123,
"fact_wall_ms": 123,
"router": {
"kind": "llm"
},
"router_wall_ms": 123
},
"stage": "<string>",
"units_done": 0,
"units_total": 123
},
"project_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"query": "<string>",
"query_scope": {
"type": "workspace"
},
"result": {
"output": {
"categories": [
{
"count": 123,
"name": "<string>"
}
],
"coverage": {
"labels_required": [
"<string>"
],
"request_access_hint": "<string>",
"restricted_candidates": 0
},
"directory": "<string>",
"file_entries": [
{
"ingestion_status": "discovered",
"path": "<string>",
"size_bytes": 123,
"category": "<string>",
"kind": "<string>",
"uploaded_at": "2023-11-07T05:31:56Z"
}
],
"files_truncated": true,
"ingestion_summary": {},
"overall_files": 123,
"subdirectories": [
{
"name": "<string>",
"overall_files": 123,
"failed_files": 123,
"top_categories": [
{
"count": 123,
"name": "<string>"
}
]
}
],
"hint": "<string>",
"job_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"result_type": "folder_metadata"
},
"result_state": "available",
"source": {
"upload_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "upload"
},
"started_at": "2023-11-07T05:31:56Z",
"surface": "deep_search",
"units": 0,
"usage": {
"lines": [
{
"credits": 1,
"credits_per_unit": 1,
"multiplier": 2,
"part": "parse",
"quantity": 1,
"unit": "page",
"waiver": {
"part": "parse",
"reason": "reused_parse",
"source_job_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
]
},
"usage_final": false,
"usage_finalized_at": "2023-11-07T05:31:56Z",
"workspace_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"error": {
"code": "invalid_request",
"detail": null,
"message": "Request body has extra fields that this operation does not accept.",
"request_id": "req-01j9k2n3p4q5r6s7t8v9",
"retryable": false
}
}{
"error": {
"code": "invalid_request",
"detail": null,
"message": "Request body has extra fields that this operation does not accept.",
"request_id": "req-01j9k2n3p4q5r6s7t8v9",
"retryable": false
}
}query_tables
Answer a natural-language question over uploaded table files — one or several.
Cost class: slow.
paths is a list of selection rows — {"path": ...} for a whole file,
{"path": ..., "component": <tab>} for one tab of one workbook (repeat
the path to select several tabs). Every path must be a table file —
a spreadsheet (xlsx, xls, xlsm, xlsb, ods) or record file (csv, tsv,
parquet, jsonl, ndjson, json); a document, media, or image path is
refused with invalid_request naming qa-file. Every tab is askable whatever its ingestion produced:
selections whose tabs all have extracted rows are answered by the SQL
engine — the answer keeps full result parquet storage outside the response
and returns bounded previews plus authenticated workspace result-file
citations — while a selection holding tabs with only a rendered sheet is
answered by a QA agent that reads renderings and queries row extractions
together (no result previews on that lane; citations quote the sheets).
component names are workbook-local — the same strings file-metadata
and filtered-search publish as component, matched exact-name first,
then the unambiguous sanitized alias. A name that matches nothing on its
own workbook — or any component on a single-table upload
(csv/jsonl/parquet), which has no named parts — is invalid_request. A
selected tab with no usable content at all is reported in unavailable
rather than silently dropped.
Execution survives HTTP disconnects. By default the route waits and returns
the original answer shape. Send Prefer: respond-async to return a Job
immediately, then poll its Location URL. Idempotency-Key recovers the
same job after a lost response. Only explicit job cancellation stops it.
curl --request POST \
--url https://ndi-api.nace.ai/v1/workspaces/{workspace_id}/tools/query-tables \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"paths": [
{
"path": "<string>",
"component": "<string>"
}
],
"query": "<string>"
}
'{
"answer": "<string>",
"citations": [],
"confidence": "certain",
"error": "<string>",
"job_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"result_citations": [],
"result_materialization_error": "<string>",
"structured_answer": "<unknown>",
"tables": [],
"timed_out": false,
"unavailable": []
}{
"created_at": "2023-11-07T05:31:56Z",
"job_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"kind": "parse",
"status": "queued",
"cost": {
"lines": [
{
"amount_usd": "<string>",
"execution": "fresh",
"operation": "parse",
"quantity": 1,
"unit": "page",
"unit_price_usd": "<string>",
"reuse_reason": "reused_parse"
}
],
"pricing_version": "<string>",
"total_usd": "<string>",
"currency": "USD"
},
"credit_schedule_version": 123,
"credits": 123,
"deleted_at": "2023-11-07T05:31:56Z",
"effort": "<string>",
"error": {
"code": "invalid_request",
"message": "<string>",
"retryable": true,
"detail": {},
"request_id": "<string>"
},
"finished_at": "2023-11-07T05:31:56Z",
"force": true,
"idempotency_key": "<string>",
"name": "<string>",
"payload_expires_at": "2023-11-07T05:31:56Z",
"progress": {
"items_done": 0,
"items_failed": 0,
"items_total": 123,
"knowledge_graph": {
"countable": true,
"phase_count": 123,
"phase_index": 123,
"documents": 123,
"mentions": 123,
"step": "<string>",
"step_done": 123,
"step_total": 123
},
"routing": {
"final": "fact",
"reason": "<string>",
"router_model": "<string>",
"selected": "fact",
"delegated_wall_ms": 123,
"fact_wall_ms": 123,
"router": {
"kind": "llm"
},
"router_wall_ms": 123
},
"stage": "<string>",
"units_done": 0,
"units_total": 123
},
"project_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"query": "<string>",
"query_scope": {
"type": "workspace"
},
"result": {
"output": {
"categories": [
{
"count": 123,
"name": "<string>"
}
],
"coverage": {
"labels_required": [
"<string>"
],
"request_access_hint": "<string>",
"restricted_candidates": 0
},
"directory": "<string>",
"file_entries": [
{
"ingestion_status": "discovered",
"path": "<string>",
"size_bytes": 123,
"category": "<string>",
"kind": "<string>",
"uploaded_at": "2023-11-07T05:31:56Z"
}
],
"files_truncated": true,
"ingestion_summary": {},
"overall_files": 123,
"subdirectories": [
{
"name": "<string>",
"overall_files": 123,
"failed_files": 123,
"top_categories": [
{
"count": 123,
"name": "<string>"
}
]
}
],
"hint": "<string>",
"job_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"result_type": "folder_metadata"
},
"result_state": "available",
"source": {
"upload_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "upload"
},
"started_at": "2023-11-07T05:31:56Z",
"surface": "deep_search",
"units": 0,
"usage": {
"lines": [
{
"credits": 1,
"credits_per_unit": 1,
"multiplier": 2,
"part": "parse",
"quantity": 1,
"unit": "page",
"waiver": {
"part": "parse",
"reason": "reused_parse",
"source_job_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
]
},
"usage_final": false,
"usage_finalized_at": "2023-11-07T05:31:56Z",
"workspace_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"error": {
"code": "invalid_request",
"detail": null,
"message": "Request body has extra fields that this operation does not accept.",
"request_id": "req-01j9k2n3p4q5r6s7t8v9",
"retryable": false
}
}{
"error": {
"code": "invalid_request",
"detail": null,
"message": "Request body has extra fields that this operation does not accept.",
"request_id": "req-01j9k2n3p4q5r6s7t8v9",
"retryable": false
}
}Authorizations
Headers
Replaying a request with the same key returns the original job with 200, never a second job. The key is kept with the job for replay and never cleared, so it must not contain personal data.
200Path Parameters
Workspace identifier.
Body
Question over a bounded set of workspace-uploaded table selections.
Every row's path must name a table file — a spreadsheet (xlsx,
xls, xlsm, xlsb, ods) or record file (csv, tsv, parquet, jsonl, ndjson,
json); a document, media, or image path is refused with
invalid_request naming qa-file. Every tab is
askable whatever its ingestion produced — extracted rows, a rendered
sheet, or both.
1 - 32 elementsShow child attributes
Show child attributes
1 - 4096A JSON Schema (Draft 2020-12, object root, local non-recursive $ref only, no pattern, patternProperties or unevaluated*) the answer must follow. When set, the agent writes answer as JSON text conforming to it, the run checks that and asks the agent to correct a mismatch, and the result carries the parsed value in structured_answer. A field the source does not state comes back null, whatever type the schema gives it. Explanation goes to reasoning where the result has one, and evidences are unchanged. If the answer still misses the schema, the run succeeds with answer as written and structured_answer null. Omit for a prose answer.
Show child attributes
Show child attributes
Response
Successful Response
- QueryTablesResponse
- Job
Answer, provenance, unavailable inputs, and retained result previews.
Two lanes fill this shape. An all-queryable selection runs the SQL engine
and returns everything: tables previews, result_citations, and SQL
receipts in citations. A selection holding tabs without extracted rows
runs a QA agent over the files' rendered sheets and row extractions
together — the answer and quoted citations are filled, while
tables and result_citations stay empty (no SQL results exist to
retain). unavailable reports selections with no usable content on
either lane.
job_id is the durable job row created for this run; retrieve it via
GET /v1/jobs/{job_id} to inspect or replay the stored answer.
Show child attributes
Show child attributes
The engine's self-graded confidence in the answer — how well the queried tables support it, on the shared six-level scale (certain / very_high / high / medium / low / speculative). Null when the engine could not grade (a timeout's partial answer, a legacy run).
certain, very_high, high, medium, low, speculative Show child attributes
Show child attributes
answer parsed as JSON, set only when the request carried output_schema and the answer validates against it; a field the source does not state is null whatever type the schema gives it. Null on every run without a schema, and on a run whose answer still missed the schema after its corrections, where answer holds the text as written.
Show child attributes
Show child attributes
Show child attributes
Show child attributes