Query Editor API
The Query Editor API provides endpoints for executing SQL queries against connected data sources, managing saved queries and tab drafts, viewing execution history, and exporting results.
All endpoints are scoped to a space and require authentication.
Base path: /spaces/{slug}/query
Endpoints
Execute Query
POST /spaces/{slug}/query/execute
Execute a SQL query against a connected data source. Only SELECT statements are allowed.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
connector_id | UUID | ✅ | ID of the query-capable connector |
sql | string | ✅ | SQL query text |
row_limit | integer | Maximum rows to return (default: 500) |
Response:
{
"columns": [
{"name": "id", "type": "integer"},
{"name": "email", "type": "varchar"}
],
"rows": [
{"id": 1, "email": "***MASKED***"}
],
"row_count": 1,
"execution_ms": 142,
"warnings": []
}
Error Codes:
| Status | Reason |
|---|---|
| 400 | Connector not queryable or query execution error |
| 403 | DML/DDL statement blocked |
| 429 | Rate limit exceeded |
List Queryable Connectors
GET /spaces/{slug}/query/connectors
Returns connectors in the space that support SQL execution.
Response: QueryableConnectorResponse[]
[
{
"id": "uuid",
"name": "Production DB",
"connector_type": "query_postgres",
"source_system_name": "data-warehouse"
}
]
Autocomplete
GET /spaces/{slug}/query/autocomplete
Returns table and column names from the catalog for SQL editor autocompletion.
Response:
{
"tables": [
{
"name": "users",
"schema": "public",
"columns": ["id", "email", "created_at"]
}
]
}
AI Query Writer
AI query writer endpoints generate, explain, and refine SQL using the current space schema context. They require authentication, are scoped to the {slug} space, and require the ai.query_writer_enabled feature.
Generated and refined SQL is validated before it is returned. Validation enforces a single read-only statement, connector-dialect parsing, known tables from the current space schema context, known columns on referenced tables or aliases, and no external schema references unless the qualified table is present in the schema context.
Generate SQL
POST /spaces/{slug}/query/ai/generate
Generate SQL from a natural language prompt. The generated SQL is intended for review before execution.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | ✅ | Natural language description of the desired query. Maximum 2,000 characters. |
connector_id | UUID | null | Connector used to resolve dialect-specific SQL parsing. |
Response:
{
"sql": "SELECT status, COUNT(*) AS order_count FROM orders GROUP BY status",
"dialect": "postgresql"
}
Explain SQL
POST /spaces/{slug}/query/ai/explain
Explain an existing SQL query in plain language.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
sql | string | ✅ | SQL query to explain. Maximum 50,000 characters. |
Response:
{
"explanation": "This query counts orders by status."
}
Refine SQL
POST /spaces/{slug}/query/ai/refine
Modify an existing SQL query with a natural language instruction. The refined SQL is intended for review before execution.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
current_sql | string | ✅ | SQL query to modify. Maximum 50,000 characters. |
instruction | string | ✅ | Natural language change request. Maximum 2,000 characters. |
connector_id | UUID | null | Connector used to resolve dialect-specific SQL parsing. |
Response:
{
"sql": "SELECT status, COUNT(*) AS order_count FROM orders WHERE status IS NOT NULL GROUP BY status"
}
Error Codes:
| Status | Reason |
|---|---|
| 400 | Prompt/input validation error or generated SQL validation failure, including unknown tables, unknown columns, mutation statements, multiple statements, external schema references, or connector dialect parse errors |
| 403 | Missing access to the space or disabled ai.query_writer_enabled feature |
Saved Queries
Create
POST /spaces/{slug}/query/saved
| Field | Type | Required | Description |
|---|---|---|---|
title | string | ✅ | Query title |
sql_text | string | ✅ | SQL query text |
connector_id | UUID | ✅ | Associated connector |
is_shared | boolean | Share with space members (default: false) |
List
GET /spaces/{slug}/query/saved
Returns saved queries visible to the current user (personal + shared). Supports pagination via X-Pagination-* headers.
Update
PUT /spaces/{slug}/query/saved/{query_id}
Update title, SQL, or sharing setting. Owner only.
Delete
DELETE /spaces/{slug}/query/saved/{query_id}
Returns 204 No Content. Owner only.
Tab Drafts
Tab drafts persist the user's editor tab state across sessions.
Get Drafts
GET /spaces/{slug}/query/drafts
Response:
{
"tabs": [
{
"id": "tab-1",
"title": "Untitled",
"sql_text": "SELECT * FROM users",
"connector_id": "uuid"
}
],
"active_tab_id": "tab-1",
"updated_at": "2026-02-16T12:00:00Z"
}
Save Drafts
PUT /spaces/{slug}/query/drafts
Upserts the full tab state for the current user/space.
Query History
User History
GET /spaces/{slug}/query/history
Returns the current user's query execution history. Supports pagination.
Response item:
{
"id": "uuid",
"connector_id": "uuid",
"sql_text": "SELECT ...",
"row_count": 42,
"execution_ms": 203,
"status": "success",
"error_message": null,
"executed_at": "2026-02-16T12:00:00Z"
}
Admin History
GET /spaces/{slug}/query/history/admin
Returns all users' query executions in the space. Requires admin permissions. Includes user_email field.
Export Results
POST /spaces/{slug}/query/export
Executes a query and streams results as CSV or JSON. Uses StreamingResponse for memory efficiency.
| Field | Type | Required | Description |
|---|---|---|---|
connector_id | UUID | ✅ | Connector to query |
sql | string | ✅ | SQL query text |
format | string | ✅ | "csv" or "json" |
Maximum export rows: 2,000.
PII/PHI Masking
All query endpoints respect PII/PHI masking. Columns flagged as sensitive are masked unless the user's product role explicitly grants PII/PHI access. Masking applies to both result grids and exports.