Skip to content

OpenAPI

Anvil can produce OpenAPI documents from compiled HTTP manifests.

OpenAPI generation is useful because Anvil already knows:

  • Routes
  • Methods
  • Path params
  • Query params
  • Headers
  • Request bodies
  • Response types
  • Validations
  • WebSocket upgrade routes
Terminal window
anvil openapi . > openapi.json

The command scans the project and compiles the manifest. It does not rerun source analysis separately for OpenAPI.

The generator writes OpenAPI 3.1.0. Default metadata is:

  • Title: Anvil API
  • Version: 0.0.0

The CLI has no metadata flags. Embedded Go tooling can call the OpenAPI package with its own title and version.

OpenAPI output is derived from HTTP routes only. gRPC, GraphQL, and queue metadata stay in the Anvil manifest.

Path syntax is converted from Anvil’s Go router form to OpenAPI form:

/projects/:projectId -> /projects/{projectId}

Parameters come from route params and request bindings:

  • param bindings become required path parameters.
  • query bindings become query parameters.
  • header bindings become header parameters.
  • local bindings are not documented as client parameters.

Request bodies are emitted when the route has a request type, the method is POST, PUT, PATCH, or DELETE, and the manifest contains body fields.

OpenAPI request and response content is emitted as application/json. XML and custom codecs can exist at runtime through the HTTP driver, but the OpenAPI generator does not describe multiple media types.

Schema inference is intentionally conservative. Anvil creates stable component schemas for DTO types and enriches request body fields with the field shape and validation metadata the compiler knows. Response DTOs are emitted as component schema references with Go metadata; the generator does not expand response DTO fields.

Component schema names are stable and collision-resistant. They use the Go type name plus an FNV-1a hash of the Go package and type name, so two packages can both define ProjectDTO without fighting over one OpenAPI component name.

Validation tags become OpenAPI constraints:

ValidationOpenAPI output
requiredRequired property
emailformat: email
uuidformat: uuid
urlformat: uri
`oneof=ab`
regex=...pattern
lenString minLength and maxLength when the validation kind is string
min, maxString length bounds for string validations, numeric range for number validations
gt, gte, lt, lteNumeric bounds

Array fields use string items unless the manifest has richer item shape metadata.

required affects generated request body properties and parameters. Handler-set runtime status codes are not visible to OpenAPI; success status is inferred from the route shape.

Each operation also carries Anvil trace extensions:

  • x-anvil-middleware: middleware type names on the generated HTTP chain
  • x-anvil-websocket: true for WebSocket upgrade routes
  • x-anvil-source: source file and line when known

x-anvil-middleware uses the provider name when generated metadata has one. Otherwise it uses package.name, falling back to name only.

Every HTTP operation includes 400 and 500 responses using Anvil’s standard HTTP error envelope:

{
"error": {
"status": 400,
"message": "invalid request",
"fields": {
"email": "must be a valid email"
}
}
}

If Anvil detects bearer-style authentication, the operation also receives a 401 response.

Security inference is deliberately small. Anvil adds bearerAuth when either:

  • A request binding reads the Authorization header.
  • A middleware name or provider contains auth, actor, principal, identity, or session.

If your company uses another auth model, treat the generated file as the base document and post-process it in CI, or add a custom tooling step from the manifest.

Success status is selected by route shape:

  • WebSocket route: 101
  • POST: 201
  • Other HTTP methods: 200

The generator validates the document before writing JSON. Validate the final file again in CI when clients or downstream services depend on it, especially when you post-process the output.

The built-in validator checks:

  • OpenAPI root fields and info.title / info.version.
  • Path parameter names against the path template.
  • Duplicate parameters.
  • Request and response content schemas.
  • Response codes in the 100..599 range.
  • Schema references.
  • Schema types, array item schemas, bounds, and required properties.
  • Referenced security schemes.
  • apiKey and http security scheme shape.