API ReferenceSaved Queries
API Reference

Saved Queries

Save, version, and execute named SQL queries. Each update creates a new version, preserving the full history. Saved queries are automatically classified by category (e.g., aggregation, join, filtered scan) and can be executed by ID.

List saved queries

GET/v1/queries

Query parameters

  • limit integer — Maximum number of results
  • offset integer — Pagination offset

Response 200 — List of saved queries

  • count integerrequired. Min: 0
  • has_more booleanrequired
  • limit integerrequired. Min: 0
  • offset integerrequired. Min: 0
  • queries SavedQuerySummary[] — required
    • created_at stringrequired
    • description stringrequired
    • id stringrequired
    • latest_version integerrequired
    • name stringrequired
    • tags string[] — required
    • updated_at stringrequired
{
  "count": 0,
  "has_more": true,
  "limit": 0,
  "offset": 0,
  "queries": [
    {
      "created_at": "2026-01-01T00:00:00Z",
      "description": "string",
      "id": "string",
      "latest_version": 0,
      "name": "string",
      "tags": [
        "string"
      ],
      "updated_at": "2026-01-01T00:00:00Z"
    }
  ]
}

Create saved query

POST/v1/queries

Save a named SQL query. The SQL is stored as version 1 and automatically analyzed for classification metadata (category, table count, predicate/join/aggregation flags).

Request body

  • description string,null
  • name stringrequired
  • sql stringrequired
  • tags string[] | null
{
  "description": "Ten highest-spending customers by order total",
  "name": "top-customers",
  "sql": "SELECT customer_id, sum(amount) AS total FROM orders GROUP BY customer_id ORDER BY total DESC LIMIT 10",
  "tags": [
    "sales",
    "weekly"
  ]
}

Response 201 — Saved query created

  • category string,null
  • created_at stringrequired
  • description stringrequired
  • has_aggregation boolean,null
  • has_group_by boolean,null
  • has_join boolean,null
  • has_limit boolean,null
  • has_order_by boolean,null
  • has_predicate boolean,null
  • id stringrequired
  • latest_version integerrequired
  • name stringrequired
  • num_tables integer,null
  • sql stringrequired
  • sql_hash stringrequired
  • table_size string,null
  • tags string[] — required
  • updated_at stringrequired
{
  "category": "string",
  "created_at": "2026-01-01T00:00:00Z",
  "description": "string",
  "has_aggregation": true,
  "has_group_by": true,
  "has_join": true,
  "has_limit": true,
  "has_order_by": true,
  "has_predicate": true,
  "id": "string",
  "latest_version": 0,
  "name": "string",
  "num_tables": 0,
  "sql": "string",
  "sql_hash": "string",
  "table_size": "string",
  "tags": [
    "string"
  ],
  "updated_at": "2026-01-01T00:00:00Z"
}

Errors

StatusDescription
400Invalid request

Get saved query

GET/v1/queries/{id}

Path parameters

  • id stringrequired. Saved query ID

Response 200 — Saved query details

  • category string,null
  • created_at stringrequired
  • description stringrequired
  • has_aggregation boolean,null
  • has_group_by boolean,null
  • has_join boolean,null
  • has_limit boolean,null
  • has_order_by boolean,null
  • has_predicate boolean,null
  • id stringrequired
  • latest_version integerrequired
  • name stringrequired
  • num_tables integer,null
  • sql stringrequired
  • sql_hash stringrequired
  • table_size string,null
  • tags string[] — required
  • updated_at stringrequired
{
  "category": "string",
  "created_at": "2026-01-01T00:00:00Z",
  "description": "string",
  "has_aggregation": true,
  "has_group_by": true,
  "has_join": true,
  "has_limit": true,
  "has_order_by": true,
  "has_predicate": true,
  "id": "string",
  "latest_version": 0,
  "name": "string",
  "num_tables": 0,
  "sql": "string",
  "sql_hash": "string",
  "table_size": "string",
  "tags": [
    "string"
  ],
  "updated_at": "2026-01-01T00:00:00Z"
}

Errors

StatusDescription
404Saved query not found

Update saved query

PUT/v1/queries/{id}

Update a saved query. If the SQL changes, a new version is created (previous versions are preserved). Name, tags, description, and classification overrides can also be updated.

Path parameters

  • id stringrequired. Saved query ID

Request body

  • category_override string,null — Override the auto-detected category. Send null to clear (revert to auto).
  • description string,null
  • name string,null — Optional new name. When omitted the existing name is preserved.
  • sql string,null — Optional new SQL. When omitted the existing SQL is preserved.
  • table_size_override string,null — User annotation for table size. Send null to clear.
  • tags string[] | null

All fields are optional. Send only the ones you want to set.

Response 200 — Saved query updated

  • category string,null
  • created_at stringrequired
  • description stringrequired
  • has_aggregation boolean,null
  • has_group_by boolean,null
  • has_join boolean,null
  • has_limit boolean,null
  • has_order_by boolean,null
  • has_predicate boolean,null
  • id stringrequired
  • latest_version integerrequired
  • name stringrequired
  • num_tables integer,null
  • sql stringrequired
  • sql_hash stringrequired
  • table_size string,null
  • tags string[] — required
  • updated_at stringrequired
{
  "category": "string",
  "created_at": "2026-01-01T00:00:00Z",
  "description": "string",
  "has_aggregation": true,
  "has_group_by": true,
  "has_join": true,
  "has_limit": true,
  "has_order_by": true,
  "has_predicate": true,
  "id": "string",
  "latest_version": 0,
  "name": "string",
  "num_tables": 0,
  "sql": "string",
  "sql_hash": "string",
  "table_size": "string",
  "tags": [
    "string"
  ],
  "updated_at": "2026-01-01T00:00:00Z"
}

Errors

StatusDescription
400Invalid request
404Saved query not found

Delete saved query

DELETE/v1/queries/{id}

Path parameters

  • id stringrequired. Saved query ID

Response 204 — Saved query deleted

Errors

StatusDescription
404Saved query not found

Execute saved query

POST/v1/queries/{id}/execute

Execute a saved query, scoped to a database (required X-Database-Id header). By default runs the latest version. Optionally specify a version number to execute a previous version. The SQL runs inside the given database scope, the same way POST /v1/query does. Returns the same response format as POST /v1/query.

Path parameters

  • id stringrequired. Saved query ID

Headers

  • X-Database-Id stringrequired. Required. Scope execution to this database (its id). A missing or malformed value is a 400; an unknown database id is a 404.

Request body

  • version integer,null

All fields are optional. Send only the ones you want to set.

Response 200 — Query executed

  • columns string[] — required
  • execution_time_ms integerrequired. Min: 0
  • nullable boolean[] — required. Nullable flags for each column (parallel to columns vec). True if the column allows NULL values, false if NOT NULL.
  • preview_row_count integerrequired. Number of rows in this response body. Always present. For a large result this is a bounded preview, not the grand total — see total_row_count and truncated.
  • query_run_id stringrequired. Unique identifier for the query run record (qrun...).
  • result_id string,null — Unique identifier for retrieving this result via GET /results/{id}. When non-null, the result is being persisted asynchronously. Null only when the result fit entirely in this response (truncated: false) but could not be persisted for later retrieval — see the warning field. A truncated: true response ALWAYS carries a non-null, resolvable result_id: a truncated result that cannot be persisted fails the request with a retryable HTTP 503 (PERSISTENCE_UNAVAILABLE, with a Retry-After header) rather than returning a partial body with a dead ticket.
  • row_count integerrequired. Deprecated — use preview_row_count (rows in this body) and total_row_count (grand total) instead. Retained as a back-compat alias and always equal to preview_row_count; for a truncated result it is the preview count, not the grand total — read total_row_count for that. Will be removed in a future release once clients migrate. Min: 0
  • rows any[][] — required. Array of rows, where each row is an array of column values. Values can be strings, numbers, booleans, or null.
  • total_row_count integer,null — Grand total rows in the full result. Present (and equal to preview_row_count) when the whole result fit in this response; null while a truncated result is still being persisted. When null, read the authoritative total from GET /v1/query-runs/{id} (row_count) or the X-Total-Row-Count header on GET /v1/results/{id}.
  • truncated booleanrequired. True when rows is a bounded preview of a larger result. Fetch the full result via result_id.
  • warning string,null — Warning message if result persistence could not be initiated. Present only when the full result is returned inline (truncated: false) but could not be persisted: result_id is then null and the result cannot be re-fetched later, though every row is in this response. A truncated result never carries a warning — if it cannot be persisted the request fails with a retryable HTTP 503 (PERSISTENCE_UNAVAILABLE, with a Retry-After header) instead.
{
  "columns": [
    "string"
  ],
  "execution_time_ms": 0,
  "nullable": [
    true
  ],
  "preview_row_count": 0,
  "query_run_id": "string",
  "result_id": "string",
  "row_count": 0,
  "rows": [
    [
      null
    ]
  ],
  "total_row_count": 0,
  "truncated": true,
  "warning": "string"
}

Errors

StatusDescription
400Invalid request (including a missing X-Database-Id header)
404Saved query or database not found

List saved query versions

GET/v1/queries/{id}/versions

Path parameters

  • id stringrequired. Saved query ID

Query parameters

  • limit integer — Maximum number of versions
  • offset integer — Pagination offset

Response 200 — List of versions

  • count integerrequired. Min: 0
  • has_more booleanrequired
  • limit integerrequired. Min: 0
  • offset integerrequired. Min: 0
  • saved_query_id stringrequired
  • versions SavedQueryVersionInfo[] — required
    • category string,null
    • created_at stringrequired
    • has_aggregation boolean,null
    • has_group_by boolean,null
    • has_join boolean,null
    • has_limit boolean,null
    • has_order_by boolean,null
    • has_predicate boolean,null
    • num_tables integer,null
    • sql stringrequired
    • sql_hash stringrequired
    • table_size string,null
    • version integerrequired
{
  "count": 0,
  "has_more": true,
  "limit": 0,
  "offset": 0,
  "saved_query_id": "string",
  "versions": [
    {
      "category": "string",
      "created_at": "2026-01-01T00:00:00Z",
      "has_aggregation": true,
      "has_group_by": true,
      "has_join": true,
      "has_limit": true,
      "has_order_by": true,
      "has_predicate": true,
      "num_tables": 0,
      "sql": "string",
      "sql_hash": "string",
      "table_size": "string",
      "version": 0
    }
  ]
}

Errors

StatusDescription
404Saved query not found