Agents now connect to datahashi over OAuth — scoped tokens, no API keys to paste
datahashi
Open console
← Docs

Query the API

The Semantic Query object — metrics, dimensions, filters, grain — the response shape, the stable error codes, and the discovery endpoints.

Updated

Every consumer — REST, MCP, the console — sends the same object: a Semantic Query. It references one model and some combination of metrics/measures, dimensions, filters, ordering, and a row limit. Never SQL, never a raw table or column name.

Authenticate

Authorization: Bearer <your-api-key>

The token carries workspace identity and mode (governed or explore) only. The warehouse a query reaches, its row-level security, and its cost limits are all resolved server-side.

Run a query

curl "$ENGINE/v1/query" \
  -H "Authorization: Bearer $DATAHASHI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "metrics": ["avg_order_value"],
    "dimensions": ["Customer.region"],
    "filters": [{ "dimension": "Order.status", "op": "eq", "value": "completed" }],
    "order": ["Customer.region"],
    "limit": 100
  }'

Request fields

FieldNotes
modelOptional; the workspace’s default model if omitted
metricsGoverned selections; available in both modes
measuresRaw selections; explore mode only
dimensionsGroup-by, with optional grain on a time dimension
filters{ dimension, op, value }eq, ne, lt, le, gt, ge, in, not_in, contains, starts_with, ends_with, is_null
segmentsNamed filter fragments, ANDed with filters
viewOptional scoping to a curated model view
orderSort spec over the output columns
limitRow cap; also bounded by the workspace cost policy

Response shape

{
  "columns": ["region", "avg_order_value"],
  "annotation": [
    { "name": "region", "kind": "dimension", "type": "string" },
    { "name": "avg_order_value", "kind": "metric", "type": "number" }
  ],
  "rows": [
    ["na", 142.50],
    ["emea", 138.10]
  ]
}

Dimensions come first, then metrics and measures. An empty result serializes as "rows": [], not null.

Errors

Errors are { "error": { "code", "message" } } with a stable code:

HTTPCodeWhen
400bad_requestinvalid grain, filter operator, type mismatch, ambiguity, oversized body
401unauthenticatedmissing or invalid bearer token
403forbiddena governed token referenced raw measures
404not_foundunknown metric, measure, dimension, or model
429over_budgetthe query exceeds the workspace cost policy
503overloadedengine capacity exceeded
500internalan unexpected server error

Discovery

Three endpoints let a consumer learn the vocabulary before it queries:

  • GET /v1/models — the workspace’s semantic model names
  • GET /v1/catalog?model= — metrics, dimensions, and curated views (plus raw measures in explore mode)
  • GET /v1/describe?model=&name= — the definition and grain of one metric, dimension, or measure

All three take the same bearer token, and all three are also exposed as MCP tools.

Metering

Every query records what it scanned against the principal that asked. GET /v1/tenants/{id}/usage/summary?from=… returns the total over any window — one number, no per-warehouse billing archaeology.