Berserk Docs

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.

EndpointResponse
POST /v1/rest/queryKusto v1: every table in one JSON object
POST /v2/rest/queryKusto 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

EndpointPOST /v1/rest/query
Content-Typeapplication/json

Request

FieldTypeRequiredDescription
dbstringyesDatabase name
cslstringyesKQL query
propertiesobjectnoKusto 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"
    }
  }
}
OptionDescription
query_datetimescope_columnMust be timestamp
query_datetimescope_fromInclusive start, ISO 8601
query_datetimescope_toExclusive 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:

StatusCause
401 with WWW-Authenticate: BearerNo bearer token
401 with WWW-Authenticate: Bearer error="invalid_token"The token is malformed, unknown or expired
401The 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 CodeMeaning
200Success
400Query syntax or analysis error, invalid request properties, or no db
401Missing or invalid bearer token
404The database does not exist
500Internal server error

On this page