Tue, November 4, 20254 min read

Ship your data with Moose APIs

OK
Olivia Kane
JO
Johanan OttensooserProduct

TL;DR

Moose lets you expose OLAP data through typed, validated APIs: either with Moose’s built-in API class or by integrating frameworks like Express, FastAPI, or Koa.

You’ve got Change Data Capture flowing, and your ClickHouse tables are modeled for fast scans and sane defaults. But your app still can’t use any of that data until you expose it cleanly—through an API that’s safe, documented, and type-consistent.

Moose gives you two ways to do that:

  1. Use the native Api class for quick, typed endpoints without extra setup.

  2. Bring your own framework (e.g. Express, Koa, Fastify, or FastAPI) and leverage your runtime validation and auth providers of choice.

This post focuses on the first option: building Moose-native APIs co-located with your models. In the next post, we’ll look at embedding or calling Moose from other frameworks.

Building APIs on OLAP data

Whether you prefer Express, Fastify, Koa, FastAPI, or Moose’s own Api class, the core challenge is the same: turning OLAP tables into clean, reliable endpoints. Most teams end up maintaining similar plumbing:

  • Connection pooling, SQL parameterization, and identifier safety
  • Query validation and type conversion
  • OpenAPI documentation and SDK generation
  • Authentication and API key management
  • Schema and client type alignment

Moose handles those cross-cutting concerns so you can focus on application logic. It provides a shared foundation for both custom frameworks and native MooseStack APIs (with batteries included), giving you:

  • Safe database access
  • Built-in JWT and API key authentication
  • Shared type definitions between models, APIs, and clients

You can choose the right level of control for your project: use the Moose Api class for lightweight analytics endpoints, or embed a full web framework when you need richer routing, middleware, or customization over type validation and auth . Either way, you get consistent APIs built directly on your OLAP data.

0) Make sure APIs are enabled in your MooseStack project

This feature is on by default, make sure you haven't turned it off!

Loading...

Run moose dev and Moose will boot an HTTP server. It will print all the endpoints available in your terminal.

1) A tiny analytics API (typed in, typed out)

Loading...

Off the shelf, the api class provides:

  • Type validation on input/output

  • DB client management

  • OpenAPI generation at .moose/openapi.yaml

Now open your browser:
GET /api/orders/recent?orderBy=total&limit=25

2) Conditional filters without SQL footguns

Loading...

All params are safely bound; The sql tagged template literal provided to your route handler handles the query sanitization, which includes safely handling identifiers passed as variables in your query string. This means you can import OlapTables and reference them and their columns directly inside your API queries.

3) Auth: API keys for internal, JWT for users (or both)

Loading...

Then in .env:

Loading...

For JWTs:

Loading...

Usage inside a handler:

Loading...

Generate a type-safe SDK with hey API

While moose dev runs, Moose emits an OpenAPI spec. You can now auto-generate a client SDK using hey API:

Loading...

Create a config:

Loading...

Link it to Moose’s reload hook:

Loading...
Loading...

Now every moose dev reload updates .moose/openapi.yaml and regenerates your SDK.

Using the generated client

Loading...

Your client stays type-safe and up-to-date with every schema change—no manual codegen, no drift.

What’s up next

In the next post, we’ll look at using common API frameworks (like FastAPI, Express, or Next.js) together with Moose. You’ll see how to plug Moose’s type system and OpenAPI spec into your preferred stack, so you get the same type safety and schema-driven SDKs while keeping your own routing, middleware, and deployment patterns.

Interested in learning more?

Sign up for our newsletter — we only send one when we have something actually worth saying.

Follow us

Related posts

All Blog Posts