Guide

Generate an Axum server from OpenAPI

Start from an existing OpenAPI contract, select the operations your service hosts, and generate the typed Axum boundary. You keep the business logic; the generator keeps routes and wire types aligned.

Last reviewed July 15, 2026

On This Page
  1. What it generates
  2. Select operations
  3. Implement the trait
  4. Typed responses
  5. SSE responses
  6. Client and server
  7. Limits

What the Axum generator creates

openapi-to-rust is a spec-first Axum generator: the input is an OpenAPI YAML or JSON document and the output is Rust server scaffolding. For selected operations, it emits:

  • A service trait per OpenAPI tag.
  • A typed response enum per operation, with variants tied to documented status codes.
  • Axum handlers and a combined build_router(...) factory.
  • Path, query, header, and request-body extraction.
  • An HTTP 400 short-circuit when required parameters are missing or invalid at the handler boundary.
  • SSE-ready response variants when streaming behavior is declared.

Shared request and response models live in the same generated types.rs used by the optional client. Your implementation remains ordinary Rust behind the generated trait.

Select the operations your server hosts

Add a [server] section to openapi-to-rust.toml:

openapi-to-rust.tomltoml
[generator]
spec_path = "openapi.yaml"
output_dir = "src/generated"
module_name = "api"

[features]
enable_async_client = false

[server]
framework = "axum"
operations = [
  "createResponse",
  "GET /v1/responses/{response_id}",
  "tag:Files",
]
prune_models = true

Selectors accept an exact operationId, an exact METHOD /path, or an entiretag:name. With prune_models = true, schemas unreachable from the selected surface are omitted.

Use the CLI to inspect and update the selection without hand-editing TOML:

Terminalshell
openapi-to-rust server list --tag Responses
openapi-to-rust server add createResponse
openapi-to-rust server add --all-tag Files
openapi-to-rust server remove deleteFile
openapi-to-rust generate

Implement the generated Axum trait

Implement each selected operation on your application state, then pass that state to the generated router factory. The exact types come from the OpenAPI contract, while authorization, storage, orchestration, and domain behavior remain yours.

server.rsrust
use generated::server::{
    build_router, CreateResponseResponse, ResponsesApi,
};

#[derive(Clone)]
struct AppState;

#[axum::async_trait]
impl ResponsesApi for AppState {
    async fn create_response(
        &self,
        body: CreateResponse,
    ) -> CreateResponseResponse {
        CreateResponseResponse::Ok(build_response(body))
    }
}

let app = build_router(AppState);

Tags let a larger service split implementation across focused traits. The combined router joins the selected tag routers so the application can serve one Axum Router.

Return status-code-typed responses

Instead of returning an unstructured status and body pair, each generated operation exposes an enum whose variants correspond to documented responses. A successful JSON response, a typed 4xx body, and an empty 204 become distinct Rust variants.

This makes the implementation’s possible wire responses visible in its return type. It does not add general runtime schema validation: minimums, maximums, patterns, and similar constraints are included as documentation rather than validators.

Generate SSE-ready Axum responses

When an operation declares text/event-stream, the response enum can include an SSE stream variant. The generatedsse_response helper accepts a stream of Axum SSE events and produces the payload expected by that variant.

Some public API documents omit streaming media types even when the live API supports them. Use a small overlay to add the missing response content entry before generation. The included Anthropic Messages example uses this approach rather than maintaining a full fork of the upstream document.

Generate a client and server together

You can enable the async client and Axum server in the same configuration. Client and server selectors are independent, and model pruning retains schemas reachable from either selected surface. This works well for gateways, protocol adapters, and services that host part of an API while calling another part.

See the completeOpenAI Responses examplefor multi-tag routing, request bodies, SSE, query parameters, and required-parameter handling.

Current server-generation limits

  • Axum is the only generated server framework.
  • Server generation is opt-in and the crate is pre-1.0.
  • OpenAPI 2.0 is not accepted.
  • Modeling a security scheme does not generate your authorization policy or credential storage.
  • OpenAPI 3.2 support is experimental; verify generated behavior for less-common fields.

Compare this workflow with OpenAPI Generator’s separate beta rust-axum target in thesource-linked Rust generator comparison.