Quickstart
Ingest a real dataset, publish a contract, and query it. Ten minutes end to end.
In ten minutes you'll go from raw CSVs to a governed contract a real application can call. We'll use the Jaffle Shop sample dataset (a fictional multi-location cafe chain) so every step has real data, real models, and real contracts behind it.
Assumes you have access to a Gaur workspace.
1. Get the sample dataset
Download and unpack the Jaffle Shop bundle:
# TODO: confirm hosted URL with the team before publishing
curl -L https://datasets.gaur.run/jaffle-shop-2026.tar.gz | tar -xz
cd jaffle-shop-2026Layout:
README.md
datasets/ raw_*.csv (~2.3M orders, ~3.5M items)
models/ 5 .sql files
contracts/ 5 .json files
business_context/ 19 .md descriptions
primary_keys.json
apikeys.jsonThe CSVs in datasets/ are the data. primary_keys.json tells you
which columns to declare as the primary key for each table. models/,
contracts/, and business_context/ cover everything the contracts
need.
A few conventions to know before you ingest:
- Money in raw tables is integer cents. The models convert to USD
(
subtotal_usd,order_total_usd). Don't divide by 100 in a measure; source the model instead. - Timestamps are naive local store wall-clock, not UTC. Don't convert.
raw_suppliesis a bill-of-materials with composite key(id, sku); thesku_costsmodel collapses it to one row persku.- Portland is correctly
tax_rate = 0.0. Oregon has no sales tax.
2. Ingest the six tables
Open the Ingestion area, pick the File upload connector, and
upload all six CSVs from datasets/ in one go (the connector supports
multi-file ingestion).
For each file, declare its primary key from primary_keys.json:
| File | Primary key | Rows |
|---|---|---|
raw_customers.csv | id | 7,836 |
raw_orders.csv | id | 2,294,909 |
raw_items.csv | id | 3,465,799 |
raw_products.csv | sku | 10 |
raw_stores.csv | id | 20 |
raw_supplies.csv | id, sku (composite) | 65 |
raw_supplies is the one with a composite key because the bill-of-materials
has one row per (supply, product). Get this right or contracts that join
into raw_supplies won't publish.
Gaur runs the ingestion as a background job and registers six tables when it's done. See File upload for the full reference.
3. Create the models
Five models sit between the raw tables and the contracts. Open the
Models area, paste each SQL file from models/, and declare its
primary key:
| Model | SQL file | Primary key |
|---|---|---|
orders_clean | models/orders_clean.sql | order_id |
products_clean | models/products_clean.sql | sku |
stores_enriched | models/stores_enriched.sql | store_id |
sku_costs | models/sku_costs.sql | sku |
customer_lifetime | models/customer_lifetime.sql | customer_id |
sku_costs is the most important one: it collapses the bill-of-materials
fan-out so contracts can join SKU cost data many-to-one without
inflating. See Models for the reasoning.
Wait until each model's state turns Active before creating contracts on top of it.
4. Add the contracts
The bundle has five ready-to-publish contracts. Start with the richest
one, contracts/product_performance.json. Open the Contracts area,
paste the JSON, and publish.
If everything in steps 2 and 3 is right, the contract publishes cleanly. If you get a validation error, it's almost always one of:
- A model isn't Active yet (wait for it).
- A primary key on a joined table or model isn't declared (re-check step 2 or 3).
- A composite key wasn't all referenced in a join's
on(re-check step 2 forraw_supplies).
Add the other four contracts the same way:
contracts/store_performance.json, contracts/customer_cohorts.json,
contracts/hourly_demand.json, contracts/sales_tax_remittance.json.
5. Attach context (optional but recommended)
The business_context/ folder has 19 markdown files describing each
table, model, contract, and the collection as a whole. For each object
in Gaur, paste the matching file's content as the object's description
and regenerate context. This is what makes the
chat and MCP answers
sharp. See Context.
You can skip this step if you only want REST access. Add context later when you're ready to point an AI surface at the data.
6. Publish a consumer
A consumer is the API endpoint that exposes
contracts. Create one named jaffle-public, enable the three protocols
(REST, Chat, MCP), and add all five contracts to its scope.
Create an API key for the consumer. Save the key; you'll only see it once.
7. Run your first query
Hit the REST endpoint with your key:
curl -s -X POST https://<base-url>/v1/api/jaffle-public/query \
-H "Authorization: Bearer gaur_***************" \
-H "Content-Type: application/json" \
-d '{
"contract_name": "product_performance",
"query": {
"dimensions": [{ "name": "category" }],
"measures": ["units_sold", "revenue_usd", "cogs_ratio"]
}
}'You'll get back two rows (one for jaffles, one for beverages) with units
sold, revenue, and the COGS ratio. Rows live at
data.pagination.items; see Pagination
for the full response shape.
Where to next
You now have an end-to-end working Gaur setup with real contracts.