Python SDK

Dataset endpoints

Request and response shapes, pagination, and discovery for Python dataset endpoints.

A dataset endpoint is a POST endpoint that runs semantic queries against one dataset through your dataset client (sync or async). Serve it at the conventional path with create_api(datasets=...), or at any path with add_dataset_endpoint:

from hypequery.serve import EndpointPolicy, add_dataset_endpoint, create_api, create_dataset_endpoint

policy = EndpointPolicy(tenant="required", max_limit=500)

# POST /datasets/orders/query
api = create_api(
    auth=authenticate,
    datasets={"orders": create_dataset_endpoint(dataset=orders, client=client, policy=policy)},
)

# or at a path of your choosing
add_dataset_endpoint(api, "/v1/orders", dataset=orders, client=client, policy=policy)

A metric endpoint fixes one measure: create_metric_endpoint(dataset=orders, measure="revenue", client=client), served with create_api(metrics={"revenue": ...}) at POST /metrics/revenue, or with add_metric_endpoint(api, path, ...).

Request body

{
  "dimensions": ["country"],
  "measures": ["revenue"],
  "filters": [{ "field": "status", "operator": "eq", "value": "completed" }],
  "orderBy": [{ "field": "revenue", "direction": "desc" }],
  "by": "month",
  "limit": 10,
  "offset": 0,
  "includeMeta": true
}

The body is validated strictly:

  • unknown fields are rejected with 400 VALIDATION_ERROR;
  • numbers and booleans are not coerced from strings;
  • attempts to supply a tenant, SQL, settings, roles, or scopes are refused.

Omitting measures selects the dataset's default measures; "measures": [] selects none. timezone (an IANA name) is also accepted.

An endpoint's policy says who may call it, not who may read the datasets its relationships reach. So fields from related datasets are off by default: customer.country, related measures, and named filters defined on a related field are refused with 400 VALIDATION_ERROR and left out of the client contract. Opt in per relationship when this endpoint's policy is enough to read the related data:

create_dataset_endpoint(dataset=orders, client=client, policy=policy, include_related={"customer"})

Response

{
  "data": [{ "country": "NZ", "revenue": "1200.5" }],
  "meta": {
    "requestId": "…",
    "timingMs": 12,
    "rowCount": 1,
    "pagination": { "limit": 10, "offset": 0, "hasMore": false },
    "cache": { "hit": false }
  }
}
  • meta is included only when the body sets includeMeta: true or the request sends x-include-meta: true.
  • meta.cache appears only when the dataset client has a result cache; without one it is omitted, as in TypeScript.
  • Non-null measure values are strings on the wire, matching TypeScript. Local Python client results keep native values.

Pagination

Page sizes default to 1,000 and are clamped to the endpoint's max_limit and the dataset's limits. The endpoint fetches one extra row to compute hasMore, then drops it from the returned data and row count.

Discovery

create_api serves GET /discovery whenever it serves datasets= or metrics=: a logical catalog of their datasets. Pass discovery=EndpointPolicy(...) to change who may read it, or discovery=False to leave it out. To publish a registry's catalog at another path, use add_discovery_endpoint:

add_discovery_endpoint(api, "/v1/discovery", registry=registry)
  • It requires authentication by default. Pass EndpointPolicy(public=True) only for intentionally public discovery.
  • The catalog matches TypeScript's /discovery projection. Physical tables, columns, SQL, tenant policy, and tenant values never appear in it.
  • Its size is capped at 256 KiB by default (max_bytes=), checked at startup.

On this page

Get early access to hypequery cloud.

Cloud hosts the same model you run in your backend, with a managed API and MCP server, versions, and rollback. We're letting teams in a few at a time. Join the waitlist and we'll reach out when your project can go live.

How do you want to build your analytics layer? (Optional)
What features do you most need? (Optional)

Pick as many as you like.

Only your email is required. All other questions are optional.