Governed SQL API and CLI reference
Use the Semantic Rails Python runtime to discover metrics, build and validate
semantic queries, compile governed SQL, and execute against your warehouse.
This reference covers the CLI and the HTTP routes served under
/api/v1/*.
Connecting an AI assistant? Start with the MCP client setup guide. For the order of tool calls, see the agent query workflow. Define the models, metrics, and policies these queries use with the semantic layer YAML reference.
CLI entrypoints
uv run semantic-rails packages uv run semantic-rails catalog --package jaffle_shop uv run semantic-rails discover --package jaffle_shop --terms store_name uv run semantic-rails inspect --package jaffle_shop --object-id measure.jaffle.order_count uv run semantic-rails build-options --package jaffle_shop --query-json '@query.json' --step group_by uv run semantic-rails valid-values --package jaffle_shop --dimension dimension.jaffle_store_name uv run semantic-rails plan --package jaffle_shop --intent "new customer orders over time" uv run semantic-rails validate --package jaffle_shop --query-json '@query.json' uv run semantic-rails compile --package jaffle_shop --query-json '@query.json' uv run semantic-rails query --package jaffle_shop --query-json '@query.json' --verbosity minimal --sql-profile off uv run semantic-rails segment-preview --package jaffle_shop --segment-id segment.jaffle.high_value_customers uv run semantic-rails serve --package jaffle_shop --port 8081 PACKAGE_PATH="$(pwd)/my_package" semantic-rails profile init --package-path "$PACKAGE_PATH" semantic-rails mcp setup --path "$PACKAGE_PATH" semantic-rails mcp status --path "$PACKAGE_PATH" semantic-rails mcp start --path "$PACKAGE_PATH" --port 8091 semantic-rails mcp stop --path "$PACKAGE_PATH" semantic-rails mcp setup --path "$PACKAGE_PATH" --client both --mcp both --install --yes uv run semantic-rails doctor --package jaffle_shop
HTTP routes
Use the /api/v1 prefix for integrations. Root paths and unversioned
/api/* paths are not public routes.
This table mirrors docs/QUERY_API.md, which is the canonical contract;
request/response shapes and error codes live there.
| Route | Purpose |
|---|---|
GET /api/v1/health |
Return service, package, schema, and warehouse metadata without warehouse I/O |
GET /api/v1/ready |
Return package readiness; protected deep checks can verify warehouse connectivity |
GET /api/v1/capabilities |
Return route index, supported API versions, aliases, warehouse capabilities, and package capabilities |
GET /api/v1/catalog or POST /api/v1/catalog |
Browse catalog metadata, public objects, value domains, and capability flags |
POST /api/v1/discover |
Rank semantic candidates from business terms; surfaces out_of_scope and low_relevance blocks inline |
POST /api/v1/inspect |
Inspect an object card with usage and compatible next moves |
POST /api/v1/build-options |
Get recommended, available, blocked, and patch-based builder choices |
POST /api/v1/valid-values |
Get valid categorical values for a dimension |
POST /api/v1/plan |
Produce validated best-query drafts and alternatives |
POST /api/v1/validate |
Validate a query without executing it |
POST /api/v1/compile |
Compile Query IR to rendered SQL and plan metadata without execution; the explain payload ships inside this response |
POST /api/v1/query |
Execute a validated query against the configured warehouse |
POST /api/v1/segment-validate |
Validate a package-authored segment membership query |
POST /api/v1/segment-explain |
Return planner and SQL details for a segment membership query |
POST /api/v1/segment-preview |
Preview membership rows for a package-authored segment |
Response envelope
Most routes return ok, status, api_version,
request_id, package_id, warnings,
errors, recovery_hints, and timing_ms
alongside route-specific payloads. Runtime calls may also include
request_context when trusted semantic context headers or
policy_context are supplied.
Request context and API key shim
Integrations can pass X-Request-ID, X-Semantic-Actor,
X-Semantic-Tenant, X-Semantic-Project,
X-Semantic-Roles, X-Semantic-Environment, and
X-Semantic-Audience. Header context wins over body context and is merged
into policy-aware routes. Set SEMANTIC_RAILS_API_KEYS or
SEMANTIC_RAILS_API_KEY_FILE to require bearer/API-key auth. This is a
runtime shim, not managed cloud tenant auth.
The local/customer-side runtime supports /api/v1/query. A hosted v0 service
should stay discovery-, validate-, and compile-first until warehouse execution is
productized separately.
Representative query shape
{
"query": {
"version": 1,
"select": [
{
"expression": { "measure": "measure.jaffle.revenue_usd" },
"as": "revenue_usd"
}
],
"group_by": ["dimension.jaffle_store_name"],
"time": {
"temporal_role": "temporal_role.jaffle_order_time",
"grain": "month"
},
"order_by": [{ "field": "revenue_usd", "direction": "DESC" }],
"limit": 5
}
}
Compile and explain metadata
POST /api/v1/compile returns rendered SQL plus semantic plan metadata.
At compact verbosity, detailed plans live under explain;
at full verbosity, physical_plan and
performance_plan are also top-level response fields.
When a package declares exact physical rollups through model.variants:
or explicit aggregate relations, the compile response shows whether a query routed to
a rollup:
logical_plan.measure_plans[].aggregate_relation_idphysical_plan.nodes[].details.selected_relation_typephysical_plan.nodes[].details.aggregate_relation_idperformance_plan.aggregate_routing.selected
Missing dimensions, unsupported time grains, non-exact equivalence, non-default sources, or unsupported rollups fall back to the raw relation.
Discovery-first request example
{
"query": {
"version": 1,
"select": [
{
"expression": { "measure": "measure.jaffle.revenue_usd" },
"as": "revenue_usd"
}
]
},
"focus_terms": "revenue by store",
"focus_object_id": "measure.jaffle.revenue_usd",
"step": "group_by",
"limit": 6
}
Error model
For the authoring-side root cause of each error and the field that typically triggers it, see the error code → root cause table in the Authoring Reference.
| Code | Meaning | Typical fix |
|---|---|---|
AMBIGUOUS_ALIAS |
Human token maps to multiple semantic objects | Use the returned candidates and pick a stable ID |
AMBIGUOUS_PATH |
Multiple non-equivalent join paths remain valid | Change the query shape or root so the planner has one safe path |
FANOUT_UNSAFE |
Requested expansion would smear the result | Choose a different grouping shape or supported rewrite |
DUPLICATE_OUTPUT_ALIAS |
Projected output names collide | Rename one of the projected aliases |
CONVERSION_NOT_SUPPORTED |
Conversion shape falls outside the supported event-count model | Use a supported conversion metric or split the ask into explicit legal queries |
PREDICATE_SCOPE_UNSAFE |
Predicate context would smear values across the outer query | Change the grouping, time grain, or predicate scope so the entity context is safe |
Recovery hint contracts
Errors ship structured recovery_hints so callers can repair the query without re-reading docs.
The contracts below are stable.
-
USE_OBJECT_SHAPE— emitted onINVALID_EXPRESSION_ASTwhen a rolling/conversionwindowor prior_periodoffsetis passed as an int instead of a{unit, value}object. -
drop_time_startthenwiden_time_window— emitted onWINDOWED_TIME_FILTER_UNSUPPORTEDin that order.drop_time_startis the always-safe first hint;widen_time_windowships a computedsuggested_start. -
USE_CANONICAL_KEY— emitted onINVALID_QUERYwhen an unknown top-level key is supplied. Maps common typos (filters→where,dimensions→group_by,having→metric_filters). -
MOVE_BOUNDS_TO_TIME_TOP_LEVEL— fires when absolute bounds are misplaced undertime.range: {start, end}instead of the top-leveltimeobject. -
MOVE_DIMENSION_TO_GROUP_BY— fires when a{dimension: "..."}is placed inselect[].expressionrather thangroup_by.
Warning codes
Non-fatal signals returned in the response warnings[] array.
-
UNGRAINED_TIME_PROJECTION—time.temporal_roleis set without agrain, nogroup_by, and no inline window expression. Recovery: set agrainor droptemporal_role. -
EXPRESSION_NORMALIZED_AWAY— the inputkinddid not survive normalization, or theas:alias is missing from the compiled output. Recovery: re-check the projection shape againstcompile's response. -
SEMANTIC_CAVEAT_APPLIED— package-authored advisory context matched the compiled query. Caveats do not change SQL, rows, access, discovery, or policy behavior; agents should use them only when interpreting affected results. -
SEMANTIC_CAVEATS_TRUNCATED— more advisory caveats matched than this verbosity returned.
discover -> inspect -> plan/build-options -> valid-values -> validate -> compile -> execute.
plan returns a validated draft, but it is still not a substitute for inspecting the governed objects.
Continue to Getting Started if you want the exact serve-and-query steps, or Guardrails for runtime limits.