Our engine never sees your warehouse password
datahashi

Getting started

Connect your warehouse, publish a model, and query it over REST, MCP, and SQL wire.

Updated

You can run datahashi in the hosted cloud or as the community engine. Both use the same query pipeline. Both reach your warehouse through Query Runner. The engine never opens your warehouse.

Option A: datahashi Cloud

The hosted console gives you a web workspace. You author YAML in Studio. You can also use Model Vibe. The console manages members and rollup schedules.

flowchart LR
    C["Console<br/>(Studio)"] --> CP["Control Plane<br/>hashi-api"] --> E["Hosted Engine<br/>Engine Cloud"]
    E -->|"HTTP SQL"| QR["Query Runner"]
    QR -->|"native driver"| W[("Warehouse")]
  1. Sign in to the console. The console creates your workspace.
  2. Install Query Runner on a host near your warehouse.
  3. Set the read-only warehouse password in the runner config.
  4. In the console, add a Connection. Enter the runner URL and the runner key.
  5. Author the model in Studio. Declare entities, dimensions, measures, and metrics.
  6. Apply the draft. The engine validates syntax.
  7. Publish the draft. The engine stores an immutable version.
  8. Issue a credential for REST, MCP, or SQL wire.
  9. Run a query. Confirm that all three surfaces return the same figure.

Use the names from Write your first model. Put Measures in measures. Put Metrics in metrics.

curl "$ENGINE_URL/v1/query" \
  -H "Authorization: Bearer $DATAHASHI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "measures": ["Order.revenue"],
    "metrics": ["avg_order_value"],
    "dimensions": ["Customer.region"]
  }'

Option B: Self-host the community engine

The binary in this example is the headless engine (hashi-engine). It reads YAML from a folder. It has no control plane and no database. The community binary hashi adds a console and a SQLite store.

flowchart TD
    E["hashi-engine<br/>reads model.yaml, warehouse.yaml, policy.yaml, auth.yaml"] -->|"loopback HTTP or private network"| QR["query-runner<br/>reads config.yaml (holds the warehouse password)"]
    QR -->|"native driver"| W[("Warehouse")]

Start the quickstart

Clone the hashi repository and start its quickstart. The published image is ghcr.io/datahashi/hashi. This compose file builds that same quickstart from the checkout.

git clone https://github.com/datahashi/hashi
cd hashi
docker compose up -d --build --wait
python3 examples/quickstart/smoke.py

Query port 8081. The key is quickstart-api-key-change-me. The quickstart model spells the entities order and customer. A Measure ref is case-sensitive.

curl -X POST http://localhost:8081/v1/query \
  -H "Authorization: Bearer quickstart-api-key-change-me" \
  -H "Content-Type: application/json" \
  -d '{
    "measures": ["order.revenue"],
    "metrics": ["avg_order_value"],
    "dimensions": ["customer.region"]
  }'

The body names each cell. Order is the dimension, then the metric, then the measure. Whole amounts are JSON integers. The US West average is the full quotient 116.66666666666667, not 116.67.

{
  "columns": [
    {"name": "region", "type": "string", "kind": "dimension"},
    {"name": "avg_order_value", "type": "float", "kind": "metric"},
    {"name": "revenue", "type": "decimal", "kind": "measure"}
  ],
  "rows": [
    ["eu", 150, 150],
    ["us-west", 116.66666666666667, 350]
  ],
  "row_count": 2,
  "truncated": false
}

SQL wire and TLS wait until after this first run. See PostgreSQL wire protocol.

Next: