Typed HTTP APIs in Go

ezz sits on top of net/http. Your handler takes a typed request and returns a typed response; the framework binds the request from struct tags, validates it, checks the caller's roles, and generates the OpenAPI spec from the same types.

One type, four jobs

GetUserRequest describes the path parameter and the query string, so ezz can bind it, validate it, document it in /openapi.json, and hand your function a filled-in struct. There is no code generation step and no reflection on the request path.
main.go
type GetUserRequest struct {
    ID     string `path:"id" validate:"required" description:"User ID"`
    Fields string `query:"fields" default:"basic"`
}

app := ezz.New().Auth(auth.NewJWTAuthProvider(jwt))

app.GET("/users/{id}", ezz.H(func(ctx *ezz.Context, req GetUserRequest) (*User, error) {
    user, ok := store[req.ID]
    if !ok {
        return nil, ezz.NotFound("user not found")
    }
    return user, nil
})).Tags("Users")

What you get

Every part of the framework works with plain net/http types, so you can drop down a level whenever you need to.
Typed handlers
ezz.H and ezz.HFunc give you generic handlers with compile-time request and response types. Binders and validators are built once at registration.
Tag-driven binding
Read values from the path, query string, headers, form fields, and JSON body with path, query, header, form, and default tags.
Auth on by default
Set an auth provider and every route requires a valid token until you mark it .Public(). Roles and permissions are route-level rules.
Authorization from your own tables
An authorization resolver loads roles and permissions from your store, lazily and once per request, with an optional TTL cache.
OpenAPI from your types
The spec is generated from handler signatures, struct tags, and validation rules, and served next to a Scalar UI at /docs.
GoTrue proxy
Keep GoTrue on a private network and expose typed, documented, rate-limited /auth/* routes through your own service.
Middleware you already know
func(http.Handler) http.Handler. Recovery, request IDs, and logging are installed by default; CORS, gzip, and rate limiting ship alongside.
Cheap request path
Pooled contexts and response writers, middleware chains compiled at registration, and Go's own ServeMux for routing.

Ready to build something?

Install the module, copy the quick start, and you have a documented, authenticated JSON API in about thirty lines.
Copyright © 2026