This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

OpenAPI Package

API reference for rivaas.dev/openapi - Automatic OpenAPI specification generation

This is the API reference for the rivaas.dev/openapi package. For learning-focused documentation, see the OpenAPI Guide.

Package Information

Package Overview

The openapi package provides automatic OpenAPI 3.0.4 and 3.1.2 specification generation from Go code using struct tags and reflection.

Core Features

  • Automatic OpenAPI specification generation from Go code
  • Support for OpenAPI 3.0.4 and 3.1.2 specifications
  • Type-safe version selection with V30x and V31x constants
  • Fluent HTTP method constructors (GET, POST, PUT, etc.)
  • Automatic parameter discovery from struct tags
  • Schema generation from Go types
  • Built-in validation against official meta-schemas
  • Type-safe warning diagnostics via diag package
  • Swagger UI configuration support

Architecture

The package is organized into two main components:

Main Package (rivaas.dev/openapi)

Core specification generation including:

  • API struct - Configuration container
  • New() / MustNew() - API initialization
  • Operation builders - WithGET(), WithPOST(), WithPUT(), etc.
  • Operation options - WithRequest(), WithResponse(), WithSecurity(), etc.
  • WithOperations() - Declarative operations at construction
  • API.AddOperation() - Add operations after construction (returns error if invalid)
  • API.Spec(ctx) - Specification generation

Example sub-package (rivaas.dev/openapi/example)

Named examples for request/response bodies:

  • Example type - OpenAPI Example Object
  • New(name, value, opts...) / NewExternal(name, url, opts...) - Create inline or external examples
  • WithSummary() / WithDescription() - Optional metadata
  • Pass results to WithRequest() or WithResponse() for named examples in the spec

Sub-package (rivaas.dev/openapi/diag)

Type-safe warning diagnostics:

  • Warning interface - Individual warning
  • Warnings type - Warning collection
  • WarningCode type - Type-safe warning codes
  • WarningCategory type - Warning categories

Validator (rivaas.dev/openapi/validate)

Standalone specification validator:

  • Validator type - Validates OpenAPI specifications
  • New(opts ...Option) (*Validator, error) / MustNew(opts ...Option) *Validator - Create a validator (options optional; construction currently cannot fail)
  • WithVersions(versions ...Version) - Restrict which OpenAPI versions are accepted (default: both 3.0 and 3.1)
  • Validate() - Validate against specific version
  • ValidateAuto() - Auto-detect version from spec and validate

Quick API Index

API Creation

api, err := openapi.New(options...)     // With error handling
api := openapi.MustNew(options...)      // Panics on error

Specification Generation

if err := api.AddOperation(op1, op2); err != nil {
    log.Fatal(err)
}
result, err := api.Spec(ctx)        // or use WithOperations at construction

Operation Builders

openapi.WithGET(path, ...opts) (Operation, error)
openapi.WithPOST(path, ...opts) (Operation, error)
openapi.WithPUT(path, ...opts) (Operation, error)
openapi.WithPATCH(path, ...opts) (Operation, error)
openapi.WithDELETE(path, ...opts) (Operation, error)
openapi.WithHEAD(path, ...opts) (Operation, error)
openapi.WithOPTIONS(path, ...opts) (Operation, error)
openapi.WithTRACE(path, ...opts) (Operation, error)
openapi.WithOp(method, path, ...opts) (Operation, error)

Result Access

result.JSON      // OpenAPI spec as JSON bytes
result.YAML      // OpenAPI spec as YAML bytes
result.Warnings  // Generation warnings

Reference Pages

API Reference

Core types, HTTP method constructors, and generation API.

View →

Options

API-level configuration for info, servers, and security.

View →

Operation Options

Operation-level configuration for endpoints.

View →

Swagger UI Options

Customize the Swagger UI interface.

View →

Diagnostics

Warning system and diagnostic codes.

View →

Troubleshooting

Common issues and solutions.

View →

User Guide

Step-by-step tutorials and examples.

View →

Type Reference

API

type API struct {
    // contains filtered or unexported fields
}

Main API configuration container. Created via New() or MustNew() with functional options. Configuration is read-only after creation; use getters such as Info(), SpecPath(), UIPath(), ServeUI(), ValidateSpec(), and Version() to read values.

Operation

type Operation struct {
    // contains filtered or unexported fields
}

Represents an HTTP operation with method, path, and metadata. Created via HTTP method constructors.

Result

type Result struct {
    JSON     []byte    // OpenAPI spec as JSON
    YAML     []byte    // OpenAPI spec as YAML
    Warnings Warnings  // Generation warnings
}

Result of specification generation containing the spec in multiple formats and any warnings.

Version

type Version int

const (
    V30x Version = iota  // OpenAPI 3.0.x (generates 3.0.4)
    V31x                 // OpenAPI 3.1.x (generates 3.1.2)
)

Type-safe OpenAPI version selection.

Option

Functional option for API configuration. Options apply to an internal config; the constructor builds the API from the validated config. Options must not be nil; passing a nil option results in an error (or panic with MustNew).

OperationOption

type OperationOption func(*Operation) error

Functional option for operation configuration.

Common Patterns

Basic Generation

api := openapi.MustNew(openapi.WithTitle("My API", "1.0.0"))
op, _ := openapi.WithGET("/users/:id", openapi.WithSummary("Get user"), openapi.WithResponse(200, User{}))
if err := api.AddOperation(op); err != nil {
    log.Fatal(err)
}
result, err := api.Spec(context.Background())

With Security

api := openapi.MustNew(
    openapi.WithTitle("My API", "1.0.0"),
    openapi.WithBearerAuth("bearerAuth", "JWT authentication"),
)
op, _ := openapi.WithGET("/users/:id", openapi.WithSecurity("bearerAuth"), openapi.WithResponse(200, User{}))
if err := api.AddOperation(op); err != nil {
    log.Fatal(err)
}
result, err := api.Spec(context.Background())

With Validation

api := openapi.MustNew(
    openapi.WithTitle("My API", "1.0.0"),
    openapi.WithValidateSpec(true),
)
result, err := api.Spec(context.Background())
// Fails if spec is invalid

With Diagnostics

import "rivaas.dev/openapi/diag"

result, err := api.Spec(context.Background())
if err != nil {
    log.Fatal(err)
}

if result.Warnings.Has(diag.WarnDownlevelInfoSummary) {
    log.Warn("info.summary was dropped")
}

Thread Safety

The API type is safe for concurrent use:

  • Multiple goroutines can call Spec() and AddOperation() (operations slice is protected)
  • Configuration is immutable after creation

Not thread-safe:

  • Modifying API configuration during initialization

Performance Notes

  • Schema generation: First use per type ~500ns (reflection), subsequent uses ~50ns (cached)
  • Validation: Adds 10-20ms on first validation (schema compilation), 1-5ms subsequent
  • Generation: Depends on operation count and complexity

Version Compatibility

The package follows semantic versioning. The API is stable for the v1 series.

Minimum Go version: 1.25

Next Steps

For learning-focused guides, see the OpenAPI Guide.

1 - API Reference

Complete API reference for types, functions, and methods

Complete reference for all types, functions, and methods in the openapi package.

Key Types

API

type API struct {
    // contains filtered or unexported fields
}

Main API configuration container. Holds the OpenAPI specification metadata and configuration. Configuration is read-only after creation; use the getters below to read values.

Created by:

  • New(...Option) (*API, error) - With error handling.
  • MustNew(...Option) *API - Panics on error.

Methods:

  • Spec(ctx context.Context) (*Result, error) - Generate OpenAPI specification from current config and operations.
  • AddOperation(ops ...Operation) error - Add operations (e.g. from [WithGET], [WithPOST]) for inclusion in the spec. Returns an error if any operation has empty method/path or invalid path format; on error no operations are added.
  • Validate() error - Check if the API configuration is valid.
  • UI() UISnapshot - Read-only snapshot of Swagger UI configuration for rendering (e.g. use [UISnapshot.ToJSON] to embed in HTML).
  • Info() Info - API metadata (title, version, description, etc.).
  • Servers() []Server - Server list.
  • Tags() []Tag - Tags.
  • SecuritySchemes() map[string]*SecurityScheme - Security schemes.
  • DefaultSecurity() []SecurityRequirement - Default security requirements.
  • ExternalDocs() *ExternalDocs - External documentation link.
  • Extensions() map[string]any - Root-level extensions.
  • Version() Version - Target OpenAPI version (V30x or V31x).
  • StrictDownlevel() bool - Whether 3.1-only features error when targeting 3.0.
  • SpecPath() string - HTTP path for the spec JSON.
  • UIPath() string - HTTP path for Swagger UI.
  • ServeUI() bool - Whether Swagger UI is enabled.
  • ValidateSpec() bool - Whether spec validation is enabled.

Operation

type Operation struct {
    // contains filtered or unexported fields
}

Represents an HTTP operation with method, path, and configuration.

Created by operation builders:

  • WithGET(path string, ...OperationOption) (Operation, error)
  • WithPOST(path string, ...OperationOption) (Operation, error)
  • WithPUT(path string, ...OperationOption) (Operation, error)
  • WithPATCH(path string, ...OperationOption) (Operation, error)
  • WithDELETE(path string, ...OperationOption) (Operation, error)
  • WithHEAD(path string, ...OperationOption) (Operation, error)
  • WithOPTIONS(path string, ...OperationOption) (Operation, error)
  • WithTRACE(path string, ...OperationOption) (Operation, error)
  • WithOp(method, path string, ...OperationOption) (Operation, error) - Custom method

Result

type Result struct {
    JSON     []byte
    YAML     []byte
    Warnings Warnings
}

Result of specification generation.

Fields:

  • JSON - OpenAPI specification as JSON bytes.
  • YAML - OpenAPI specification as YAML bytes.
  • Warnings - Collection of generation warnings. Check Diagnostics for details.

Version

type Version int

const (
    V30x Version = iota  // OpenAPI 3.0.x (generates 3.0.4)
    V31x                 // OpenAPI 3.1.x (generates 3.1.2)
)

Type-safe OpenAPI version selection. Use with WithVersion() option.

Constants:

  • V30x - Target OpenAPI 3.0.x family. Generates 3.0.4 specification.
  • V31x - Target OpenAPI 3.1.x family. Generates 3.1.2 specification.

UISnapshot

type UISnapshot interface {
    ToJSON(specPath string) (string, error)
}

Read-only view of Swagger UI configuration returned by [API.UI]. Use it for rendering (e.g. embed JSON in HTML); do not use for construction. Configuration is done via [UIOption] and [New] or [MustNew].

Option

type Option func(*config)

Functional option for configuring the API. See Options for all available options.

OperationOption

type OperationOption func(*operationDoc)

Functional option for configuring operations. See Operation Options for all available options.

Functions

New

func New(opts ...Option) (*API, error)

Creates a new API configuration with error handling.

Parameters:

  • opts - Variable number of Option functions

Returns:

  • *API - Configured API instance
  • error - Configuration error if any

Example:

api, err := openapi.New(
    openapi.WithTitle("My API", "1.0.0"),
    openapi.WithServer("http://localhost:8080", "Development"),
)
if err != nil {
    log.Fatal(err)
}

MustNew

func MustNew(opts ...Option) *API

Creates a new API configuration. Panics if configuration fails.

Parameters:

  • opts - Variable number of Option functions

Returns:

  • *API - Configured API instance

Panics:

  • If configuration fails

Example:

api := openapi.MustNew(
    openapi.WithTitle("My API", "1.0.0"),
    openapi.WithServer("http://localhost:8080", "Development"),
)

Operation Builders

Operations are created with WithGET, WithPOST, etc., and added to the API via [WithOperations] at construction or [API.AddOperation] after. Then call [API.Spec] to generate the spec.

WithGET

func WithGET(path string, opts ...OperationOption) (Operation, error)

Creates a GET operation.

Example:

op, err := openapi.WithGET("/users/:id",
    openapi.WithSummary("Get user"),
    openapi.WithResponse(200, User{}),
)
if err == nil {
    _ = api.AddOperation(op)
}

WithPOST

func WithPOST(path string, opts ...OperationOption) (Operation, error)

Creates a POST operation.

Example:

op, err := openapi.WithPOST("/users",
    openapi.WithSummary("Create user"),
    openapi.WithRequest(CreateUserRequest{}),
    openapi.WithResponse(201, User{}),
)
if err == nil {
    _ = api.AddOperation(op)
}

WithPUT, WithPATCH, WithDELETE, WithHEAD, WithOPTIONS, WithTRACE

Same pattern as WithGET / WithPOST for other HTTP methods.

WithOp

func WithOp(method, path string, opts ...OperationOption) (Operation, error)

Creates an operation with a custom HTTP method.

Methods

API.Spec

func (api *API) Spec(ctx context.Context) (*Result, error)

Generates an OpenAPI specification from the API’s current configuration and operations (from [WithOperations] and/or [API.AddOperation]). No operation list is passed at call time.

Example:

api := openapi.MustNew(openapi.WithTitle("My API", "1.0.0"))
op, _ := openapi.WithGET("/users/:id", openapi.WithSummary("Get user"), openapi.WithResponse(200, User{}))
if err := api.AddOperation(op); err != nil {
    log.Fatal(err)
}
result, err := api.Spec(context.Background())
// Or use WithOperations at construction and skip AddOperation

API.AddOperation

func (api *API) AddOperation(ops ...Operation) error

Adds one or more operations to the API. Call [API.Spec] to generate the spec including these operations. Returns an error if any operation has empty Method or Path or an invalid path format; on error no operations are added.

API.Version

func (api *API) Version() Version

Returns the target OpenAPI version (V30x or V31x).

Returns:

  • string - Version string (“3.0.4” or “3.1.2”)

Example:

api := openapi.MustNew(
    openapi.WithTitle("API", "1.0.0"),
    openapi.WithVersion(openapi.V31x),
)

fmt.Println(api.Version()) // "3.1.2"

Type Aliases and Constants

Parameter Locations

const (
    InHeader ParameterLocation = "header"
    InQuery  ParameterLocation = "query"
    InCookie ParameterLocation = "cookie"
)

Used with WithAPIKey() to specify where the API key is located.

Swagger UI Constants

// Document expansion
const (
    DocExpansionList DocExpansion = "list"
    DocExpansionFull DocExpansion = "full"
    DocExpansionNone DocExpansion = "none"
)

// Model rendering
const (
    ModelRenderingExample ModelRendering = "example"
    ModelRenderingModel   ModelRendering = "model"
)

// Operations sorting
const (
    OperationsSorterAlpha  OperationsSorter = "alpha"
    OperationsSorterMethod OperationsSorter = "method"
)

// Tags sorting
const (
    TagsSorterAlpha TagsSorter = "alpha"
)

// Validators (untyped string constants)
const (
    ValidatorLocal = "local"  // Use embedded meta-schema validation
    ValidatorNone  = "none"   // Disable validation
)

// Syntax themes
const (
    SyntaxThemeAgate        SyntaxTheme = "agate"
    SyntaxThemeArta         SyntaxTheme = "arta"
    SyntaxThemeMonokai      SyntaxTheme = "monokai"
    SyntaxThemeNord         SyntaxTheme = "nord"
    SyntaxThemeObsidian     SyntaxTheme = "obsidian"
    SyntaxThemeTomorrowNight SyntaxTheme = "tomorrow-night"
    SyntaxThemeIdea         SyntaxTheme = "idea"
)

// Request snippet languages
const (
    SnippetCurlBash       RequestSnippetLanguage = "curl_bash"
    SnippetCurlPowerShell RequestSnippetLanguage = "curl_powershell"
    SnippetCurlCmd        RequestSnippetLanguage = "curl_cmd"
)

See Swagger UI Options for usage.

Breaking changes / Migration

If upgrading from an older version, note:

  • OAuth2: WithOAuth2(name, desc, flows ...OAuth2Flow) and the OAuth2Flow struct have been removed. Use flow-specific options instead: [WithOAuth2AuthorizationCode], [WithOAuth2Implicit], [WithOAuth2Password], [WithOAuth2ClientCredentials]. Multiple flows for the same scheme name can be composed by calling more than one option.
  • Getters: Info(), Servers(), Tags(), SecuritySchemes(), DefaultSecurity(), and ExternalDocs() now return types defined in the openapi package (Info, Server, Tag, SecurityScheme, SecurityRequirement, ExternalDocs) instead of internal/model types.
  • AddOperation: AddOperation(ops ...Operation) now returns error. Invalid operations (empty method/path or invalid path format) cause an error and no operations are added. Always check the return value.
  • Default security builder: The constructor for security requirements was renamed from SecurityRequirement(scheme, scopes...) to [RequireSecurity].
  • Operations validation: Operations passed to WithOperations or AddOperation are validated at construction or add time (method and path required, path format validated). Invalid operations cause New() or AddOperation() to fail.
  • UI config types: SyntaxHighlightConfig and RequestSnippetsConfig are no longer exported. Configure syntax highlighting and request snippets only via [WithUISyntaxTheme], [WithUIRequestSnippets], and related UIOptions.

Next Steps

2 - API Options

Complete reference for API-level configuration options

Complete reference for all API-level configuration options (functions passed to New() or MustNew()).

Info Options

WithTitle

func WithTitle(title, version string) Option

Sets the API title and version. Required.

Parameters:

  • title - API title.
  • version - API version like “1.0.0”.

Example:

openapi.WithTitle("My API", "1.0.0")

WithTitleIfDefault

func WithTitleIfDefault(title, version string) Option

Sets the API title and version only if they are still the defaults (“API” and “1.0.0”). Used by the app package to inject service name and version when the user has not set a custom title. Option order does not matter; when applied last, it only overwrites default values.

Example (typically used by app when building OpenAPI options):

opts = append(opts, openapi.WithTitleIfDefault(serviceName, serviceVersion))

WithDescription

func WithDescription(description string) Option

Sets the API description (Info object).

Example:

openapi.WithDescription("Comprehensive API for managing users and resources")

WithInfoSummary

func WithInfoSummary(summary string) Option

Sets a short summary for the API. OpenAPI 3.1 only. Generates warning if used with 3.0 target.

Example:

openapi.WithInfoSummary("User Management API")

WithTermsOfService

func WithTermsOfService(url string) Option

Sets the terms of service URL.

Example:

openapi.WithTermsOfService("https://example.com/terms")

WithContact

func WithContact(name, url, email string) Option

Sets contact information.

Parameters:

  • name - Contact name
  • url - Contact URL
  • email - Contact email

Example:

openapi.WithContact("API Support", "https://example.com/support", "support@example.com")

WithLicense

func WithLicense(name, url string) Option

Sets license information.

Parameters:

  • name - License name
  • url - License URL

Example:

openapi.WithLicense("Apache 2.0", "https://www.apache.org/licenses/LICENSE-2.0.html")

WithLicenseIdentifier

func WithLicenseIdentifier(name, identifier string) Option

Sets license with SPDX identifier. OpenAPI 3.1 only.

Parameters:

  • name - License name
  • identifier - SPDX license identifier

Example:

openapi.WithLicenseIdentifier("Apache 2.0", "Apache-2.0")

WithInfoExtension

func WithInfoExtension(key string, value any) Option

Adds a custom extension to the info object.

Parameters:

  • key - Extension key (must start with x-)
  • value - Extension value

Example:

openapi.WithInfoExtension("x-api-id", "user-service")

Version Options

WithVersion

func WithVersion(version Version) Option

Sets the target OpenAPI version. Default is V30x.

Parameters:

  • version - Either V30x or V31x

Example:

openapi.WithVersion(openapi.V31x)

Server Options

WithServer

func WithServer(url, description string) Option

Adds a server configuration.

Parameters:

  • url - Server URL
  • description - Server description

Example:

openapi.WithServer("https://api.example.com", "Production")
openapi.WithServer("http://localhost:8080", "Development")

WithServerVariable

func WithServerVariable(name, defaultValue string, enumValues []string, description string) Option

Adds a server variable for URL templating.

Parameters:

  • name - Variable name
  • defaultValue - Default value
  • enumValues - Allowed values
  • description - Variable description

Example:

openapi.WithServer("https://{environment}.example.com", "Environment-based"),
openapi.WithServerVariable("environment", "api", 
    []string{"api", "staging", "dev"},
    "Environment to use",
)

Security Scheme Options

WithBearerAuth

func WithBearerAuth(name, description string) Option

Adds Bearer (JWT) authentication scheme.

Parameters:

  • name - Security scheme name (used in WithSecurity())
  • description - Scheme description

Example:

openapi.WithBearerAuth("bearerAuth", "JWT authentication")

WithAPIKey

func WithAPIKey(name, paramName string, location ParameterLocation, description string) Option

Adds API key authentication scheme.

Parameters:

  • name - Security scheme name
  • paramName - Parameter name (e.g., “X-API-Key”, “api_key”)
  • location - Where the key is located: InHeader, InQuery, or InCookie
  • description - Scheme description

Example:

openapi.WithAPIKey("apiKey", "X-API-Key", openapi.InHeader, "API key for authentication")

WithOAuth2AuthorizationCode

func WithOAuth2AuthorizationCode(name, desc, authURL, tokenURL, refreshURL string, scopes map[string]string) Option

Adds the OAuth2 authorization code flow to the named scheme. authURL and tokenURL are required; refreshURL is optional. If a scheme with the same name already exists (e.g. from another flow option), the flow is merged into it.

Example:

openapi.WithOAuth2AuthorizationCode("oauth2", "OAuth2 authentication",
    "https://example.com/oauth/authorize", "https://example.com/oauth/token", "https://example.com/oauth/refresh",
    map[string]string{"read": "Read access", "write": "Write access"})

WithOAuth2Implicit

func WithOAuth2Implicit(name, desc, authURL, refreshURL string, scopes map[string]string) Option

Adds the OAuth2 implicit flow. authURL is required; refreshURL is optional.

Example:

openapi.WithOAuth2Implicit("oauth2", "OAuth2 authentication",
    "https://example.com/oauth/authorize", "",
    map[string]string{"read": "Read access"})

WithOAuth2Password

func WithOAuth2Password(name, desc, tokenURL, refreshURL string, scopes map[string]string) Option

Adds the OAuth2 resource owner password flow. tokenURL is required; refreshURL is optional.

Example:

openapi.WithOAuth2Password("oauth2", "OAuth2 authentication",
    "https://example.com/oauth/token", "",
    map[string]string{"read": "Read access"})

WithOAuth2ClientCredentials

func WithOAuth2ClientCredentials(name, desc, tokenURL, refreshURL string, scopes map[string]string) Option

Adds the OAuth2 client credentials flow. tokenURL is required; refreshURL is optional.

Example:

openapi.WithOAuth2ClientCredentials("oauth2", "OAuth2 authentication",
    "https://example.com/oauth/token", "",
    map[string]string{"api": "API access"})

WithOpenIDConnect

func WithOpenIDConnect(name, openIDConnectURL, description string) Option

Adds OpenID Connect authentication scheme.

Parameters:

  • name - Security scheme name
  • openIDConnectURL - OpenID Connect discovery URL
  • description - Scheme description

Example:

openapi.WithOpenIDConnect("openId", "https://example.com/.well-known/openid-configuration", "OpenID Connect")

WithDefaultSecurity

func WithDefaultSecurity(requirements ...SecurityReq) Option

Sets default security requirements at API level. Use [RequireSecurity] to build each requirement.

Example:

openapi.WithDefaultSecurity(openapi.RequireSecurity("bearerAuth"))
openapi.WithDefaultSecurity(openapi.RequireSecurity("oauth2", "read", "write"))

RequireSecurity

func RequireSecurity(scheme string, scopes ...string) SecurityReq

Builds a [SecurityReq] for use with [WithDefaultSecurity] or operation [WithSecurity].

Tag Options

WithTag

func WithTag(name, description string) Option

Adds a tag for organizing operations.

Parameters:

  • name - Tag name
  • description - Tag description

Example:

openapi.WithTag("users", "User management operations")
openapi.WithTag("posts", "Post management operations")

External Documentation

WithExternalDocs

func WithExternalDocs(url, description string) Option

Links to external documentation.

Parameters:

  • url - Documentation URL
  • description - Documentation description

Example:

openapi.WithExternalDocs("https://docs.example.com", "Full API Documentation")

Validation Options

WithValidateSpec

func WithValidateSpec(validate bool) Option

Enables or disables JSON Schema validation of the generated spec. Default is false.

Example:

openapi.WithValidateSpec(true)

WithStrictDownlevel

func WithStrictDownlevel(enabled bool) Option

Enables strict downlevel mode. When enabled, using 3.1 features with a 3.0 target causes errors instead of warnings. Default is false.

Parameters:

  • enabled - Whether to error on downlevel issues

Example:

openapi.WithStrictDownlevel(true) // Error on 3.1 features with 3.0 target

WithSpecPath

func WithSpecPath(path string) Option

Sets the path where the OpenAPI specification will be served.

Parameters:

  • path - URL path for the spec (e.g., “/openapi.json”)

Example:

openapi.WithSpecPath("/api/openapi.json")

Swagger UI Options

WithSwaggerUI

func WithSwaggerUI(path string, opts ...UIOption) Option

Configures Swagger UI at the specified path.

Parameters:

  • path - URL path where Swagger UI is served
  • opts - Swagger UI configuration options (see Swagger UI Options)

Example:

openapi.WithSwaggerUI("/docs",
    openapi.WithUIExpansion(openapi.DocExpansionList),
    openapi.WithUITryItOut(true),
)

WithoutSwaggerUI

func WithoutSwaggerUI() Option

Disables Swagger UI.

Example:

openapi.WithoutSwaggerUI()

Extension Options

WithExtension

func WithExtension(key string, value interface{}) Option

Adds a custom x-* extension to the root of the specification.

Parameters:

  • key - Extension key (must start with x-)
  • value - Extension value (any JSON-serializable type)

Example:

openapi.WithExtension("x-api-version", "v2")
openapi.WithExtension("x-custom-config", map[string]interface{}{
    "feature": "enabled",
    "rate-limit": 100,
})

Next Steps

3 - Operation Options

Complete reference for operation-level configuration options

Complete reference for all operation-level configuration options (functions passed to HTTP method constructors).

Operation constructors (WithGET, WithPOST, etc.) return an error for invalid paths (e.g. missing leading slash, invalid parameter syntax) instead of panicking.

Metadata Options

WithSummary

func WithSummary(summary string) OperationOption

Sets the operation summary (short description).

Example:

openapi.WithSummary("Get user by ID")

WithOperationDescription

func WithOperationDescription(description string) OperationOption

Sets the operation description (detailed explanation).

Example:

openapi.WithOperationDescription("Retrieves a user by their unique identifier from the database")

WithOperationID

func WithOperationID(operationID string) OperationOption

Sets a custom operation ID. By default, operation IDs are auto-generated from method and path.

Example:

openapi.WithOperationID("getUserById")

Request and Response Options

WithRequest

func WithRequest(requestType interface{}, examples ...interface{}) OperationOption

Sets the request body type with optional named examples.

Parameters:

  • requestType - Go type to convert to schema
  • examples - Named examples (from rivaas.dev/openapi/example) or a single value for the default example

Example:

// Single unnamed example
openapi.WithRequest(CreateUserRequest{}, CreateUserRequest{Name: "John", Email: "john@example.com"})

// Named examples (use the example package)
openapi.WithRequest(CreateUserRequest{},
    example.New("minimal", CreateUserRequest{Name: "J", Email: "j@example.com"}),
    example.New("full", CreateUserRequest{Name: "John", Email: "john@example.com"}, example.WithSummary("Full example")),
)

WithResponse

func WithResponse(statusCode int, responseType interface{}, examples ...interface{}) OperationOption

Adds a response type for a specific status code.

Parameters:

  • statusCode - HTTP status code
  • responseType - Go type to convert to schema (use nil for no body)
  • examples - Named examples (from rivaas.dev/openapi/example) or a single value for the default example

Example:

openapi.WithResponse(200, User{})
openapi.WithResponse(204, nil) // No response body
openapi.WithResponse(404, ErrorResponse{})

// Named examples for a status
openapi.WithResponse(200, User{},
    example.New("success", User{ID: 1, Name: "John"}, example.WithSummary("Success")),
    example.New("admin", User{ID: 1, Name: "Admin", Role: "admin"}, example.WithSummary("Admin user")),
)

Organization Options

WithTags

func WithTags(tags ...string) OperationOption

Adds tags to the operation for organization.

Parameters:

  • tags - Tag names

Example:

openapi.WithTags("users")
openapi.WithTags("users", "admin")

Security Options

WithSecurity

func WithSecurity(scheme string, scopes ...string) OperationOption

Adds a security requirement to the operation.

Parameters:

  • scheme - Security scheme name (defined with WithBearerAuth, WithAPIKey, etc.)
  • scopes - Optional OAuth2 scopes

Example:

openapi.WithSecurity("bearerAuth")
openapi.WithSecurity("oauth2", "read", "write")

Multiple calls create alternative security requirements (OR logic):

openapi.WithGET("/users/:id",
    openapi.WithSecurity("bearerAuth"),  // Can use bearer auth
    openapi.WithSecurity("apiKey"),      // OR can use API key
    openapi.WithResponse(200, User{}),
)

Content Type Options

WithConsumes

func WithConsumes(contentTypes ...string) OperationOption

Sets accepted content types for the request.

Parameters:

  • contentTypes - MIME types

Example:

openapi.WithConsumes("application/json", "application/xml")

WithProduces

func WithProduces(contentTypes ...string) OperationOption

Sets returned content types for the response.

Parameters:

  • contentTypes - MIME types

Example:

openapi.WithProduces("application/json", "application/xml")

Deprecation

WithDeprecated

func WithDeprecated(deprecated ...bool) OperationOption

Marks the operation as deprecated. WithDeprecated() is shorthand for true; WithDeprecated(false) clears deprecation.

Example:

openapi.WithGET("/users/legacy",
    openapi.WithSummary("Legacy user list"),
    openapi.WithDeprecated(),
    openapi.WithResponse(200, []User{}),
)

Extension Options

WithOperationExtension

func WithOperationExtension(key string, value any) OperationOption

Adds a custom x-* extension to the operation.

Parameters:

  • key - Extension key (must start with x-)
  • value - Extension value (any JSON-serializable type)

Example:

openapi.WithOperationExtension("x-rate-limit", 100)
openapi.WithOperationExtension("x-cache-ttl", 300)

Composable Options

WithOptions

func WithOptions(opts ...OperationOption) (OperationOption, error)

Combines multiple operation options into a single reusable option. Returns an error if any element of opts is nil (validation at compose time).

Parameters:

  • opts - Operation options to combine

Example:

CommonErrors, err := openapi.WithOptions(
    openapi.WithResponse(400, ErrorResponse{}),
    openapi.WithResponse(500, ErrorResponse{}),
)
if err != nil {
    // handle err (e.g. log.Fatal(err))
}

UserEndpoint, err := openapi.WithOptions(
    openapi.WithTags("users"),
    openapi.WithSecurity("bearerAuth"),
    CommonErrors,
)
if err != nil {
    // handle err
}

// Use in operations
openapi.WithGET("/users/:id",
    UserEndpoint,
    openapi.WithSummary("Get user"),
    openapi.WithResponse(200, User{}),
)

Option Summary Table

OptionDescription
WithSummary(s)Set operation summary
WithOperationDescription(s)Set operation description
WithOperationID(id)Set custom operation ID
WithRequest(type, examples...)Set request body type
WithResponse(status, type, examples...)Set response type for status code
WithTags(tags...)Add tags to operation
WithSecurity(scheme, scopes...)Add security requirement
WithDeprecated()Mark operation as deprecated
WithConsumes(types...)Set accepted content types
WithProduces(types...)Set returned content types
WithOperationExtension(key, value)Add operation extension
WithOptions(opts...)Combine options into reusable set

Next Steps

4 - Swagger UI Options

Complete reference for Swagger UI configuration options

Complete reference for all Swagger UI configuration options (functions passed to WithSwaggerUI()).

Display Options

WithUIExpansion

func WithUIExpansion(expansion DocExpansion) UIOption

Controls initial document expansion.

Parameters:

  • expansion - DocExpansionList, DocExpansionFull, or DocExpansionNone

Values:

  • DocExpansionList - Show endpoints, hide details (default)
  • DocExpansionFull - Show endpoints and details
  • DocExpansionNone - Hide everything

Example:

openapi.WithUIExpansion(openapi.DocExpansionFull)

WithUIDefaultModelRendering

func WithUIDefaultModelRendering(rendering ModelRendering) UIOption

Controls how models/schemas are rendered.

Parameters:

  • rendering - ModelRenderingExample or ModelRenderingModel

Example:

openapi.WithUIDefaultModelRendering(openapi.ModelRenderingExample)

WithUIModelExpandDepth

func WithUIModelExpandDepth(depth int) UIOption

Controls how deeply a single model is expanded.

Parameters:

  • depth - Expansion depth (-1 to disable, 1 for shallow, higher for deeper)

Example:

openapi.WithUIModelExpandDepth(2)

WithUIModelsExpandDepth

func WithUIModelsExpandDepth(depth int) UIOption

Controls how deeply the models section is expanded.

Example:

openapi.WithUIModelsExpandDepth(1)

WithUIDisplayOperationID

func WithUIDisplayOperationID(display bool) UIOption

Shows operation IDs alongside summaries.

Example:

openapi.WithUIDisplayOperationID(true)

Try It Out Options

WithUITryItOut

func WithUITryItOut(enabled bool) UIOption

Enables “Try it out” functionality.

Example:

openapi.WithUITryItOut(true)

WithUIRequestSnippets

func WithUIRequestSnippets(enabled bool, languages ...RequestSnippetLanguage) UIOption

Shows code snippets for making requests.

Parameters:

  • enabled - Whether to show snippets
  • languages - Snippet languages to show

Languages:

  • SnippetCurlBash - curl for bash/sh shells
  • SnippetCurlPowerShell - curl for PowerShell
  • SnippetCurlCmd - curl for Windows CMD

Example:

openapi.WithUIRequestSnippets(true,
    openapi.SnippetCurlBash,
    openapi.SnippetCurlPowerShell,
    openapi.SnippetCurlCmd,
)

WithUIRequestSnippetsExpanded

func WithUIRequestSnippetsExpanded(expanded bool) UIOption

Expands request snippets by default.

Example:

openapi.WithUIRequestSnippetsExpanded(true)

WithUIDisplayRequestDuration

func WithUIDisplayRequestDuration(display bool) UIOption

Shows how long requests take.

Example:

openapi.WithUIDisplayRequestDuration(true)

Filtering and Sorting Options

WithUIFilter

func WithUIFilter(enabled bool) UIOption

Enables filter/search box.

Example:

openapi.WithUIFilter(true)

WithUIMaxDisplayedTags

func WithUIMaxDisplayedTags(max int) UIOption

Limits the number of tags displayed.

Example:

openapi.WithUIMaxDisplayedTags(10)

WithUIOperationsSorter

func WithUIOperationsSorter(sorter OperationsSorter) UIOption

Sets operation sorting method.

Parameters:

  • sorter - OperationsSorterAlpha or OperationsSorterMethod

Example:

openapi.WithUIOperationsSorter(openapi.OperationsSorterAlpha)

WithUITagsSorter

func WithUITagsSorter(sorter TagsSorter) UIOption

Sets tag sorting method.

Parameters:

  • sorter - TagsSorterAlpha

Example:

openapi.WithUITagsSorter(openapi.TagsSorterAlpha)

Syntax Highlighting Options

WithUISyntaxHighlight

func WithUISyntaxHighlight(enabled bool) UIOption

Enables syntax highlighting.

Example:

openapi.WithUISyntaxHighlight(true)

WithUISyntaxTheme

func WithUISyntaxTheme(theme SyntaxTheme) UIOption

Sets syntax highlighting theme.

Available Themes:

  • SyntaxThemeAgate - Dark theme with blue accents
  • SyntaxThemeArta - Dark theme with orange accents
  • SyntaxThemeMonokai - Dark theme with vibrant colors
  • SyntaxThemeNord - Dark theme with cool blue tones
  • SyntaxThemeObsidian - Dark theme with green accents
  • SyntaxThemeTomorrowNight - Dark theme with muted colors
  • SyntaxThemeIdea - Light theme similar to IntelliJ IDEA

Example:

openapi.WithUISyntaxTheme(openapi.SyntaxThemeMonokai)

Authentication Options

WithUIPersistAuth

func WithUIPersistAuth(persist bool) UIOption

Persists authentication across browser refreshes.

Example:

openapi.WithUIPersistAuth(true)

WithUIWithCredentials

func WithUIWithCredentials(withCredentials bool) UIOption

Includes credentials in requests.

Example:

openapi.WithUIWithCredentials(true)

Additional Options

WithUIDeepLinking

func WithUIDeepLinking(enabled bool) UIOption

Enables deep linking for tags and operations.

Example:

openapi.WithUIDeepLinking(true)

WithUIShowExtensions

func WithUIShowExtensions(show bool) UIOption

Shows vendor extensions (x-*) in the UI.

Example:

openapi.WithUIShowExtensions(true)

WithUIShowCommonExtensions

func WithUIShowCommonExtensions(show bool) UIOption

Shows common extensions in the UI.

Example:

openapi.WithUIShowCommonExtensions(true)

WithUISupportedMethods

func WithUISupportedMethods(methods ...HTTPMethod) UIOption

Configures which HTTP methods are supported for “Try it out”.

Parameters:

  • methods - HTTP method constants (MethodGet, MethodPost, MethodPut, etc.)

Example:

openapi.WithUISupportedMethods(
    openapi.MethodGet,
    openapi.MethodPost,
    openapi.MethodPut,
    openapi.MethodDelete,
)

Validation Options

WithUIValidator

func WithUIValidator(url string) UIOption

Sets specification validator.

Parameters:

  • url - ValidatorLocal, ValidatorNone, or custom validator URL

Example:

openapi.WithUIValidator(openapi.ValidatorLocal)
openapi.WithUIValidator("https://validator.swagger.io/validator")
openapi.WithUIValidator(openapi.ValidatorNone)

Complete Example

openapi.WithSwaggerUI("/docs",
    // Display
    openapi.WithUIExpansion(openapi.DocExpansionList),
    openapi.WithUIModelExpandDepth(1),
    openapi.WithUIDisplayOperationID(true),
    
    // Try it out
    openapi.WithUITryItOut(true),
    openapi.WithUIRequestSnippets(true,
        openapi.SnippetCurlBash,
        openapi.SnippetCurlPowerShell,
        openapi.SnippetCurlCmd,
    ),
    openapi.WithUIDisplayRequestDuration(true),
    
    // Filtering/Sorting
    openapi.WithUIFilter(true),
    openapi.WithUIOperationsSorter(openapi.OperationsSorterAlpha),
    
    // Syntax
    openapi.WithUISyntaxHighlight(true),
    openapi.WithUISyntaxTheme(openapi.SyntaxThemeMonokai),
    
    // Auth
    openapi.WithUIPersistAuth(true),
    
    // Validation
    openapi.WithUIValidator(openapi.ValidatorLocal),
)

Next Steps

5 - Diagnostics

Warning system reference with codes and categories

Complete reference for the warning diagnostics system in rivaas.dev/openapi/diag.

Package Import

import "rivaas.dev/openapi/diag"

Warning Interface

type Warning interface {
    Code() WarningCode
    Message() string
    Path() string
    Category() WarningCategory
}

Individual warning with diagnostic information.

Methods:

  • Code() - Returns type-safe warning code
  • Message() - Returns human-readable message
  • Path() - Returns location in spec (e.g., “info.summary”)
  • Category() - Returns warning category

Warnings Collection

type Warnings []Warning

Collection of warnings with helper methods.

Has

func (w Warnings) Has(code WarningCode) bool

Checks if collection contains a specific warning code.

Example:

if result.Warnings.Has(diag.WarnDownlevelInfoSummary) {
    log.Warn("info.summary was dropped")
}

HasAny

func (w Warnings) HasAny(codes ...WarningCode) bool

Checks if collection contains any of the specified warning codes.

Example:

if result.Warnings.HasAny(
    diag.WarnDownlevelMutualTLS,
    diag.WarnDownlevelWebhooks,
) {
    log.Warn("Some 3.1 security features were dropped")
}

Filter

func (w Warnings) Filter(code WarningCode) Warnings

Returns warnings matching the specified code.

Example:

licenseWarnings := result.Warnings.Filter(diag.WarnDownlevelLicenseIdentifier)

FilterCategory

func (w Warnings) FilterCategory(category WarningCategory) Warnings

Returns warnings in the specified category.

Example:

downlevelWarnings := result.Warnings.FilterCategory(diag.CategoryDownlevel)

Exclude

func (w Warnings) Exclude(codes ...WarningCode) Warnings

Returns warnings excluding the specified codes.

Example:

expected := []diag.WarningCode{
    diag.WarnDownlevelInfoSummary,
}
unexpected := result.Warnings.Exclude(expected...)

Warning Codes

WarningCode Type

type WarningCode string

Type-safe warning code constant.

Downlevel Warning Codes

Warnings generated when using 3.1 features with a 3.0 target:

ConstantCode ValueDescription
WarnDownlevelWebhooksDOWNLEVEL_WEBHOOKSWebhooks dropped (3.0 doesn’t support them)
WarnDownlevelInfoSummaryDOWNLEVEL_INFO_SUMMARYinfo.summary dropped (3.0 doesn’t support it)
WarnDownlevelLicenseIdentifierDOWNLEVEL_LICENSE_IDENTIFIERlicense.identifier dropped
WarnDownlevelMutualTLSDOWNLEVEL_MUTUAL_TLSmutualTLS security scheme dropped
WarnDownlevelConstToEnumDOWNLEVEL_CONST_TO_ENUMJSON Schema const converted to enum
WarnDownlevelConstToEnumConflictDOWNLEVEL_CONST_TO_ENUM_CONFLICTconst conflicted with existing enum
WarnDownlevelPathItemsDOWNLEVEL_PATH_ITEMS$ref in pathItems was expanded
WarnDownlevelPatternPropertiesDOWNLEVEL_PATTERN_PROPERTIESpatternProperties dropped
WarnDownlevelUnevaluatedPropertiesDOWNLEVEL_UNEVALUATED_PROPERTIESunevaluatedProperties dropped
WarnDownlevelContentEncodingDOWNLEVEL_CONTENT_ENCODINGcontentEncoding dropped
WarnDownlevelContentMediaTypeDOWNLEVEL_CONTENT_MEDIA_TYPEcontentMediaType dropped
WarnDownlevelMultipleExamplesDOWNLEVEL_MULTIPLE_EXAMPLESMultiple examples collapsed to one
const (
    WarnDownlevelWebhooks              WarningCode = "DOWNLEVEL_WEBHOOKS"
    WarnDownlevelInfoSummary           WarningCode = "DOWNLEVEL_INFO_SUMMARY"
    WarnDownlevelLicenseIdentifier     WarningCode = "DOWNLEVEL_LICENSE_IDENTIFIER"
    WarnDownlevelMutualTLS             WarningCode = "DOWNLEVEL_MUTUAL_TLS"
    WarnDownlevelConstToEnum           WarningCode = "DOWNLEVEL_CONST_TO_ENUM"
    WarnDownlevelConstToEnumConflict   WarningCode = "DOWNLEVEL_CONST_TO_ENUM_CONFLICT"
    WarnDownlevelPathItems             WarningCode = "DOWNLEVEL_PATH_ITEMS"
    WarnDownlevelPatternProperties     WarningCode = "DOWNLEVEL_PATTERN_PROPERTIES"
    WarnDownlevelUnevaluatedProperties WarningCode = "DOWNLEVEL_UNEVALUATED_PROPERTIES"
    WarnDownlevelContentEncoding       WarningCode = "DOWNLEVEL_CONTENT_ENCODING"
    WarnDownlevelContentMediaType      WarningCode = "DOWNLEVEL_CONTENT_MEDIA_TYPE"
    WarnDownlevelMultipleExamples      WarningCode = "DOWNLEVEL_MULTIPLE_EXAMPLES"
)

Deprecation Warning Codes

Warnings for deprecated feature usage:

ConstantCode ValueDescription
WarnDeprecationExampleSingularDEPRECATION_EXAMPLE_SINGULARUsing deprecated singular example field
const (
    WarnDeprecationExampleSingular WarningCode = "DEPRECATION_EXAMPLE_SINGULAR"
)

Warning Categories

WarningCategory Type

type WarningCategory string

Category grouping for warnings.

Category Constants

CategoryDescription
CategoryDownlevel3.1 to 3.0 conversion feature losses (spec is still valid)
CategoryDeprecationDeprecated feature usage (feature still works but is discouraged)
CategoryUnknownUnrecognized warning codes
const (
    CategoryDownlevel   WarningCategory = "downlevel"
    CategoryDeprecation WarningCategory = "deprecation"
    CategoryUnknown     WarningCategory = "unknown"
)

Usage Examples

Check for Specific Warning

import "rivaas.dev/openapi/diag"

result, err := api.Generate(context.Background(), ops...)
if err != nil {
    log.Fatal(err)
}

if result.Warnings.Has(diag.WarnDownlevelInfoSummary) {
    log.Warn("info.summary was dropped (3.1 feature with 3.0 target)")
}

Filter by Category

downlevelWarnings := result.Warnings.FilterCategory(diag.CategoryDownlevel)
if len(downlevelWarnings) > 0 {
    fmt.Printf("Downlevel warnings: %d\n", len(downlevelWarnings))
    for _, warn := range downlevelWarnings {
        fmt.Printf("  [%s] %s at %s\n", 
            warn.Code(), 
            warn.Message(), 
            warn.Path(),
        )
    }
}

Check for Unexpected Warnings

expected := []diag.WarningCode{
    diag.WarnDownlevelInfoSummary,
    diag.WarnDownlevelLicenseIdentifier,
}

unexpected := result.Warnings.Exclude(expected...)
if len(unexpected) > 0 {
    log.Fatalf("Unexpected warnings: %d", len(unexpected))
}

Iterate All Warnings

for _, warn := range result.Warnings {
    fmt.Printf("[%s] %s\n", warn.Code(), warn.Message())
    fmt.Printf("  Location: %s\n", warn.Path())
    fmt.Printf("  Category: %s\n", warn.Category())
}

Complete Example

package main

import (
    "context"
    "fmt"
    "log"
    
    "rivaas.dev/openapi"
    "rivaas.dev/openapi/diag"
)

func main() {
    api := openapi.MustNew(
        openapi.WithTitle("My API", "1.0.0"),
        openapi.WithVersion(openapi.V30x),
        openapi.WithInfoSummary("API Summary"), // 3.1 feature
    )
    
    result, err := api.Generate(context.Background(), operations...)
    if err != nil {
        log.Fatal(err)
    }
    
    // Handle specific warnings
    if result.Warnings.Has(diag.WarnDownlevelInfoSummary) {
        fmt.Println("Note: info.summary was dropped")
    }
    
    // Filter by category
    downlevelWarnings := result.Warnings.FilterCategory(diag.CategoryDownlevel)
    fmt.Printf("Downlevel warnings: %d\n", len(downlevelWarnings))
    
    // Check for unexpected
    expected := []diag.WarningCode{
        diag.WarnDownlevelInfoSummary,
    }
    unexpected := result.Warnings.Exclude(expected...)
    
    if len(unexpected) > 0 {
        fmt.Printf("UNEXPECTED warnings: %d\n", len(unexpected))
        for _, warn := range unexpected {
            fmt.Printf("  [%s] %s\n", warn.Code(), warn.Message())
        }
        log.Fatal("Unexpected warnings found")
    }
    
    fmt.Println("Generation complete")
}

Next Steps

6 - Troubleshooting

Common issues and solutions

Common issues and solutions for the openapi package.

Schema Name Collisions

Problem

Types with the same name in different packages may collide in the generated specification.

Solution

The package automatically uses pkgname.TypeName format for schema names:

// In package "api"
type User struct { ... }  // Becomes "api.User"

// In package "models"  
type User struct { ... }  // Becomes "models.User"

If you need custom schema names, use the openapi struct tag:

type User struct {
    ID   int    `json:"id" openapi:"name=CustomUser"`
    Name string `json:"name"`
}

Extension Validation

Problem

Custom extensions are rejected or filtered out.

Solution

Extensions must follow OpenAPI rules:

Valid:

openapi.WithExtension("x-custom", "value")
openapi.WithExtension("x-api-version", "v2")

Invalid:

// Missing x- prefix
openapi.WithExtension("custom", "value") // Error

// Reserved prefix in 3.1.x
openapi.WithExtension("x-oai-custom", "value") // Filtered out in 3.1.x
openapi.WithExtension("x-oas-custom", "value") // Filtered out in 3.1.x

Version Compatibility

Problem

Using OpenAPI 3.1 features with a 3.0 target generates warnings or errors.

Solution

When using OpenAPI 3.0.x target, some 3.1.x features are automatically down-leveled:

Feature3.0 Behavior
info.summaryDropped (warning)
license.identifierDropped (warning)
const in schemasConverted to enum with single value
examples (multiple)Converted to single example
webhooksDropped (warning)
mutualTLS securityDropped (warning)

Options:

  1. Accept warnings (default):
api := openapi.MustNew(
    openapi.WithVersion(openapi.V30x),
    openapi.WithInfoSummary("Summary"), // Generates warning
)

result, err := api.Generate(context.Background(), ops...)
// Check result.Warnings
  1. Enable strict mode (error on 3.1 features):
api := openapi.MustNew(
    openapi.WithVersion(openapi.V30x),
    openapi.WithStrictDownlevel(true), // Error on 3.1 features
    openapi.WithInfoSummary("Summary"), // Causes error
)
  1. Use 3.1 target:
api := openapi.MustNew(
    openapi.WithVersion(openapi.V31x), // All features available
    openapi.WithInfoSummary("Summary"), // No warning
)

Parameters Not Discovered

Problem

Parameters are not appearing in the generated specification.

Solution

Ensure struct tags are correct:

Common Issues:

// Wrong tag name
type Request struct {
    ID int `params:"id"` // Should be "path", "query", "header", or "cookie"
}

// Missing tag
type Request struct {
    ID int // No tag - won't be discovered
}

// Wrong location
type Request struct {
    ID int `query:"id"` // Should be "path" for path parameters
}

Correct:

type Request struct {
    // Path parameters
    ID int `path:"id" doc:"User ID"`
    
    // Query parameters
    Page int `query:"page" doc:"Page number"`
    
    // Header parameters
    Auth string `header:"Authorization" doc:"Auth token"`
    
    // Cookie parameters
    Session string `cookie:"session_id" doc:"Session ID"`
}

Validation Errors

Problem

Generated specification fails validation.

Solution

Enable validation to get detailed error messages:

api := openapi.MustNew(
    openapi.WithTitle("My API", "1.0.0"),
    openapi.WithValidation(true), // Enable validation
)

result, err := api.Generate(context.Background(), ops...)
if err != nil {
    log.Printf("Validation failed: %v\n", err)
}

Common validation errors:

  1. Missing required fields:
// Missing version
openapi.MustNew(
    openapi.WithTitle("My API", ""), // Version required
)
  1. Invalid URLs:
// Invalid server URL
openapi.WithServer("not-a-url", "Server")
  1. Invalid enum values:
type Request struct {
    Status string `json:"status" enum:"active"` // Missing comma-separated values
}

Performance Issues

Problem

Specification generation is slow.

Solution

Typical performance:

  • First generation per type: ~500ns (reflection)
  • Subsequent generations: ~50ns (cached)
  • Validation overhead: 10-20ms first time, 1-5ms subsequent

Optimization tips:

  1. Disable validation in production:
api := openapi.MustNew(
    openapi.WithTitle("API", "1.0.0"),
    openapi.WithValidation(false), // Disable for production
)
  1. Generate once, cache result:
var cachedSpec []byte
var once sync.Once

func getSpec() []byte {
    once.Do(func() {
        result, _ := api.Generate(context.Background(), ops...)
        cachedSpec = result.JSON
    })
    return cachedSpec
}
  1. Pre-generate at build time:
# generate-spec.go
go run generate-spec.go > openapi.json

Schema Generation Issues

Problem

Go types are not converted correctly to OpenAPI schemas.

Solution

Supported types:

type Example struct {
    // Primitives
    String  string  `json:"string"`
    Int     int     `json:"int"`
    Bool    bool    `json:"bool"`
    Float   float64 `json:"float"`
    
    // Pointers (nullable)
    Optional *string `json:"optional,omitempty"`
    
    // Slices
    Tags []string `json:"tags"`
    
    // Maps
    Metadata map[string]string `json:"metadata"`
    
    // Nested structs
    Address Address `json:"address"`
    
    // Time
    CreatedAt time.Time `json:"created_at"`
}

Unsupported types:

type Unsupported struct {
    Channel chan int        // Not supported
    Func    func()          // Not supported
    Complex complex64       // Not supported
}

Workaround for unsupported types:

Use custom types or JSON marshaling:

type CustomType struct {
    data interface{}
}

func (c CustomType) MarshalJSON() ([]byte, error) {
    // Custom marshaling logic
}

Context Errors

Problem

Generate() returns “context is nil” error.

Solution

Always provide a valid context:

// Wrong
result, err := api.Generate(nil, ops...) // Error

// Correct
result, err := api.Generate(context.Background(), ops...)
result, err := api.Generate(ctx, ops...) // With existing context

Common FAQ

Q: How do I make a parameter optional?

A: For query/header/cookie parameters, omit validate:"required" tag. For request body fields, use pointer types or omitempty:

type Request struct {
    Required string  `json:"required" validate:"required"`
    Optional *string `json:"optional,omitempty"`
}

Q: How do I add multiple examples?

A: Pass multiple example instances to WithRequest() or WithResponse():

example1 := User{ID: 1, Name: "Alice"}
example2 := User{ID: 2, Name: "Bob"}

openapi.WithResponse(200, User{}, example1, example2)

Q: Can I generate specs for existing handlers?

A: Yes, define types that match your handlers and pass them to operations:

// Handler
func GetUser(id int) (*User, error) { ... }

// OpenAPI
openapi.GET("/users/:id",
    openapi.WithResponse(200, User{}),
)

Q: How do I document error responses?

A: Use multiple WithResponse() calls:

openapi.GET("/users/:id",
    openapi.WithResponse(200, User{}),
    openapi.WithResponse(400, ErrorResponse{}),
    openapi.WithResponse(404, ErrorResponse{}),
    openapi.WithResponse(500, ErrorResponse{}),
)

Q: Can I use this with existing OpenAPI specs?

A: Use the validate package to validate external specs:

import "rivaas.dev/openapi/validate"

validator := validate.MustNew()
err := validator.ValidateAuto(context.Background(), specJSON)

Getting Help

If you encounter issues not covered here:

  1. Check the pkg.go.dev documentation
  2. Review examples
  3. Search GitHub issues
  4. Open a new issue with a minimal reproduction

Next Steps