Before writing any backend code, it’s important to design the API.

Swagger (now officially called OpenAPI Specification) lets you define what your API will look like — the endpoints, the inputs, the outputs — in a structured way.

Here’s how you write a complete Swagger document before coding anything.

🛠 Example: A Simple User API

Let’s say you’re building a User API for a system that manages users.

You want to support the following actions:

  • Get all users
  • Get a user by ID
  • Create a new user

We’ll now break down the Swagger file for this API and explain every single part.

✅ Step 1: Define the API Info

openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
  description: API for managing users

What this does:

  • openapi: Version of the OpenAPI spec you're using
  • info: Basic metadata about your API (name, version, description)

✅ Step 2: Define Paths (i.e. Endpoints)

paths:
  /users:
    get:
      summary: Get all users
      responses:
        '200':
          description: A list of users

🔍 What is a Path?

  • A path is a URL pattern that your API exposes. Example: /users
  • It represents a resource — in this case, the "users" resource

🔍 What is an Endpoint?

  • An endpoint is a path + method
  • Example: GET /users is one endpoint, POST /users is another

So:

  • /users is a path
  • GET /users is an endpoint for fetching users
  • POST /users would be an endpoint for creating a user

✅ Step 3: Add Another Endpoint (GET /users/{id})

/users/{id}:
    get:
      summary: Get a user by ID
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: A single user
        '404':
          description: User not found

🔍 What are Path Parameters?

  • {id} in the path is a dynamic part — it’ll be replaced with an actual value like /users/5
  • You define it under parameters to describe the input expected

✅ Step 4: Add a Request Body (POST /users)

/users:
    post:
      summary: Create a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserCreate'
      responses:
        '201':
          description: User created

🔍 What is RequestBody?

  • It describes the input payload the client needs to send when making a POST request
  • In this case, we expect the client to send a JSON object with user details

✅ Step 5: Define Reusable Schemas (Models)

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        email:
          type: string

    UserCreate:
      type: object
      required:
        - name
        - email
      properties:
        name:
          type: string
        email:
          type: string

🔍 What is a Schema?

  • A schema defines the structure of the data in requests or responses
  • You put schemas under components/schemas so you can reuse them using $ref

In this case:

  • User is used in responses (contains id, name, email)
  • UserCreate is used in requests (only name, email — no id because it’s generated)

🔗 How Schemas and Endpoints Work Together

Every endpoint that returns or receives data needs to describe what that data looks like. That’s where schemas come in.

Example:

  • GET /users returns a list of users → uses the User schema
  • POST /users expects user input → uses the UserCreate schema

This way:

  • You avoid repeating structure definitions everywhere
  • You can update schemas in one place and all linked endpoints reflect it
  • Documentation stays clean, reusable, and DRY

Think of it like this:

  • Endpoints describe the actions,
  • Schemas describe the shape of the data those actions work with.

They are two sides of the same API design.

✅ Full Swagger YAML Example

openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
  description: API for managing users

paths:
  /users:
    get:
      summary: Get all users
      responses:
        '200':
          description: A list of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
    post:
      summary: Create a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserCreate'
      responses:
        '201':
          description: User created

  /users/{id}:
    get:
      summary: Get a user by ID
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: A single user
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: User not found

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        email:
          type: string

    UserCreate:
      type: object
      required:
        - name
        - email
      properties:
        name:
          type: string
        email:
          type: string

🧠 Summary

  • Swagger lets you design your API before you write code.
  • Paths define resources, endpoints define actions.
  • Schemas define the structure of data for requests and responses.
  • Endpoints and schemas work together to define a complete API contract.
  • Writing Swagger first saves time, avoids confusion, and aligns your team.