Query HTTP API
Kusto-compatible REST endpoints for running KQL over HTTP, through the gateway
The gateway serves the Kusto REST query endpoints at its root. Tools that speak the Azure Data Explorer REST protocol (the Grafana datasource, Kusto SDKs, scripts) send their queries there.
| Endpoint | Response |
|---|---|
POST /v1/rest/query | Kusto v1: every table in one JSON object |
POST /v2/rest/query | Kusto v2 frames, batch or progressive. See HTTP REST Protocol (ADX v2) |
Authentication
Every request carries a bearer token: a CLI access token from bzrk login, or a service account's token for scripts and integrations. The gateway checks the token and forwards the request to the query service. The query service answers only requests the gateway forwarded, so these endpoints are not reachable on a query pod directly.
curl -X POST https://<gateway>/v1/rest/query \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"db": "default", "csl": "my_table | take 10"}'Kusto v1 Endpoint
| Endpoint | POST /v1/rest/query |
| Content-Type | application/json |
Request
| Field | Type | Required | Description |
|---|---|---|---|
db | string | yes | Database name |
csl | string | yes | KQL query |
properties | object | no | Kusto request properties. See Time Range |
Response
{
"Tables": [
{
"TableName": "Table_0",
"Columns": [
{ "ColumnName": "timestamp", "DataType": "datetime", "ColumnType": "datetime" },
{ "ColumnName": "message", "DataType": "string", "ColumnType": "string" }
],
"Rows": [
["2026-03-12T10:00:00Z", "hello world"]
]
}
]
}When some segments could not be read, the response ends with an extra @PartialFailures table. Its columns are Message and SegmentCount, one row per failure. The rows in the other tables are then incomplete.
Time Range
Both endpoints accept the Kusto query_datetimescope_* options in properties.Options (or properties.options). Set all three to scope the query to [from, to) on the server:
{
"db": "default",
"csl": "my_table | summarize count() by bin(timestamp, 1m)",
"properties": {
"Options": {
"query_datetimescope_column": "timestamp",
"query_datetimescope_from": "2026-03-12T10:00:00Z",
"query_datetimescope_to": "2026-03-12T11:00:00Z"
}
}
}| Option | Description |
|---|---|
query_datetimescope_column | Must be timestamp |
query_datetimescope_from | Inclusive start, ISO 8601 |
query_datetimescope_to | Exclusive end, ISO 8601 |
Setting only some of the three, or another column, is a 400. Without them, the query's own filters bound it, e.g. where timestamp > ago(1h).
Error Handling
The gateway rejects a request it cannot authenticate before it reaches the query service:
| Status | Cause |
|---|---|
401 with WWW-Authenticate: Bearer | No bearer token |
401 with WWW-Authenticate: Bearer error="invalid_token" | The token is malformed, unknown or expired |
401 | The account the token belongs to is disabled |
A query that fails (parse, bind or execution error) returns a JSON problem body:
{
"type": "https://api.bzrk.dev/problems/query-error",
"message": "Unknown table 'foo'",
"code": "UnknownTable",
"error_details": {}
}A missing or unknown database uses the Kusto error envelope, with the HTTP status repeated in the body:
{
"error": {
"code": "DatabaseNotFound",
"message": "database 'nope' not found",
"@type": "BzrkClient/v1"
},
"status": 404
}| Status Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Query syntax or analysis error, invalid request properties, or no db |
| 401 | Missing or invalid bearer token |
| 404 | The database does not exist |
| 500 | Internal server error |