Core Package
The root openswag package contains every type you need to define an OpenAPI spec and serve interactive documentation from your Go application.
Config
Top-level configuration passed to openswag.New().
type Config struct {
Info Info // API metadata (title, version, description)
Servers []Server // Server URLs shown in the docs UI
Tags []Tag // Logical groupings for endpoints
UI UIConfig // Scalar UI appearance settings
Auth AuthConfig // Security schemes exposed under components.securitySchemes
DocsAuth *DocsAuth // Optional password/API-key protection for the docs page
InlineSchemas bool // Inline every struct instead of emitting components.schemas (v1.3.0+)
}The mount path (e.g.
/docs) is passed todocs.Mount(mux, "/docs"), not configured onConfig.
Fields
| Field | Type | Description |
|---|---|---|
Info | Info | API title, version, description, contact, and license |
Servers | []Server | Base URLs displayed in the server dropdown |
Tags | []Tag | Grouping tags that organise endpoints in the sidebar |
UI | UIConfig | Theme, layout, and Scalar UI options |
Auth | AuthConfig | Security schemes exposed under components.securitySchemes |
DocsAuth | *DocsAuth | Protect the docs page with basic auth or an API key |
InlineSchemas | bool | Default false: every named struct used in a request or response body is emitted once under components.schemas and referenced with $ref. true restores the pre-v1.3.0 output: every struct inlined at each use and recursive back-edges cut off with {type: object, description: "Recursive reference to ..."}. See Schema Components (v1.3.0+) |
Docs
Docs is the main handle returned by openswag.New(). It holds the compiled spec and serves the UI.
func New(cfg Config) *Docstype Docs struct {
// unexported fields
}
func (d *Docs) Add(endpoint Endpoint) // Register one endpoint
func (d *Docs) AddAll(endpoints ...Endpoint) // Register multiple endpoints
func (d *Docs) Validate() error // Report invalid endpoint definitions (v1.3.0+)
func (d *Docs) Mount(mux *http.ServeMux, basePath string) // Serve UI + spec on a ServeMux
func (d *Docs) Handler() http.HandlerFunc // Handler that serves the docs UI
func (d *Docs) SpecHandler() http.HandlerFunc // Handler that serves the raw OpenAPI JSON
func (d *Docs) SpecJSON() ([]byte, error) // The OpenAPI spec as JSON bytes
func (d *Docs) BuildSpec() *spec.OpenAPI // The compiled spec object
func (d *Docs) GetUIConfig() (string, error) // Serialized UI config (advanced)Add and AddAll never fail: BuildSpec keeps the last of two endpoints with the same method and path and skips unsupported methods. Validate (v1.3.0+) returns one joined error (errors.Join) listing every duplicate method+path pair (compared after upper-casing the method and normalising /users/:id to /users/{id}), every method other than GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS and TRACE, and every duplicate operationId. It returns nil when everything is valid. Call it once after AddAll and treat an error as fatal.
Usage
docs := openswag.New(cfg)
docs.AddAll(endpoints...)
if err := docs.Validate(); err != nil {
log.Fatal(err)
}
// Serve with net/http
mux := http.NewServeMux()
docs.Mount(mux, "/docs")
http.ListenAndServe(":8080", mux)Endpoint
Describes a single API operation.
type Endpoint struct {
Method string // GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, TRACE
Path string // "/users/{id}"; "/users/:id", "/files/*path" are normalised
OperationID string // Overrides the generated operationId (v1.3.0+)
Summary string // Short one-line description
Description string // Detailed explanation (Markdown supported)
Tags []string // Grouping tags for the sidebar
Parameters []Parameter // Path, query, and header parameters (manual)
QueryParams interface{} // Struct whose fields become query params (form/description/example tags)
PathParams interface{} // Struct whose fields become path params (param tag)
RequestBody *RequestBody // Request body (nil for GET/DELETE)
Responses Responses // map[int]ResponseSpec keyed by HTTP status
Security []string // Security scheme names applied to this endpoint
Deprecated bool // Mark the endpoint as deprecated
}
// Responses is a convenience alias used in endpoint literals.
type Responses = map[int]ResponseSpecFields
| Field | Type | Description |
|---|---|---|
Method | string | HTTP verb — GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, TRACE (case-insensitive; HEAD/OPTIONS/TRACE v1.3.0+) |
Path | string | Route path with {param} placeholders. Router-style :id, *path and chi {id:[0-9]+} segments are normalised to {name} (v1.3.0+) |
OperationID | string | Overrides the generated operationId (v1.3.0+). When empty, it is derived from method + path in lowerCamelCase: GET /users/{id} → getUsersById, GET / → getRoot |
Summary | string | One-line summary shown in the sidebar |
Description | string | Longer description, supports Markdown |
Tags | []string | Groups the endpoint under one or more sidebar sections |
Parameters | []Parameter | Manually declared path, query, and header parameters |
QueryParams | interface{} | A struct whose fields (with form tags) become query parameters |
PathParams | interface{} | A struct whose fields (with param tags) become path parameters |
RequestBody | *RequestBody | Payload definition for write operations — build with Body() / BodyWithDesc() / FormBody() |
Responses | Responses | Status-code map — build entries with Response(desc, schema) |
Security | []string | Names of security schemes this endpoint requires |
Deprecated | bool | Flags the endpoint as deprecated in the spec |
Parameter
Describes a single path, query, or header parameter.
type Parameter struct {
Name string // Parameter name, e.g. "id"
In string // Location: "path", "query", "header", or "cookie"
Description string // Human-readable description
Required bool // Whether the parameter is mandatory
Schema *spec.Schema // Parameter schema (e.g. spec.NewSchema("string"))
Example interface{} // Optional example value
}RequestBody
Describes the payload for POST, PUT, and PATCH operations.
type RequestBody struct {
Description string // What the body represents
ContentType string // MIME type, e.g. "application/json", "multipart/form-data"
Required bool // Whether the body is mandatory
Schema interface{} // Go struct for schema generation
}ContentType is honored end-to-end — set it to multipart/form-data for file
uploads and the generated spec will list that media type instead of
application/json. Prefer the Body() / FormBody() / FormURLEncodedBody()
helpers above when you don't need custom fields.
Request body schemas only carry examples where you set an example:"..." tag on a field (the auto-generated body example from v1.1.0 was removed in v1.1.1). Example values are type-coerced (e.g. example:"42" on an int64 field produces the integer 42, not the string "42"). A top-level pointer passed as Schema (e.g. &CreateUserRequest{}) produces the same, non-nullable schema as the value.
ResponseSpec & Response()
ResponseSpec is the struct stored in Endpoint.Responses. Build entries with the Response() helper for the concise, decorator-style form documented in the README:
type ResponseSpec struct {
Description string // What this response means
Schema interface{} // Go struct for schema generation (optional)
}
// Response builds a ResponseSpec. Pass the schema as the second argument,
// or omit it for empty responses (e.g. 204 No Content).
func Response(description string, schema ...interface{}) ResponseSpecResponses are keyed by status code in the Endpoint.Responses map:
Responses: openswag.Responses{
200: openswag.Response("A list of pets", []Pet{}),
204: openswag.Response("Deleted"),
404: openswag.Response("Not found", ErrorResponse{}),
},The struct used to be named
Response. v1.2.0 renamed it toResponseSpecso thatopenswag.Response(...)could become a constructor function. Field literals still work — just replace the type name.
Request body helpers
*RequestBody literals are verbose. Use these constructors:
// JSON body (Required: true, ContentType: "application/json")
openswag.Body(CreateUserRequest{})
// JSON body with a description
openswag.BodyWithDesc("Pet object to create", Pet{})
// multipart/form-data — for file uploads / HTML forms
openswag.FormBody(UploadRequest{})
// application/x-www-form-urlencoded
openswag.FormURLEncodedBody(LoginForm{})All four return *RequestBody, so they slot directly into Endpoint.RequestBody.
Parameter helpers
Decorator-style helpers that return a Parameter ready to drop into Endpoint.Parameters:
openswag.PathParam("id", "User ID") // required path string
openswag.QueryParam("include", "Related resources") // optional query string
openswag.RequiredQueryParam("filter", "Required filter") // required query string
openswag.HeaderParam("X-Request-ID", "Request tracking ID") // optional header
openswag.CookieParam("session", "Session cookie") // optional cookieAll produce a string-typed schema. For typed query/path params, prefer the struct-based QueryParams / PathParams form below.
AuthConfig
Top-level container for the security schemes your spec advertises.
type AuthConfig struct {
PersistCredentials bool // No runtime effect: not passed to the docs UI (see below)
Schemes []AuthScheme // Schemes exposed under components.securitySchemes
}
type AuthScheme struct {
Name string // ID referenced from Endpoint.Security
Type string // "http", "apiKey", "oauth2", "openIdConnect"
Scheme string // "bearer" / "basic" when Type == "http"
BearerFormat string // Hint for http+bearer (e.g. "JWT")
In string // "header" / "query" / "cookie" when Type == "apiKey"
ParamName string // Header/query/cookie name carrying the credential
Description string
}PersistCredentials exists on the struct but is not read anywhere: it is not part of the spec and is not passed to Scalar, so setting it has no effect. Credentials entered in the docs UI are handled client-side by Scalar.
Build entries with the helpers:
Auth: openswag.AuthConfig{
Schemes: []openswag.AuthScheme{
openswag.BearerAuth(openswag.SecurityBearerAuth),
openswag.APIKeyAuth("apiKey", "X-API-Key"),
openswag.BasicAuth(openswag.SecurityBasicAuth),
openswag.CookieAuth(openswag.SecurityCookieAuth, "session_id"),
},
},Custom scheme names referenced from
Endpoint.Securitythat are not one of theSecurity*predefined constants and not registered inAuthConfig.Schemesare intentionally left out of the spec — prior versions silently materialised them ashttp-bearer, which masked typos. Register the scheme explicitly to keep the previous behavior.
Predefined security names
Use these constants in Endpoint.Security to pick up the built-in spec entries
without supplying an AuthScheme:
| Constant | Resolves to |
|---|---|
SecurityBearerAuth | http + bearer + JWT |
SecurityBasicAuth | http + basic |
SecurityApiKey | apiKey in X-API-Key header |
SecurityApiKeyQuery | apiKey in ?api_key= query |
SecurityCookieAuth | apiKey in session_id cookie |
SecurityOAuth2 | oauth2 authorization code |
UIConfig
Controls the Scalar-based documentation UI appearance.
type UIConfig struct {
Theme string // Scalar theme name, passed to Scalar as-is (default "purple")
DarkMode bool // Enable dark mode by default
Layout string // Scalar layout, passed as-is (default "modern")
ShowSidebar bool // Show the navigation sidebar
SidebarSearch bool // Deprecated: has no effect (v1.3.0+)
TagGrouping bool // Deprecated: has no effect (v1.3.0+)
CollapsibleSchemas bool // Deprecated: has no effect (v1.3.0+)
CustomCSS string // Raw CSS injected verbatim into the docs page (trusted input only)
ScalarVersion string // Pin @scalar/api-reference; "" = ui.DefaultScalarVersion ("1.75.0") (v1.3.0+)
SpecCORSOrigin string // Access-Control-Allow-Origin on the spec: "" = "*", "-" = omitted (v1.3.0+)
}| Field | Description |
|---|---|
Theme | Passed through unchanged as Scalar's theme option; any theme name supported by the loaded Scalar version works. Defaults to "purple". See Theming. |
SidebarSearch, TagGrouping, CollapsibleSchemas | Deprecated: has no effect (v1.3.0+). They were never passed to Scalar, which always shows the sidebar search, groups operations by tag and renders collapsible model sections. Kept so existing configuration compiles. |
ScalarVersion | Version of @scalar/api-reference loaded from the CDN (v1.3.0+). Empty uses ui.DefaultScalarVersion ("1.75.0"), so upstream Scalar releases no longer change your docs UI without you opting in. |
SpecCORSOrigin | Controls the Access-Control-Allow-Origin header sent by SpecHandler (v1.3.0+). "" keeps the historical *, "-" omits the header, any other value (e.g. "https://app.example.com") is sent as-is. |
CustomCSS | Inserted verbatim into a <style> element. It must come from trusted configuration. The page title and spec URL, by contrast, are escaped (the page is rendered with html/template since v1.3.0). |
DocsAuth
Protects the documentation page with credentials.
type DocsAuth struct {
Enabled bool // Turn protection on
Username string // Basic auth username
Password string // Basic auth password
Realm string // Basic auth realm (optional)
APIKey string // Alternative: protect with an API key (?key=...)
}When both APIKey and Username/Password are set, either one grants access: the ?key= API key is checked first, then the basic auth credentials. A request that matches neither gets 401 Unauthorized with a WWW-Authenticate challenge.
If Enabled is true but neither APIKey nor both Username and Password are set, every request gets 500 DocsAuth enabled but no credentials configured (v1.3.0+; earlier versions answered 401, which looked like a wrong password).
Info
API metadata rendered in the docs header.
type Info struct {
Title string // API title
Version string // Semantic version, e.g. "1.0.0"
Description string // Markdown description
TermsOfService string // URL to terms of service
Contact *Contact // Maintainer contact info
License *License // License details
}Server
A base URL entry shown in the server dropdown.
type Server struct {
URL string // Base URL, e.g. "https://api.example.com"
Description string // Label for this server
}Tag
A logical grouping for endpoints.
type Tag struct {
Name string // Tag name referenced by Endpoint.Tags
Description string // Displayed in the sidebar
}Contact
Maintainer contact information embedded in Info.
type Contact struct {
Name string // Contact name
URL string // Contact URL
Email string // Contact email
}License
License details embedded in Info.
type License struct {
Name string // License name, e.g. "MIT"
URL string // URL to the full license text
}Parameters from structs
Instead of declaring Parameters by hand, set Endpoint.QueryParams or Endpoint.PathParams to a struct value. Query-param names come from the query tag, then form; path-param names from the path tag, then param; json and the lower-cased field name are fallbacks. The description and example tags annotate each parameter (doc is a fallback for description).
Since v1.3.0 parameter fields follow the same tag rules as request bodies: swagger:"required" or a validator required rule marks a query parameter required, and format, enum and validator constraints (validate:"min=1,max=100", oneof=...) are applied to the parameter schema. A pointer field means optional, not nullable. Path parameters are always required.
type ListProductsQuery struct {
Page int `form:"page" description:"Page number" example:"1"`
PerPage int `form:"per_page" description:"Items per page" example:"20"`
Category string `form:"category" description:"Filter by category ID"`
}
type ProductPathParams struct {
ID string `param:"id" description:"Product ID" example:"prod_123"`
}
openswag.Endpoint{
Method: "GET",
Path: "/products/{id}",
PathParams: ProductPathParams{},
QueryParams: ListProductsQuery{},
// ...
}For full control you can still declare Parameters manually with spec.NewSchema:
import "github.com/gopackx/open-swag-go/pkg/spec"
Parameters: []openswag.Parameter{
{Name: "id", In: "path", Description: "User ID", Required: true, Schema: spec.NewSchema("string")},
},Quick Example
package main
import (
"log"
"net/http"
openswag "github.com/gopackx/open-swag-go"
)
func main() {
cfg := openswag.Config{
Info: openswag.Info{
Title: "Pet Store",
Version: "1.0.0",
},
Servers: []openswag.Server{
{URL: "http://localhost:8080", Description: "Local"},
},
}
endpoints := []openswag.Endpoint{
{
Method: "GET",
Path: "/pets",
Summary: "List all pets",
Tags: []string{"Pets"},
Responses: openswag.Responses{
200: openswag.Response("A list of pets"),
},
},
}
docs := openswag.New(cfg)
docs.AddAll(endpoints...)
if err := docs.Validate(); err != nil {
log.Fatal(err)
}
http.Handle("/docs/", docs.Handler())
http.ListenAndServe(":8080", nil)
}