ClickHouse OpenAPI
Auto-generated OpenAPI docs from ClickHouse query definitions
Most internal analytics APIs never get documented properly because the spec is a second thing to maintain. hypequery makes the docs fall out of the query definition, so the request shape, response shape, and served endpoint stay in sync.
Spec format
OpenAPI 3.0
Source
Derived from query types
UI
Swagger included
Hand-written specs drift from real endpoints
Teams update the route, forget the YAML, and then frontend code is generated from a spec that no longer matches production. That is worse than having no spec at all.
Frontend teams still need a contract they can trust
If a dashboard or another service is consuming the API, “ask backend for the shape” does not scale. They need a stable spec that reflects the actual query output.
Documentation is usually treated as a separate project
As soon as docs become a parallel workflow, they slip. The only durable version is one derived from the same definitions that serve the endpoint.
What actually happens
Define the query once and let the spec come from it
The query definition already contains the pieces an API spec needs: validated input, a known endpoint, and a typed response. hypequery uses those pieces directly instead of asking you to mirror them in a second file.
- Request body schema derived from your Zod input definition
- Response schema derived from ClickHouse-generated TypeScript types
- Full OpenAPI 3.0 spec available at /openapi.json
- Interactive Swagger UI available at /docs
- Spec changes when the query definition changes, not on a separate docs schedule
Query definition
The source of truth is the served query
This is the only code you should need to maintain. The spec is derived from the input schema and the inferred query result instead of being copied into OpenAPI YAML.
What the client sees
The generated spec is boring in the right way
A good generated spec should look ordinary. That is the point. Consumers get a standard OpenAPI document they can inspect, feed into tooling, or use to generate clients without knowing anything about hypequery.
That makes client generation viable again. If you feed this into `openapi-typescript`, the resulting client types are grounded in the same query definitions that serve production traffic.
If your main problem is the endpoint layer itself, go to the REST API page. If the problem is browser consumption, pair this with the React page.
Generated spec
A normal OpenAPI response, not a custom format
What matters here is not the JSON itself. It is that the output is plain OpenAPI, which means the rest of your tooling can stay standard.
Where teams usually get stuck
The questions this page should answer
Why this is better than writing YAML
You stop maintaining two parallel descriptions of the same endpoint. The served query is the implementation, and the OpenAPI document is a by-product of that implementation.
What frontend teams get out of it
A trustworthy spec means frontend codegen becomes practical again. Consumers can generate types or clients without reverse-engineering responses from network tabs.
When this page matters
This page matters once a query is no longer private implementation detail and needs external consumers, generated clients, or documentation that survives team growth.
When it does not
If you only run queries locally inside one service, OpenAPI is not the point. The value starts when other people or other apps need to call what you built.
Further reading
Go deeper where it actually helps
ClickHouse REST API
The full guide to serving ClickHouse queries as typed HTTP endpoints with @hypequery/serve.
Open guide
ClickHouse Query Builder
The query definitions that drive the OpenAPI spec and the HTTP endpoints.
Open guide
ClickHouse React hooks
Consume your typed REST endpoints as React hooks for dashboard components.
Open guide
ClickHouse schema generation
How the TypeScript types are generated from your ClickHouse schema — the source of the response schemas.
Open guide
Next step
Serve one query and inspect the generated spec
Pick a real analytics query, expose it through `serve()`, and look at `/openapi.json`. That gives you a much better signal than polishing a docs layer before the endpoint even exists.