Huma & OpenAPI

Modern APIs: Huma & OpenAPI

Writing REST APIs involves two pains: 1. Validation (Checking JSON inputs). 2. Documentation (Keeping Swagger/OpenAPI YAML in sync with code).

In the past, we wrote code, then manually wrote YAML. The YAML effectively lied because it drifted from the code.

Enter Huma

Huma (huma.rocks) is the modern (2025/2026) framework of choice for building APIs. * Code-First OpenAPI: It generates the OpenAPI 3.1 Spec from your Go structs. * Automatic Validation: It validates inputs based on struct tags.

Huma Example

package main

import (
    "context"
    "net/http"
    "github.com/danielgtaylor/huma/v2"
    "github.com/danielgtaylor/huma/v2/adapters/humachi"
    "github.com/go-chi/chi/v5"
)

// 1. Define Request/Response
type GreetingInput struct {
    Name string `query:"name" maxLength:"30" doc:"Name to greet"`
}

type GreetingOutput struct {
    Body struct {
        Message string `json:"message" example:"Hello, World!"`
    }
}

func main() {
    router := chi.NewMux()
    api := humachi.New(router, huma.DefaultConfig("My API", "1.0.0"))

    // 2. Register Operation
    huma.Register(api, huma.Operation{
        OperationID: "get-greeting",
        Method:      http.MethodGet,
        Path:        "/greeting",
        Summary:     "Get a welcome message",
    }, func(ctx context.Context, input *GreetingInput) (*GreetingOutput, error) {
        // Only executes if validation passes!
        resp := &GreetingOutput{}
        resp.Body.Message = "Hello, " + input.Name
        return resp, nil
    })

    http.ListenAndServe(":8888", router)
}

Why Huma?

  1. Documentation: Visit /docs (or similar) and you get a beautiful, interactive Scalar or Swagger UI automatically.
  2. Safety: Meaningful error messages for users (“Field ‘name’ is too long”).
  3. Standard Library Compatible: It works on top of http.ServeMux, Chi, or Gin. It doesn’t lock you into a monolithic ecosystem.

This replaces the older swag comment-based generation which was error-prone and brittle.