# Path Params, Query Parameters and Body<no value>

## What will we learn?

A Client needs to tell the server **what** exactly it wants. It has three ways:

| Way | Where | Example |
|---|---|---|
| **Path Parameter** | Part of the path itself | `/students/7` |
| **Query Parameters** | After `?` in the URL | `/students?city=Haifa&limit=10` |
| **Body** | In the body of the request (JSON) | `{"name": "Dana", "age": 24}` |

## Why do we need this?

In the next lesson we will write the first server, and in FastAPI each of the three is defined in a different way. If you don't understand the difference, you put information in the wrong place: an identifier in the Body, or a password in the URL. And every real API you will consume (GitHub, weather, payments) uses all three.

## Explanation from the basics

### Path Parameter — "which one?"

A **variable** part inside the path, which identifies **a specific resource**:

```text
GET /students/7
              └─ path parameter: which student
GET /users/octocat/repos
           └─ path parameter: which user
```

**When:** when you identify **one item** (usually by id). Without the parameter, the path is not complete.

### Query Parameters — "how? how many? filtered by what?"

`key=value` pairs after `?`, separated by `&`:

```text
GET /students?city=Haifa&min_age=20&limit=10
             └──────────── query string ────────┘
                key=value & key=value & key=value
```

**When:** **filtering**, **sorting**, **paging** (Pagination), and **options**. Usually **optional**: `GET /students` also works without them, and simply returns everything.

### Body — "here is the data"

The data itself, in the body of the request, almost always in **JSON**:

```text
POST /students
Content-Type: application/json

{"name": "Dana", "age": 24, "email": "dana@mail.com"}
```

**When:** when you **send data** for creating or updating (POST, PUT). You can send complex structures (lists, nested objects) and large amounts. **GET and DELETE have no Body.**

### How do you decide?

| Question | Way |
|---|---|
| Identifies **which** item? | **Path** — `/students/7` |
| Filters, sorts, limits the amount, a display option? | **Query** — `?city=Haifa&sort=age` |
| **The data** of a resource you create or update? | **Body** — JSON |
| Sensitive information (a password, a token)? | **Never in the URL** (it is saved in logs and in the browser history). The Body or Headers |

{{< box "analogy" "Analogy: ordering from a pizzeria by phone" >}}
"I am calling **the Haifa branch**" (**Path**: which place exactly). "Tell me the deals, **vegan only**, **cheapest first**" (**Query**: filtering and sorting of what I ask for). "I want to order: **a family pizza, olives, mushrooms, to 10 Herzl Street**" (**Body**: the full details of what is being created).
{{< /box >}}

### URL Encoding

In a URL, spaces and special characters are not allowed "as they are". A space becomes `%20` (or `+`), an `&` inside a value becomes `%26`, and non-English letters (like Hebrew) are encoded into bytes (`%D7%93...`). The browser and the libraries do the encoding for us — but it is important to understand why it exists.

## Breaking down an address

```text
/students/7/grades?semester=2&limit=5

path   ->  students / 7 / grades   (the grades of student 7)
query  ->  semester = 2            (a filter)
           limit    = 5            (how many)
```

- The **Path** identifies **which** resource: the grades of student 7.
- The **Query** starts after `?`, and every parameter is separated by `&`. It says **how**: which semester, and how many results.

## All three in one request

```text
PUT /students/7?notify=true
Content-Type: application/json

{"name": "Dana Cohen", "age": 25}
```

| Part | Value | Why here |
|---|---|---|
| Path | `7` | **Which** student — part of the resource's identity |
| Query | `notify=true` | **An option** of the request — not part of the data |
| Body | `{"name": ..., "age": ...}` | **The new data** itself |
| Header | `Content-Type: application/json` | **In which format** the body is |

In the next lesson we will see how FastAPI receives all three automatically — and puts each one into a parameter of our function.

## Common mistake

**Mistake 1: an identifier in the Query instead of the Path, or the opposite.**

```text
GET /students?id=7          ← works, but not the convention for ONE resource
GET /students/city/Haifa    ← "Haifa" is a filter, not a resource id
```

The convention: **a specific item in the Path** (`/students/7`), **filtering in the Query** (`/students?city=Haifa`).

**Mistake 2: a value with spaces and `&` "as it is" in the address.**

```text
/search?q=rock & roll
```

The spaces break the address, and the `&` is interpreted as the start of a new parameter. The value has to be **encoded**: `q=rock+%26+roll`.

**Mistake 3: forgetting that everything in the URL is a string.** `"7"` ≠ `7`. A comparison `if student_id == 7` when `student_id` arrived from the URL as `"7"` → `False`. (FastAPI will convert for us, if we define a type.)

**Mistake 4: sensitive information in the URL.** `GET /login?user=dana&password=1234`. The URL is saved in the browser history, in server logs, and in links you send. Passwords: **only in the Body** (and always over HTTPS).

<!-- exercises:start — generated by scripts/intro6/sync_site_exercises.py; edit scripts/intro6/exercises/ -->
## Practice

The exercises use only what was taught in this lesson and the lessons before it. Try on your own first, and only then open the solution.

### Exercise 1: Where does each piece of data go?

For each request — is the data a Path Parameter, a Query Parameter or a Body?

1. The identifier of the student you want to get.
2. Filtering students by city.
3. The name and the age of a new student.
4. How many results to return per page.
5. The updated data of an existing student.

{{< solution >}}
1. **Path** — identifies **which** resource: `/students/7`.
2. **Query** — filtering: `/students?city=Haifa`.
3. **Body** — the data of a new resource, in JSON.
4. **Query** — an option: `?limit=10`.
5. **Body** (and the identifier in the **Path**): `PUT /students/7` with a body.

The rule: **Path** — which resource. **Query** — filtering, sorting and pages. **Body** — the data itself.
{{< /solution >}}

### Exercise 2: Breaking down an address

Break down the address: what is the Path, what is the identifier inside it, and what are the Query Parameters?

```text
https://api.kodkod.dev/students/7/grades?semester=2&limit=5
```

{{< solution >}}
| Part | Value | Meaning |
|---|---|---|
| Path | `/students/7/grades` | The grades of student 7 |
| Identifier in the Path | `7` | **Which** student |
| Query | `semester=2` | A filter — semester 2 |
| Query | `limit=5` | How many results — 5 |

The Query starts after `?`, and every parameter is separated by `&`.
{{< /solution >}}

### Exercise 3: Building an address

Write the addresses for the following requests, to the server `https://api.x.com`:

1. All the students from Haifa.
2. Students from Haifa, the first ten.
3. Student 7.
4. The grades of student 7 in semester 1.

{{< solution >}}
```text
1. https://api.x.com/students?city=Haifa
2. https://api.x.com/students?city=Haifa&limit=10
3. https://api.x.com/students/7
4. https://api.x.com/students/7/grades?semester=1
```

The identifier goes **in the path**, and the filters **in the Query** — after `?`, and joined with `&`.
{{< /solution >}}

### Exercise 4: All three in one request

```text
PUT /students/7?notify=true
Content-Type: application/json

{"name": "Dana Cohen", "age": 25}
```

Identify the Path Parameter, the Query Parameter and the Body, and explain why each piece of data is in its place. What is the role of the Header `Content-Type`?

{{< solution >}}
- **Path:** `7` — **which** student is being updated. It is part of the resource's identity.
- **Query:** `notify=true` — **an option** of the request: how to perform it. It is not part of the student's data.
- **Body:** `{"name": "Dana Cohen", "age": 25}` — **the new data** itself.
- **`Content-Type: application/json`** — tells the server **in which format** the body is, so that it knows how to read it.
{{< /solution >}}

### Exercise 5: What doesn't go in the address?

For each address — what is the problem, and how do you do it right?

```text
1. GET /students?id=7
2. GET /students/city/Haifa
3. GET /login?user=dana&password=1234
4. GET /search?q=rock & roll
```

{{< solution >}}
1. **The identifier of one item belongs in the path**: `GET /students/7`. The Query is meant for filtering.
2. **"Haifa" is a filter, not the identifier of a resource**: `GET /students?city=Haifa`.
3. **A password in the address** is saved in the browser history, in server logs and in links you send. Passwords — **only in the Body**, and always over HTTPS.
4. **Spaces and `&` inside a value** break the address: the `&` is interpreted as the start of a new parameter. The value has to be **encoded** (URL Encoding): `q=rock+%26+roll`. In practice, the browser and the libraries do the encoding for us.
{{< /solution >}}

<!-- exercises:end -->

## Summary

- **Path Parameter** (`/students/7`) — **which** resource. Part of the path.
- **Query Parameters** (`?city=Haifa&limit=10`) — **filtering, sorting, paging, options**. Usually optional.
- **Body** (JSON) — **the data** for creating and updating (POST, PUT). GET and DELETE have no Body.
- Everything in the URL is a **string**. A Query has to be encoded correctly (spaces, `&` and non-English letters).
- Don't put passwords and sensitive information in the URL.
- In the next lessons, FastAPI will decode all three automatically, including converting types.

<!-- docs:start — generated by scripts/intro6/site_docs.py; edit the links there -->

## Official documentation

- [MDN — What is a URL?](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Web_mechanics/What_is_a_URL)
- [MDN — HTTP messages: Body](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Messages#request_body)

<!-- docs:end -->
