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

# FastAPI Fundamentals: Routing, Params & Validation

> Master FastAPI routing, path and query parameters, request bodies, response models, and data validation using Pydantic Field, Query, and Path.

With FastAPI installed and your first endpoint running, it's time to go deeper into the building blocks that make up every real-world API. In this lesson you'll learn how to define routes for each HTTP method, extract values from URLs and query strings, accept structured JSON payloads, return clean response models, and apply validation rules to all of the above. These are the skills you'll use in every single endpoint you ever write.

***

## FastAPI Architecture

FastAPI is not built from scratch — it combines Python language features, Starlette's web layer, and Pydantic's data layer into a single cohesive API framework.

```mermaid theme={null}
graph TD
    Client[Client Browser/App] --> Uvicorn[Uvicorn ASGI Server]
    Uvicorn --> FastAPI[FastAPI App Framework]
    FastAPI --> Starlette[Starlette: Routing & Web Parts]
    FastAPI --> Pydantic[Pydantic: Data Validation & Serialization]
```

| Component     | Responsibility                                                                              |
| ------------- | ------------------------------------------------------------------------------------------- |
| **Python**    | Language features: functions, decorators, type hints, async, classes                        |
| **Starlette** | Web framework: HTTP, routing, middleware, requests, responses, WebSockets                   |
| **Pydantic**  | Data validation, serialization, models, settings                                            |
| **FastAPI**   | Binds Starlette and Pydantic together; adds DI, parameter handling, security, and auto-docs |

```text theme={null}
HTTP Request
      │
      ▼
Uvicorn → Starlette (Routing, Request, Middleware)
      │
      ▼
FastAPI (Parameter Parsing, Dependency Injection)
      │
      ▼
Pydantic (Validate & Convert Input Data)
      │
      ▼
Your Endpoint Function
      │
      ▼
Pydantic (Serialize Response)
      │
      ▼
Starlette (Create HTTP Response) → Client
```

***

## Setup and Installation

<Steps>
  <Step title="Create a virtual environment and activate it">
    ```bash theme={null}
    python -m venv .venv
    source .venv/bin/activate  # macOS/Linux
    # .venv\Scripts\activate   # Windows
    ```
  </Step>

  <Step title="Install FastAPI and Uvicorn">
    ```bash theme={null}
    pip install fastapi "uvicorn[standard]"
    ```
  </Step>

  <Step title="Create main.py with your first app">
    ```python theme={null}
    from fastapi import FastAPI

    app = FastAPI()

    @app.get("/")
    def home():
        return {"message": "Welcome to FastAPI"}
    ```
  </Step>

  <Step title="Run the server">
    ```bash theme={null}
    uvicorn main:app --reload
    ```
  </Step>
</Steps>

<Tip>
  If you use `uv` instead of `pip`, replace `pip install fastapi` with `uv add fastapi`. The `uv run uvicorn main:app --reload` command also works.
</Tip>

***

## Routing

A **route** maps an HTTP method + URL path to a Python function. The general pattern is:

```python theme={null}
@app.<http_method>("endpoint")
def function_name():
    ...
```

### Common Routes

```python theme={null}
from fastapi import FastAPI

app = FastAPI()

@app.get("/students")
def get_students():
    return {"message": "Getting all students"}

@app.post("/students")
def create_student():
    return {"message": "Student created"}

@app.put("/students/{student_id}")
def update_student(student_id: int):
    return {"message": f"Updating student {student_id}"}

@app.patch("/students/{student_id}")
def partial_update_student(student_id: int):
    return {"message": f"Partially updating student {student_id}"}

@app.delete("/students/{student_id}")
def delete_student(student_id: int):
    return {"message": f"Deleting student {student_id}"}
```

***

## Path Parameters

Path parameters are embedded directly inside the URL path and identify a specific resource.

```python theme={null}
@app.get("/students/{student_id}")
def get_student(student_id: int):
    return {"student_id": student_id}
```

Request:

```http theme={null}
GET /students/101
```

FastAPI extracts `101` from the URL and converts it to the `int` type automatically. If the value can't be converted (e.g., `/students/abc`), FastAPI returns a `422` error without ever calling your function.

***

## Query Parameters

Any function parameter that is **not** part of the path is automatically treated as a query parameter — the key-value pairs after `?` in the URL.

```python theme={null}
@app.get("/students")
def get_students(course: str, semester: int):
    return {
        "course": course,
        "semester": semester
    }
```

Request:

```http theme={null}
GET /students?course=CSE&semester=4
```

Use `str | None = None` to make a parameter optional:

```python theme={null}
@app.get("/students")
def get_students(department: str | None = None, limit: int = 10):
    return {"department": department, "limit": limit}
```

***

## Request Bodies

Use a **Pydantic model** to receive JSON data in `POST`, `PUT`, and `PATCH` requests.

```python theme={null}
from pydantic import BaseModel

class Student(BaseModel):
    name: str
    age: int
    course: str

@app.post("/students")
def create_student(student: Student):
    return student
```

Request body:

```json theme={null}
{
    "name": "Rahul",
    "age": 20,
    "course": "CSE"
}
```

FastAPI reads the JSON body, validates it against the `Student` schema, creates a `Student` object, and passes it into your function. Access field values with `student.name`, `student.age`, etc.

***

## Response Models

Declare the response structure using `response_model` to control what gets sent back to the client:

```python theme={null}
from pydantic import BaseModel

class StudentResponse(BaseModel):
    id: int
    name: str
    age: int
    course: str

@app.post("/students", response_model=StudentResponse)
def create_student(student: Student):
    return {
        "id": 101,
        **student.model_dump()
    }
```

FastAPI will automatically filter the response to include only the fields declared in `StudentResponse`, even if the returned dictionary contains more fields.

***

## HTTP Status Codes

Set the correct success status code using the `status_code` parameter and constants from `fastapi.status`:

```python theme={null}
from fastapi import status

@app.post("/students", status_code=status.HTTP_201_CREATED)
def create_student(student: Student):
    return student
```

| Code  | Meaning               |
| ----- | --------------------- |
| `200` | OK                    |
| `201` | Created               |
| `204` | No Content            |
| `400` | Bad Request           |
| `401` | Unauthorized          |
| `403` | Forbidden             |
| `404` | Not Found             |
| `422` | Validation Error      |
| `500` | Internal Server Error |

***

## Data Validation

FastAPI provides three validators for different parameter sources:

### `Field()` — Request Body Validation

Use `Field()` inside Pydantic models. The recommended Pydantic v2 style uses `Annotated`:

```python theme={null}
from typing import Annotated
from pydantic import BaseModel, EmailStr, Field

class Student(BaseModel):
    name: Annotated[str, Field(min_length=3, max_length=50)]
    age: Annotated[int, Field(gt=0, lt=100)]
    email: EmailStr
    cgpa: Annotated[float, Field(ge=0, le=10)]
```

### `Query()` — Query Parameter Validation

```python theme={null}
from typing import Annotated
from fastapi import Query

@app.get("/students")
def get_students(
    page: Annotated[int, Query(ge=1)] = 1,
    limit: Annotated[int, Query(ge=1, le=100)] = 20,
    department: Annotated[str | None, Query(alias="dept")] = None,
):
    ...
```

### `Path()` — Path Parameter Validation

```python theme={null}
from typing import Annotated
from fastapi import Path

@app.get("/students/{student_id}")
def get_student(
    student_id: Annotated[int, Path(gt=0)]
):
    ...
```

### Common Validation Options

| Option        | Purpose                        |
| ------------- | ------------------------------ |
| `gt`          | Greater than                   |
| `ge`          | Greater than or equal          |
| `lt`          | Less than                      |
| `le`          | Less than or equal             |
| `min_length`  | Minimum string length          |
| `max_length`  | Maximum string length          |
| `pattern`     | Regular expression match       |
| `alias`       | Alternate field/parameter name |
| `description` | Description shown in API docs  |

<Note>
  `EmailStr` requires the `email-validator` package. Install it with `pip install email-validator`.
</Note>

***

## REST API Design Conventions

Follow these naming conventions to keep your API clean and consistent:

| ✅ Good             | ❌ Bad                    |
| ------------------ | ------------------------ |
| `/students`        | `/getStudents`           |
| `/students/101`    | `/studentDetails?id=101` |
| `/student-courses` | `/student_courses`       |

**Quick Rules**

| Use                 | Example                                                   |
| ------------------- | --------------------------------------------------------- |
| **Path variable**   | `/students/101` — identifies a specific resource          |
| **Query parameter** | `/students?department=CSE` — filters or paginates results |
| **Request body**    | `POST /students` — sends structured resource data         |

***

## Automatic API Documentation

FastAPI generates interactive documentation automatically from your type hints and Pydantic models:

| URL                                  | Purpose                   |
| ------------------------------------ | ------------------------- |
| `http://localhost:8000/docs`         | Swagger UI                |
| `http://localhost:8000/redoc`        | ReDoc                     |
| `http://localhost:8000/openapi.json` | Raw OpenAPI specification |

<Tip>
  Use the Swagger UI during development to test your endpoints directly from the browser — no separate tool like Postman required.
</Tip>
