API Documentation Overview
zzz includes a built-in OpenAPI 3.1.0 spec generator that derives API documentation directly from your route definitions. Because the spec is generated at compile time, there is zero runtime overhead and the documentation is always in sync with your code.
What zzz provides
Section titled “What zzz provides”The zzz.swagger module offers three capabilities:
| Feature | Module | Description |
|---|---|---|
| Spec generation | zzz.swagger.spec | Produces a complete OpenAPI 3.1.0 JSON document from annotated routes at comptime |
| JSON Schema | zzz.swagger.schema | Derives JSON Schema definitions from Zig struct and enum types |
| Swagger UI | zzz.swagger.middleware | Serves an interactive Swagger UI page and the raw JSON spec as middleware |
All three work together: you annotate routes with .doc(), point the spec generator at your route table, and plug the Swagger UI middleware into your application. The result is a fully browsable API reference served alongside your application.
How it works
Section titled “How it works”-
Annotate routes using the
.doc()method on any route definition. Only annotated routes appear in the generated spec; everything else is excluded.zzz.Router.get("/api/status", statusHandler).doc(.{ .summary = "Health check", .response_body = StatusResponse }), -
Generate the spec by calling
zzz.swagger.generateSpecwith a configuration struct and your route table. This runs entirely at compile time and produces a[]const u8containing the OpenAPI JSON.const api_spec = zzz.swagger.generateSpec(.{.title = "My API",.version = "1.0.0",}, routes); -
Serve the UI by adding the Swagger UI middleware to your application. It serves an interactive HTML page at
/api/docsand the raw spec at/api/docs/openapi.json.const App = zzz.Router.define(.{.middleware = &.{// ... other middleware ...zzz.swagger.ui(.{ .spec_json = api_spec }),},.routes = routes,});
Key concepts
Section titled “Key concepts”Compile-time generation
Section titled “Compile-time generation”The entire OpenAPI spec, including JSON Schema definitions for request and response bodies, is computed at compile time using Zig’s comptime evaluation. The generated JSON string is embedded directly in the binary. This means:
- No runtime allocation or serialization cost
- No reflection or code generation build steps
- Type mismatches between documentation and handlers are caught at compile time
Selective documentation
Section titled “Selective documentation”Routes without a .doc() annotation are invisible to the spec generator. This lets you keep internal endpoints (health checks, debug routes, admin tools) out of your public API documentation while still defining them in the same route table.
Automatic schema derivation
Section titled “Automatic schema derivation”When you specify request_body or response_body types in a .doc() annotation, zzz automatically generates JSON Schema definitions for those Zig types and places them in the OpenAPI components/schemas section. Struct fields, optional types, enums, arrays, and nested structures are all handled.
A complete example
Section titled “A complete example”const std = @import("std");const zzz = @import("zzz");
const User = struct { id: i64, name: []const u8, email: ?[]const u8,};
const CreateUserRequest = struct { name: []const u8, email: []const u8,};
fn listUsers(ctx: *zzz.Context) !void { ctx.json(.ok, .{ .users = &[_]User{} });}
fn createUser(ctx: *zzz.Context) !void { ctx.json(.created, .{ .id = 1, .name = "new" });}
const routes = &.{ zzz.Router.get("/api/users", listUsers) .doc(.{ .summary = "List all users", .tag = "Users", .response_body = []const User, }), zzz.Router.post("/api/users", createUser) .doc(.{ .summary = "Create a user", .tag = "Users", .request_body = CreateUserRequest, .response_body = User, }),};
const api_spec = zzz.swagger.generateSpec(.{ .title = "User Service", .version = "1.0.0", .description = "User management API",}, routes);
const App = zzz.Router.define(.{ .middleware = &.{ zzz.logger, zzz.swagger.ui(.{ .spec_json = api_spec }), }, .routes = routes,});After starting the server, visit /api/docs to see the interactive Swagger UI, or fetch /api/docs/openapi.json for the raw spec.
Next steps
Section titled “Next steps”- Swagger and OpenAPI — configure spec generation, security schemes, and the Swagger UI middleware in detail
- JSON Schema — understand how Zig types map to JSON Schema and how to customize schema output