{
  "openapi": "3.1.0",
  "info": {
    "title": "FactQL API",
    "version": "1.0.0",
    "description": "The endpoints covered by the FactQL docs."
  },
  "servers": [
    {
      "url": "https://api.factql.ai"
    }
  ],
  "paths": {
    "/query": {
      "post": {
        "tags": [
          "Core Query Engine"
        ],
        "summary": "Query Endpoint",
        "description": "B2B query endpoint — authenticate via X-API-Key header.\n\nDelegates to the existing orchestrator. Same response shape as\n/clients/{id}/ask.",
        "operationId": "query_endpoint_query_post",
        "parameters": [
          {
            "name": "X-API-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "X-Tenant-ID",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Tenant-Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryApiRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Same agent envelope as /clients/{client_id}/ask. An envelope with an ``error`` key is collapsed to {error, error_type} before it is returned.",
            "content": {
              "application/json": {
                "schema": {},
                "examples": {
                  "text2sql_success": {
                    "summary": "text2sql — rows returned inline",
                    "value": {
                      "type": "text2sql",
                      "result": "success",
                      "sql": "SELECT month, SUM(revenue) AS revenue FROM monthly_revenue WHERE month >= '2026-06-01' GROUP BY month ORDER BY month",
                      "data": {
                        "columns": [
                          "month",
                          "revenue"
                        ],
                        "rows": [
                          [
                            "2026-06-01",
                            184320.5
                          ],
                          [
                            "2026-07-01",
                            201880
                          ],
                          [
                            "2026-08-01",
                            196410.25
                          ]
                        ]
                      },
                      "explanation": "2026-06-01: **184,320.50** · 2026-07-01: **201,880** · 2026-08-01: **196,410.25**",
                      "lineage": {
                        "tables": [
                          "monthly_revenue"
                        ],
                        "measures": [
                          "SUM(revenue)"
                        ],
                        "period": "month >= '2026-06-01'",
                        "filters": [],
                        "grouped_by": [
                          "month"
                        ],
                        "text": "Computed SUM(revenue); from monthly_revenue; for the period where month >= '2026-06-01'; broken down by month."
                      },
                      "verification": {
                        "status": "verified",
                        "metrics": [
                          "Net Revenue"
                        ],
                        "reason": "Computed using the certified definition(s): Net Revenue"
                      },
                      "model_used": "claude-sonnet-4-5",
                      "fallback_triggered": false,
                      "fallback_reason": "",
                      "attempts": 1,
                      "complexity": "easy",
                      "agent": "Text2SQL",
                      "trace_id": "8c1d9a52-4f0b-4c77-9a3e-1b2c3d4e5f60"
                    }
                  },
                  "sanitized_error": {
                    "summary": "any agent error, flattened by the API-key surface",
                    "value": {
                      "error": "Invalid or unsafe SQL generated",
                      "error_type": "QUERY_ERROR"
                    }
                  },
                  "budget_alerts_attached": {
                    "summary": "non-blocking budget threshold alerts ride on the envelope",
                    "value": {
                      "type": "text2sql",
                      "result": "success",
                      "sql": "SELECT month, SUM(revenue) AS revenue FROM monthly_revenue WHERE month >= '2026-06-01' GROUP BY month ORDER BY month",
                      "data": {
                        "columns": [
                          "month",
                          "revenue"
                        ],
                        "rows": [
                          [
                            "2026-06-01",
                            184320.5
                          ],
                          [
                            "2026-07-01",
                            201880
                          ],
                          [
                            "2026-08-01",
                            196410.25
                          ]
                        ]
                      },
                      "explanation": "2026-06-01: **184,320.50** · 2026-07-01: **201,880** · 2026-08-01: **196,410.25**",
                      "lineage": {
                        "tables": [
                          "monthly_revenue"
                        ],
                        "measures": [
                          "SUM(revenue)"
                        ],
                        "period": "month >= '2026-06-01'",
                        "filters": [],
                        "grouped_by": [
                          "month"
                        ],
                        "text": "Computed SUM(revenue); from monthly_revenue; for the period where month >= '2026-06-01'; broken down by month."
                      },
                      "verification": {
                        "status": "verified",
                        "metrics": [
                          "Net Revenue"
                        ],
                        "reason": "Computed using the certified definition(s): Net Revenue"
                      },
                      "model_used": "claude-sonnet-4-5",
                      "fallback_triggered": false,
                      "fallback_reason": "",
                      "attempts": 1,
                      "complexity": "easy",
                      "agent": "Text2SQL",
                      "trace_id": "8c1d9a52-4f0b-4c77-9a3e-1b2c3d4e5f60",
                      "budget_alerts": [
                        {
                          "scope_type": "tenant",
                          "scope_id": "acme",
                          "cap": 500,
                          "spent": 431.207714,
                          "pct_used": 0.862415,
                          "level": "warn80",
                          "enforcement": "alert"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The X-API-Key header did not resolve to an account.",
            "content": {
              "application/json": {
                "example": {
                  "detail": "Invalid or revoked API key"
                }
              }
            }
          },
          "402": {
            "description": "A budget with enforcement='block' is at or over its cap (ENABLE_BUDGETS).",
            "content": {
              "application/json": {
                "example": {
                  "detail": {
                    "error": "budget_exceeded",
                    "message": "This workspace has reached its budget. Contact your admin to raise it.",
                    "blocking_scope": {
                      "scope_type": "workspace",
                      "scope_id": "9f1c2f7e-0d64-4a1e-9b6c-5c3a2e8d1b40",
                      "cap": 250,
                      "spent": 251.418302,
                      "pct_used": 1.005673
                    },
                    "alerts": [
                      {
                        "scope_type": "workspace",
                        "scope_id": "9f1c2f7e-0d64-4a1e-9b6c-5c3a2e8d1b40",
                        "cap": 250,
                        "spent": 251.418302,
                        "pct_used": 1.005673,
                        "level": "over100",
                        "enforcement": "block"
                      }
                    ]
                  }
                }
              }
            }
          },
          "403": {
            "description": "Direct accounts have no API access, or the key is scoped to another tenant.",
            "content": {
              "application/json": {
                "examples": {
                  "direct_account": {
                    "value": {
                      "detail": "Direct accounts must use the UI"
                    }
                  },
                  "wrong_tenant": {
                    "value": {
                      "detail": "API key is scoped to a different tenant"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "The resolved client has no database configured yet.",
            "content": {
              "application/json": {
                "example": {
                  "detail": "Client has no database configured. Call PUT /accounts/clients/{client_id}/database first."
                }
              }
            }
          },
          "429": {
            "description": "The account's plan quota for the period is exhausted.",
            "content": {
              "application/json": {
                "example": {
                  "detail": {
                    "error": "quota_exceeded",
                    "plan": "free",
                    "limit": 1000
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/whoami": {
      "get": {
        "tags": [
          "Developer"
        ],
        "summary": "Describe the API key in use",
        "description": "What this key is and where it points: tenant, bound workspace, plan.",
        "operationId": "whoami_whoami_get",
        "parameters": [
          {
            "name": "X-API-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Whoami Whoami Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sample": {
      "get": {
        "tags": [
          "Developer"
        ],
        "summary": "Sample data for Try it",
        "description": "The public sample-data key, its IDs and suggested questions.",
        "operationId": "sample_sample_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Sample Sample Get"
                }
              }
            }
          }
        }
      }
    },
    "/clients/{client_id}/ask/stream": {
      "post": {
        "tags": [
          "Core Query Engine"
        ],
        "summary": "Ask Question Stream",
        "description": "Streaming variant of the /ask endpoint using Server-Sent Events (SSE).\n\nReturns a stream of events as the query is processed:\n- **status**      – progress updates (routing, agent_selected, executing …)\n- **thinking**    – token-by-token LLM output\n- **sql**         – generated SQL (text2sql agent)\n- **result**      – query result rows / columns\n- **explanation** – human-readable summary\n- **done**        – final event with agent name and duration_ms\n- **error**       – if something goes wrong at any stage",
        "operationId": "ask_question_stream_clients__client_id__ask_stream_post",
        "security": [
          {
            "HTTPBearer": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Client Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QueryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Server-Sent Events. Errors (including the budget block) arrive as an ``error`` EVENT on a 200 stream, not as an HTTP status. Note that text2sql emits its own ``done`` and the route then appends a second, richer ``done``.",
            "content": {
              "application/json": {
                "schema": {}
              },
              "text/event-stream": {
                "examples": {
                  "text2sql_success": {
                    "summary": "session → status → thinking → sql → result → explanation → done",
                    "value": "event: session\ndata: {\"session_id\": \"3f7b1c40-2a55-4f9e-8d21-0a6f4b9c1d33\"}\n\nevent: status\ndata: {\"stage\": \"building_context\", \"message\": \"Gathering schema and history...\"}\n\nevent: status\ndata: {\"stage\": \"routing\", \"message\": \"Analyzing query...\", \"trace_id\": \"8c1d9a52-4f0b-4c77-9a3e-1b2c3d4e5f60\"}\n\nevent: status\ndata: {\"stage\": \"agent_selected\", \"agent\": \"text2sql\", \"trace_id\": \"8c1d9a52-4f0b-4c77-9a3e-1b2c3d4e5f60\"}\n\nevent: status\ndata: {\"stage\": \"generating_sql\", \"message\": \"Generating SQL...\"}\n\nevent: thinking\ndata: {\"content\": \"Revenue grew\"}\n\nevent: thinking\ndata: {\"content\": \" 6.6% since June.\"}\n\nevent: sql\ndata: {\"sql\": \"SELECT month, SUM(revenue) AS revenue FROM monthly_revenue WHERE month >= '2026-06-01' GROUP BY month ORDER BY month\"}\n\nevent: status\ndata: {\"stage\": \"executing\", \"message\": \"Running query...\"}\n\nevent: result\ndata: {\"columns\": [\"month\", \"revenue\"], \"rows\": [[\"2026-06-01\", 184320.5], [\"2026-07-01\", 201880.0], [\"2026-08-01\", 196410.25]], \"total_rows\": 3, \"truncated\": false, \"lineage\": {\"tables\": [\"monthly_revenue\"], \"measures\": [\"SUM(revenue)\"], \"period\": \"month >= '2026-06-01'\", \"filters\": [], \"grouped_by\": [\"month\"], \"row_limit\": null, \"text\": \"Computed SUM(revenue); from monthly_revenue; for the period where month >= '2026-06-01'; broken down by month.\"}}\n\nevent: explanation\ndata: {\"text\": \"2026-06-01: **184,320.50** \\u00b7 2026-07-01: **201,880** \\u00b7 2026-08-01: **196,410.25**\"}\n\nevent: done\ndata: {\"agent\": \"text2sql\"}\n\nevent: done\ndata: {\"agent\": \"text2sql\", \"duration_ms\": 4210, \"session_id\": \"3f7b1c40-2a55-4f9e-8d21-0a6f4b9c1d33\", \"output_mode\": \"both\"}\n\n"
                  },
                  "large_dataset": {
                    "summary": "truncated result event + result_token mirrored onto done",
                    "value": "event: result\ndata: {\"columns\": [\"order_id\", \"product_name\", \"order_total\"], \"rows\": [[10001, \"Widget A\", 129.99], [10002, \"Widget B\", 89.5], [10003, \"Gadget C\", 415.0]], \"total_rows\": 1284, \"truncated\": true, \"result_token\": \"eyJzcWwiOiJTRUxFQ1QgLi4uIn0.ZmFrZVNpZ25hdHVyZQ\"}\n\nevent: explanation\ndata: {\"text\": \"Query returned 1284 rows. Showing first 10 rows. Full results available via export.\"}\n\nevent: done\ndata: {\"agent\": \"text2sql\", \"duration_ms\": 6180, \"output_mode\": \"both\", \"result_token\": \"eyJzcWwiOiJTRUxFQ1QgLi4uIn0.ZmFrZVNpZ25hdHVyZQ\", \"total_rows\": 1284, \"sql\": \"SELECT order_id, product_name, order_total FROM orders\"}\n\n"
                  },
                  "decline": {
                    "summary": "error event, stream closes",
                    "value": "event: status\ndata: {\"stage\": \"agent_selected\", \"agent\": \"text2sql\"}\n\nevent: error\ndata: {\"message\": \"Invalid or unsafe SQL generated\", \"kind\": \"decline\", \"decline_reason\": \"no_safe_sql\", \"suggestions\": [{\"raw\": \"prodcts\", \"resolved\": \"products\"}], \"hint\": \"Did you mean: products?\"}\n\n"
                  },
                  "budget_blocked": {
                    "summary": "error(status=402) + done(budget_blocked)",
                    "value": "event: error\ndata: {\"error\": \"budget_exceeded\", \"status\": 402, \"message\": \"This workspace has reached its budget. Contact your admin to raise it.\", \"blocking_scope\": {\"scope_type\": \"workspace\", \"scope_id\": \"9f1c2f7e-0d64-4a1e-9b6c-5c3a2e8d1b40\", \"cap\": 250.0, \"spent\": 251.418302, \"pct_used\": 1.005673}, \"alerts\": []}\n\nevent: done\ndata: {\"agent\": \"none\", \"duration_ms\": 12, \"budget_blocked\": true}\n\n"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The JWT's client_id does not match the path client_id.",
            "content": {
              "application/json": {
                "example": {
                  "detail": "Access denied to this client"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/clients/{client_id}/workspaces/{workspace_id}/files": {
      "get": {
        "tags": [
          "File Data Sources"
        ],
        "summary": "List Files",
        "description": "The workspace's file manifest — what was uploaded and what it produced.",
        "operationId": "list_files_clients__client_id__workspaces__workspace_id__files_get",
        "security": [
          {
            "HTTPBearer": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Client Id"
            }
          },
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Workspace Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "File Data Sources"
        ],
        "summary": "Commit File",
        "description": "Step 2 (synchronous): ingest the upload and configure the workspace.\n\nFine for small files. A large workbook takes 50-100s and will be cut off\nby a proxy timeout long before it finishes — use the ``/files/async``\nendpoint for anything non-trivial.",
        "operationId": "commit_file_clients__client_id__workspaces__workspace_id__files_post",
        "security": [
          {
            "HTTPBearer": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Client Id"
            }
          },
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Workspace Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_commit_file_clients__client_id__workspaces__workspace_id__files_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The commit manifest. A re-upload of identical bytes under the same filename is a no-op (``unchanged: true``) unless ``force=true``; new bytes bump ``version`` and atomically rebuild that file's tables.",
            "content": {
              "application/json": {
                "schema": {},
                "examples": {
                  "ingested": {
                    "summary": "first ingest of this filename",
                    "value": {
                      "filename": "acme-revenue-2026.xlsx",
                      "version": 1,
                      "tables": [
                        {
                          "table_name": "monthly_revenue",
                          "sheet_name": "Monthly Revenue",
                          "row_count": 36,
                          "column_count": 2
                        },
                        {
                          "table_name": "products",
                          "sheet_name": "Products",
                          "row_count": 118,
                          "column_count": 2
                        }
                      ],
                      "sha256": "4f2b9c1d8e7a6053b1c4d2e9f8a7b6c504132a9b8c7d6e5f40312a9b8c7d6e5f",
                      "unchanged": false
                    }
                  },
                  "unchanged": {
                    "summary": "identical content — nothing was written",
                    "value": {
                      "filename": "acme-revenue-2026.xlsx",
                      "version": 1,
                      "tables": [
                        {
                          "table_name": "monthly_revenue",
                          "sheet_name": "Monthly Revenue",
                          "row_count": 36,
                          "column_count": 2
                        }
                      ],
                      "sha256": "4f2b9c1d8e7a6053b1c4d2e9f8a7b6c504132a9b8c7d6e5f40312a9b8c7d6e5f",
                      "unchanged": true,
                      "message": "Identical content is already ingested for this filename. Pass force=true to re-ingest anyway."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unparseable workbook or malformed mapping.",
            "content": {
              "application/json": {
                "example": {
                  "detail": "No ingestable data found — every sheet was empty or skipped."
                }
              }
            }
          },
          "404": {
            "description": "The feature flag gating this endpoint is off. The path still appears in /openapi.json — check the running container's env.",
            "content": {
              "application/json": {
                "example": {
                  "detail": "Not found"
                }
              }
            }
          },
          "409": {
            "description": "Either a proposed table is owned by another file (_collision_http_error, — ``force`` deliberately does NOT override this) or the workspace already has a native/gateway source (_assert_source_compatible, :186).",
            "content": {
              "application/json": {
                "examples": {
                  "table_collision": {
                    "value": {
                      "detail": {
                        "error": "table_name_collision",
                        "message": "1 table name(s) from 'acme-revenue-2026.xlsx' are already owned by 'acme-catalogue.xlsx': products. Ingesting would overwrite that file's data. Rename these tables via the mapping (table_name), skip the sheets, or delete the other file first.",
                        "collisions": [
                          {
                            "table_name": "products",
                            "owned_by": "acme-catalogue.xlsx"
                          }
                        ]
                      }
                    }
                  },
                  "wrong_source_type": {
                    "value": {
                      "detail": "This workspace already has its own database configured (source type 'native'). Remove that configuration first, or use a different workspace for file uploads."
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/clients/{client_id}/workspaces/{workspace_id}/files/{file_id}": {
      "delete": {
        "tags": [
          "File Data Sources"
        ],
        "summary": "Delete File",
        "description": "Remove one uploaded file: drops its tables from the workspace DuckDB\nand deletes the stored original. Removing the last file clears the\nworkspace's file-source configuration.",
        "operationId": "delete_file_clients__client_id__workspaces__workspace_id__files__file_id__delete",
        "security": [
          {
            "HTTPBearer": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Client Id"
            }
          },
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Workspace Id"
            }
          },
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "File Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/clients/{client_id}/schema/status": {
      "get": {
        "tags": [
          "Schema & Tables"
        ],
        "summary": "Get Client Schema Status",
        "description": "Check the auto-discovery status for your company's database schema.\n\nWhen an OWN-DB ``workspace_id`` is active, reports that workspace's own\ndiscovery/enrichment status (migration 0030) instead of the tenant's.",
        "operationId": "get_client_schema_status_clients__client_id__schema_status_get",
        "security": [
          {
            "HTTPBearer": []
          },
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Client Id"
            }
          },
          {
            "name": "workspace_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Workspace Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Body_commit_file_clients__client_id__workspaces__workspace_id__files_post": {
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "title": "File"
          },
          "mapping": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mapping"
          },
          "force": {
            "type": "boolean",
            "title": "Force",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "file"
        ],
        "title": "Body_commit_file_clients__client_id__workspaces__workspace_id__files_post"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "QueryApiRequest": {
        "properties": {
          "q": {
            "type": "string",
            "maxLength": 4096,
            "minLength": 1,
            "title": "Q"
          },
          "stream": {
            "type": "boolean",
            "title": "Stream",
            "default": false
          },
          "dry_run": {
            "type": "boolean",
            "title": "Dry Run",
            "default": false
          },
          "workspace_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64
              },
              {
                "type": "null"
              }
            ],
            "title": "Workspace Id"
          }
        },
        "type": "object",
        "required": [
          "q"
        ],
        "title": "QueryApiRequest"
      },
      "QueryRequest": {
        "properties": {
          "query": {
            "type": "string",
            "title": "Query"
          },
          "stream": {
            "type": "boolean",
            "title": "Stream",
            "default": false
          },
          "dry_run": {
            "type": "boolean",
            "title": "Dry Run",
            "default": false
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id"
          },
          "new_session": {
            "type": "boolean",
            "title": "New Session",
            "default": false
          },
          "workspace_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Workspace Id"
          },
          "sql_mode": {
            "type": "boolean",
            "title": "Sql Mode",
            "default": true
          },
          "data_mode": {
            "type": "boolean",
            "title": "Data Mode",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "query"
        ],
        "title": "QueryRequest"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    }
  },
  "security": [
    {
      "ApiKeyAuth": []
    }
  ]
}
