> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Creating API Documentation

> How to create clear OpenAPI and interactive Swagger documentation with FastAPI using Pydantic models, docstrings, endpoints, validation, and example responses.

In this lesson we'll walk through creating clear, usable API documentation using FastAPI. FastAPI automatically generates OpenAPI/Swagger documentation (Swagger UI at `/docs`, ReDoc at `/redoc`) from your function signatures, Pydantic models, and docstrings — making it an excellent choice for building well-documented APIs quickly.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/DEYrDKSldd3lYPoS/images/GitHub-Copilot-in-Action/Using-Copilot-Efficiently/Creating-API-Documentation/creating-api-documentation-demo-kodekloud.jpg?fit=max&auto=format&n=DEYrDKSldd3lYPoS&q=85&s=bad0443cc62b94101e080ffee49a01aa" alt="A presentation slide titled &#x22;Creating API Documentation&#x22; with a large dark curved shape on the right containing the word &#x22;Demo&#x22; in blue. The bottom-left corner shows a small &#x22;© Copyright KodeKloud&#x22; notice." width="1920" height="1080" data-path="images/GitHub-Copilot-in-Action/Using-Copilot-Efficiently/Creating-API-Documentation/creating-api-documentation-demo-kodekloud.jpg" />
</Frame>

<Callout icon="lightbulb" color="#1CB2FE">
  FastAPI auto-generates OpenAPI/Swagger documentation from path operation signatures, Pydantic models, and docstrings. Well-structured docstrings and typed models greatly improve the generated docs and the developer experience.
</Callout>

Overview

* Why FastAPI: automatic OpenAPI generation, interactive docs, type-driven validation.
* What this example shows: Pydantic request model, SQLite path setup, a context manager for DB connections, a helper to fetch randomized fake data, and a POST endpoint that returns that data.
* Result: interactive docs available at `/docs` (Swagger UI) and `/redoc` (ReDoc) after running the app.

Code example (concise, cleaned-up)
The following blocks show the full example used in the lesson. Each block is explained briefly before the code so the flow and purpose are clear.

```python theme={null}
# main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import sqlite3
from typing import List, Dict
from contextlib import contextmanager
from pathlib import Path

app = FastAPI(title="Fake Data API")

class DataRequest(BaseModel):
    count: int

BASE_DIR = Path(__file__).resolve().parent
DATA_DIR = BASE_DIR / "data" / "db"
DB_PATH = DATA_DIR / "fakedata.db"

# Create data directory if it doesn't exist
DATA_DIR.mkdir(parents=True, exist_ok=True)
```

Context manager for database connections
Use a context manager to ensure SQLite connections are opened and closed reliably. The docstring includes usage notes and exceptions to help maintainers and automated docs.

```python theme={null}
@contextmanager
def get_db_connection():
    """
    Create and manage a database connection as a context manager.

    This function establishes a connection to the SQLite database
    specified by DB_PATH, sets the row factory to sqlite3.Row for
    dictionary-like access to rows, and ensures the connection is
    properly closed after use.

    Usage:
        >>> with get_db_connection() as conn:
        ...     cursor = conn.cursor()
        ...     cursor.execute("SELECT 1")
        ...     rows = cursor.fetchall()

    Yields:
        sqlite3.Connection: An active connection to the SQLite database.

    Raises:
        sqlite3.Error: If there's an error connecting to or interacting
                       with the database.
    """
    conn = sqlite3.connect(str(DB_PATH))
    conn.row_factory = sqlite3.Row
    try:
        yield conn
    finally:
        conn.close()
```

Helper function to fetch random fake data
The helper includes a precise docstring describing parameters, return type, and possible database errors. This helps both readers and generated documentation.

```python theme={null}
def fetch_fake_data(count: int) -> List[Dict]:
    """
    Retrieve a number of randomly selected fake data entries from the DB.

    Parameters:
        count (int): The number of fake data entries to retrieve.

    Returns:
        List[Dict]: A list of dictionaries, each representing a single fake
                    data entry with keys: first_name, last_name,
                    email_address, age, city, occupation.

    Raises:
        sqlite3.Error: If there's an error executing the SQL query or
                       fetching the results from the database.
    """
    with get_db_connection() as conn:
        cursor = conn.cursor()
        cursor.execute(
            """
            SELECT first_name, last_name, email_address, age, city,
                   occupation
            FROM fake_data
            ORDER BY RANDOM()
            LIMIT ?
            """,
            (count,)
        )
        rows = cursor.fetchall()
        return [dict(row) for row in rows]
```

POST endpoint: docstrings, validation, and error handling
This POST endpoint demonstrates how to document an operation with a descriptive docstring and how to perform input validation and error handling. Note: FastAPI will use the function signature and Pydantic models for the OpenAPI schema; the extended YAML-style docstring below can be consumed by external tooling or for human readers, though FastAPI does not parse YAML blocks in docstrings into OpenAPI automatically.

```python theme={null}
@app.post("/api/v1/getfakedata")
async def get_fake_data(request: DataRequest):
    """
    Generate fake personal data entries from the database.

    ---
    tags:
      - Fake Data API
      - Data Generation

    summary: Retrieve randomly generated personal data entries

    description: |
      Endpoint generates and returns randomly selected fake personal
      data entries from a pre-populated database. Each entry contains
      personal information including name, email, age, location, and
      occupation. Rate limited to 1000 records per request.

    requestBody:
      required: true
      content:
        application/json:
          schema:
            type: object
            properties:
              count:
                type: integer
                minimum: 1
                maximum: 1000
                description: Number of data entries to retrieve
          example:
            count: 2

    responses:
      '200':
        description: Successfully retrieved fake data entries
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
                properties:
                  first_name:
                    type: string
                    example: "John"
                  last_name:
                    type: string
                    example: "Doe"
                  email_address:
                    type: string
                    format: email
                    example: "john.doe@example.com"
                  age:
                    type: integer
                    example: 30
                  city:
                    type: string
                    example: "New York"
                  occupation:
                    type: string
                    example: "Software Engineer"
      '400':
        description: Invalid request parameters
        content:
          application/json:
            example:
              detail: "Count must be between 1 and 1000"
      '404':
        description: No data found in database
        content:
          application/json:
            example:
              detail: "No data entries found in database"
      '500':
        description: Internal server error
        content:
          application/json:
            example:
              detail: "Internal server error occurred"
    """
    count = request.count

    # Input validation
    if count <= 0:
        raise HTTPException(status_code=400, detail="Count must be greater than 0")
    if count > 1000:
        raise HTTPException(status_code=400, detail="Count must be 1000 or fewer")

    # Fetch and return results with error handling
    try:
        results = fetch_fake_data(count)
        if not results:
            raise HTTPException(status_code=404, detail="No data entries found in database")
        return results
    except sqlite3.Error:
        raise HTTPException(status_code=500, detail="Internal server error occurred")
```

Entrypoint to run the app
Start the app with Uvicorn for local testing and to view the generated docs.

```python theme={null}
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
```

Request and response examples
These examples help API consumers understand the expected input and output formats.

Request (example)

```json theme={null}
{
  "count": 2
}
```

Response (example)

```json theme={null}
[
  {
    "first_name": "John",
    "last_name": "Doe",
    "email_address": "john.doe@example.com",
    "age": 30,
    "city": "New York",
    "occupation": "Software Engineer"
  },
  {
    "first_name": "Jane",
    "last_name": "Smith",
    "email_address": "jane.smith@example.com",
    "age": 25,
    "city": "San Francisco",
    "occupation": "Data Scientist"
  }
]
```

Typical startup and doc access log
After running the server you should see logs similar to:

```text theme={null}
INFO:     Started server process [14253]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     127.0.0.1:52513 - "GET /docs HTTP/1.1" 200 OK
INFO:     127.0.0.1:52517 - "GET /redoc HTTP/1.1" 200 OK
INFO:     127.0.0.1:52513 - "GET /openapi.json HTTP/1.1" 200 OK
```

Quick reference: response codes and examples

| HTTP Code | Meaning                            | Example response                                      |
| --------- | ---------------------------------- | ----------------------------------------------------- |
| 200       | Successful retrieval of data       | `[{ "first_name": "John", "last_name": "Doe", ... }]` |
| 400       | Invalid request (validation error) | `{"detail":"Count must be greater than 0"}`           |
| 404       | No data found                      | `{"detail":"No data entries found in database"}`      |
| 500       | Internal server error (DB error)   | `{"detail":"Internal server error occurred"}`         |

<Callout icon="warning" color="#FF6B6B">
  When running locally or in production, never expose an open database file directly without proper access controls. Apply rate limiting, input validation, and authentication for public APIs to prevent abuse and protect sensitive data.
</Callout>

Tips and best practices for API documentation (SEO-friendly)

* Use Pydantic models for request and response schemas — FastAPI surfaces these types in generated docs and OpenAPI schemas.
* Write clear docstrings: include a concise summary, a descriptive body, and examples. These show up in Swagger UI and ReDoc and help search engines index descriptive content.
* Document possible responses and error cases (400/404/500) with examples to help API consumers implement robust clients.
* Keep function signatures and type hints accurate — the OpenAPI schema is built from these.
* Consider adding operation-level tags and summaries to group endpoints and improve discoverability in interactive docs.
* Use external YAML snippets or tools if you need to extend the generated OpenAPI beyond what FastAPI infers, but verify how those tools integrate into your pipeline.
* Treat AI assistants (e.g., GitHub Copilot) as collaborators: ask for docstring suggestions, then review and refine to align with your documentation standards.

Links and references

* FastAPI documentation: [https://fastapi.tiangolo.com/](https://fastapi.tiangolo.com/)
* Pydantic models: [https://pydantic-docs.helpmanual.io/](https://pydantic-docs.helpmanual.io/)
* SQLite: [https://sqlite.org/index.html](https://sqlite.org/index.html)
* Uvicorn: [https://www.uvicorn.org/](https://www.uvicorn.org/)
* Example course: [GitHub Copilot in Action](https://learn.kodekloud.com/user/courses/github-copilot-in-action)

That concludes this lesson on creating API documentation using FastAPI. Thank you for reading.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/github-copilot-in-action/module/5c3827f4-b200-4c22-90bb-e7c6540d96d8/lesson/f3b936e1-1a95-4520-9952-01faeaf10e91" />
</CardGroup>
