Query the REST API
Run a Semantic Query, stream CSV, drill into a cell, and list dimension values over HTTP.
Updated
Every consumer sends a Semantic Query to the engine over HTTP. The engine compiles the query into SQL. It applies row-level security. Query Runner then runs the SQL.
Clients never write raw SQL. They never receive warehouse schema details.
Authenticate
Send your data-plane API key or JWT as a Bearer token:
Authorization: Bearer <your-datahashi-key>
The token is the caller. Grants on that caller decide which metrics and measures the query may name.
Run a Semantic Query (POST /v1/query)
curl "$ENGINE_URL/v1/query" \
-H "Authorization: Bearer $DATAHASHI_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": ["avg_order_value"],
"measures": ["Order.revenue"],
"dimensions": [
"Customer.region",
{ "name": "order_date", "entity": "Order", "grain": "month" }
],
"filters": [
{ "dimension": "status", "entity": "Order", "op": "eq", "value": "completed" }
],
"having": [
{ "ref": "revenue", "op": "gt", "value": 10000 }
],
"order": [
{ "ref": "revenue", "desc": true }
],
"limit": 100,
"offset": 0
}'
JSON response shape
{
"columns": [
{ "name": "region", "type": "string", "kind": "dimension" },
{ "name": "order_date", "type": "timestamp", "kind": "dimension" },
{ "name": "avg_order_value", "type": "float", "kind": "metric" },
{ "name": "revenue", "type": "decimal", "kind": "measure" }
],
"rows": [
["na", "2026-03-01T00:00:00Z", 142.5, 45200],
["emea", "2026-03-01T00:00:00Z", 138.1, 38100]
],
"row_count": 2,
"truncated": false,
"meta": {
"rollup": { "used": "monthly_order_summary" }
}
}
columns lines up with each row: dimensions, then metrics, then measures. type is int, float, decimal, string, bool, date, or timestamp. A metric is float. A sum measure is decimal. A count measure is int. There is no annotation array.
Whole amounts are JSON integers. A ratio is the full quotient, not a rounded decimal such as 142.50. The body also includes resolved.
Stream CSV
Add ?format=csv or send Accept: text/csv:
curl "$ENGINE_URL/v1/query?format=csv" \
-H "Authorization: Bearer $DATAHASHI_KEY" \
-H "Content-Type: application/json" \
-d '{
"measures": ["Order.revenue"],
"dimensions": ["Customer.region"]
}'
Output. The header is the column names. Cells use the same values as JSON, written as text.
region,revenue
na,45200
emea,38100
Drill into a cell (POST /v1/drill-down)
Drill-down turns one aggregated cell into the explore rows behind it. measure is a raw measure, never a metric.
curl "$ENGINE_URL/v1/drill-down" \
-H "Authorization: Bearer $DATAHASHI_KEY" \
-H "Content-Type: application/json" \
-d '{
"measure": "Order.revenue",
"cell": [
{ "dimension": "region", "entity": "Customer", "value": "emea" },
{ "dimension": "order_date", "entity": "Order", "grain": "month", "value": "2026-03-01" }
],
"limit": 50
}'
The engine turns the cell into an explore query. Time filters are half-open ([2026-03-01, 2026-04-01)).
List dimension values (POST /v1/dimension-values)
Fetch distinct values of a dimension from the warehouse. Use this for dropdowns or search:
curl "$ENGINE_URL/v1/dimension-values" \
-H "Authorization: Bearer $DATAHASHI_KEY" \
-H "Content-Type: application/json" \
-d '{
"entity": "Customer",
"dimension": "region",
"q": "em"
}'
Values follow the caller’s row-level security. q is a case-insensitive substring.
Discover the catalog (POST /v1/catalog)
Inspect granted metrics and dimensions:
curl "$ENGINE_URL/v1/catalog" \
-H "Authorization: Bearer $DATAHASHI_KEY" \
-H "Content-Type: application/json" \
-d '{}'
OpenAPI specification
Download the OpenAPI 3.1 specification from the running engine:
curl "$ENGINE_URL/v1/openapi.yaml"
Next: Connect an LLM agent · REST API.