# Week 2

**Getting Started**

Join the github classroom assignment with the following link: [https://classroom.github.com/a/Cg-MTRGE](https://classroom.github.com/a/Cg-MTRGE)

Once you join your repository will be created [https://github.com/blueprint-learn/week2-techteam-sp26-{github-username}](https://github.com/blueprint-learn/week1-techteam-sp26-miguel-merlin)

Once you join, GitHub Classroom will automatically create your personal repository. You will receive an email confirming access.

After receiving access:

1. Clone your repository locally
2. Install dependencies
3. Run the starter FastAPI app

This repository contains the scaffolding you will extend during this week.

```bash
git clone https://github.com/blueprint-learn/week1-techteam-sp26-{github-username}.git
```

**Recap last week**

In Week 1, we established the core foundation of APIs using FastAPI. By the end of the session, you had:

- Built a running FastAPI server
- Created basic endpoints
- Used path parameters
- Verified correctness through automated CI tests

You also saw how an API defines a contract between a client and a server, and how tests enforce that contract.

**Goal for today**

By the end of this week, you will understand how APIs receive structured data and how FastAPI automatically validates incoming data.

This is a major step forward: your API will no longer only return data — it will safely accept data from clients.

**Big idea**

Last week, the interaction pattern was:

**Client asks for data → Server returns data**

This week, we expand that model:

**Client sends data → Server validates and accepts data**

This shift introduces one of the most important responsibilities of a backend API: validating inputs at the system boundary.

## **1. How Data Enters an API**

There are three primary ways data reaches an API endpoint. Understanding these channels is essential for designing correct APIs.

<table id="bkmrk-type-where-used-exam" style="height: 141.562px; width: 88.5185%;"><thead><tr style="height: 35.3906px;"><th style="width: 33.285%; height: 35.3906px;">**Type**

</th><th style="width: 33.285%; height: 35.3906px;">**Where used**

</th><th style="width: 33.285%; height: 35.3906px;">**Example**

</th></tr></thead><tbody><tr style="height: 35.3906px;"><td style="width: 33.285%; height: 35.3906px;">Path

</td><td style="width: 33.285%; height: 35.3906px;">Identify resource

</td><td style="width: 33.285%; height: 35.3906px;">/users/3

</td></tr><tr style="height: 35.3906px;"><td style="width: 33.285%; height: 35.3906px;">Query

</td><td style="width: 33.285%; height: 35.3906px;">Filter/search

</td><td style="width: 33.285%; height: 35.3906px;">?limit=10

</td></tr><tr style="height: 35.3906px;"><td style="width: 33.285%; height: 35.3906px;">Body

</td><td style="width: 33.285%; height: 35.3906px;">Send data

</td><td style="width: 33.285%; height: 35.3906px;">POST JSON

</td></tr></tbody></table>

Each serves a different purpose:

- Path parameters identify <span class="s1">**which**</span> resource
- Query parameters refine <span class="s1">**how**</span> to retrieve
- Request bodies provide <span class="s1">**new data**</span>

### **Path parameters**

Path parameters help define a resource. They usually appear after a / . IDs are usually passed as path parameters to identify a resource.

```
/items/5
```

### **Query parameters**

Query parameters appear after a <span class="s1">?</span> in the URL and are commonly used for filtering, pagination, or search controls.

Examples to test:

```
/items?limit=10
```

```python
@app.get("/items")
def list_items(limit: int = 10):
    return {"limit": limit}
```

FastAPI automatically:

- Applies default values when missing
- Converts types based on type hints
- Validates incorrect input

For example, if <span class="s1">limit</span> is defined as an integer and a string is provided, FastAPI will reject the request before your function executes.

**Key insight:**

FastAPI parses query strings into typed Python values.

### **Request body (JSON)**

Real-world APIs must accept structured data. Common examples include:

- User signup information
- Orders or transactions
- Messages or posts
- Payment details

Clients send this data as JSON in the request body.

```json
{
  "name": "Notebook",
  "price": 5.99
}
```

```python
@app.post("/items")
def create_item(item: dict):
    return item
```

A naive implementation might accept this as a generic dictionary. However, this approach has critical problems:

- No validation
- No defined structure
- No guarantees about data shape

This leads to unstable and unsafe APIs

We need a schema.

## **4. Pydantic Models**

FastAPI uses Pydantic models to define structured request bodies.

A Pydantic model specifies:

- Required fields
- Types
- Optional fields
- Validation rules

When used in an endpoint, FastAPI:

- Parses incoming JSON
- Validates types and structure
- Converts into a Python object
- Rejects invalid requests automatically

This provides:

- Schema definition
- Type enforcement
- Automatic parsing
- Validation

The model becomes the contract for accepted data.

# **Why Validation Matters**

Validation at the API boundary protects the system from invalid or malicious input.

Without validation, systems risk:

- Database corruption
- Runtime crashes
- Security vulnerabilities
- Inconsistent data

With validation, APIs ensure:

- Safe inputs
- Predictable structure
- Stable behavior

**Core principle:**

Validation is defensive programming at the API boundary.

**Define**

```python
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
```

Use

```python
@app.post("/items")
def create_item(item: Item):
    return item
```

**Explain**

- Schema definition
- Type enforcement
- Automatic parsing
- Validation