# API Documentation Pattern

**Last Updated:** 2026-01-31
**Confidence:** High

## Summary

Episteme uses a "define once, document everywhere" approach. Rust types are the single source of truth for both runtime behavior and API documentation. The `utoipa` crate generates OpenAPI 3.1 specs at compile time from derive macros on the same structs used for JSON serialization.

**Key Facts:**
- `utoipa` chosen over `aide` for compile-time generation and framework-agnostic design
- `utoipa-axum` provides `OpenApiRouter` that collects handler metadata automatically
- `utoipa-swagger-ui` serves interactive docs in dev mode
- `widdershins` converts OpenAPI JSON to Slate-compatible markdown in CI
- No separate schema files to maintain; types ARE the schema

## The Stack

| Layer | Tool | Purpose |
|-------|------|---------|
| Type definitions | `serde` + `utoipa::ToSchema` | Single struct defines JSON shape AND OpenAPI schema |
| Handler docs | `#[utoipa::path]` | Documents endpoint alongside implementation |
| Router | `utoipa_axum::OpenApiRouter` | Collects all handler metadata automatically |
| Spec output | `/api-doc/openapi.json` | OpenAPI 3.1 spec, no build step |
| Dev UI | `utoipa-swagger-ui` | Interactive API explorer at `/swagger-ui` |
| Published docs | `widdershins` + Slate | CI generates static docs from OpenAPI spec |

## Adding a New Endpoint (Quick Reference)

1. Define DTO types with `#[derive(Serialize, Deserialize, ToSchema)]`
2. Write handler function
3. Annotate with `#[utoipa::path(post, path = "/foo", ...)]`
4. Register on `OpenApiRouter` - docs update automatically
5. No manual schema sync needed

**File Pointer:** `.claude/guides/backend/api-endpoints.md` for full procedure.

## Why utoipa Over aide

- Compile-time generation fits zero-cost philosophy
- Framework-agnostic (future gRPC won't require rewrite)
- Larger ecosystem (SwaggerUI, Redoc, Scalar, RapiDoc crates)
- Already macro-heavy codebase (rkyv derives) - one more derive is natural

## gRPC (Future)

When added, `.proto` files will be the source for gRPC docs via `protoc-gen-doc`.
Both HTTP and gRPC will share the same internal types via `From<>` conversions.
The DTO layer keeps internal `rkyv` types separate from public API contracts.

## Related Topics

- [API Service](../services/api.md) - Endpoints and crate structure
- [Error Handling](./error-handling.md) - thiserror + context pattern
