Stackbook Logo
← Back to Tools

Swagger API Documentation

Document REST APIs with OpenAPI and Swagger: write a spec, render it with Swagger UI, generate code, lint it, and keep docs in sync with your implementation.

4 min read

Swagger is the family of tools built around the OpenAPI Specification, a language-neutral, machine-readable format for describing HTTP APIs. A single OpenAPI document can drive interactive documentation, client and server code generation, mock servers, validation, and contract tests. Use it whenever more than one team or consumer depends on your API, because a precise contract prevents misunderstandings that code alone cannot.

A quick naming note: OpenAPI is the specification, and Swagger refers to the tooling, including Swagger UI, Swagger Editor, and Swagger Codegen. Current specs use OpenAPI 3.0 or 3.1.

Writing a spec

Specs are written in YAML or JSON. This example describes a small users API.

openapi: 3.0.3
info:
  title: Users API
  version: 1.0.0
  description: Manage users.
servers:
  - url: https://api.example.com/v1
paths:
  /users:
    get:
      summary: List users
      operationId: listUsers
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
      responses:
        "200":
          description: A page of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/User"
    post:
      summary: Create a user
      operationId: createUser
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/NewUser"
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "400":
          description: Validation error
  /users/{id}:
    get:
      summary: Get a user
      operationId: getUser
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: The user
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "404":
          description: Not found
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    NewUser:
      type: object
      required: [email]
      properties:
        email:
          type: string
          format: email
        name:
          type: string
    User:
      allOf:
        - $ref: "#/components/schemas/NewUser"
        - type: object
          required: [id]
          properties:
            id:
              type: string

Core concepts

  • paths: endpoints and the HTTP operations on each.
  • parameters: inputs from the path, query, header, or cookie.
  • requestBody and responses: payload shapes per media type and status code.
  • components: reusable schemas, parameters, and security schemes, referenced with $ref.
  • operationId: a unique name per operation that code generators turn into method names.

Rendering and tooling

Serve interactive docs with Swagger UI, where readers can try requests in the browser.

docker run -d -p 8081:8080 \
  -e SWAGGER_JSON=/spec/openapi.yaml \
  -v "$(pwd)":/spec \
  swaggerapi/swagger-ui

Open http://localhost:8081. Other useful commands:

npx @redocly/cli lint openapi.yaml            # lint against rules
npx @redocly/cli build-docs openapi.yaml      # static HTML docs
npx @openapitools/openapi-generator-cli generate \
  -i openapi.yaml -g typescript-fetch -o ./client
npx prism mock openapi.yaml                    # mock server

Design-first versus code-first

In design-first, you write and review the spec before implementation, then generate server stubs and client SDKs. This suits public APIs and parallel team work. In code-first, annotations or framework integrations (for example springdoc-openapi for Spring Boot, or FastAPI which generates a spec automatically) produce the spec from code. It is faster to start but risks leaking implementation accidents into the contract.

Common pitfalls

  • Spec drift. Documentation that no longer matches behaviour is worse than none. Validate requests and responses against the spec in CI using contract tests.
  • Missing error responses. Document 4xx and 5xx shapes, not just success.
  • Duplicated schemas instead of $ref, which makes updates error-prone.
  • Vague descriptions and no examples. Add example values to schemas and operations.
  • Skipping versioning. Version the API in the URL or header and the spec in Git.
  • Exposing internal endpoints in public docs. Split specs or use tags.
  • Unquoted status codes in YAML, which can parse as integers. Quote them as shown above.

Where it fits in an architecture

The OpenAPI document is the contract at the boundary between services. API gateways can import it to configure routes and validation, Postman can generate collections from it, test tools can verify conformance, and front-end teams can code against a mock server before the backend exists. Store it in the same repository as the service and lint it in the pull request pipeline.

Key takeaways

  • OpenAPI is the specification, and Swagger is the tooling around it.
  • Describe paths, schemas, and security once, and reuse components with $ref.
  • Render with Swagger UI, lint with Redocly, and generate clients and mocks from the same file.
  • Prevent drift with contract tests and CI checks.
  • Treat the spec as a versioned, reviewed artifact.