Course Content
FastAPI Essentials
1 sections · 32 lessons
Explain the difference between path parameters and query parameters in FastAPI.
What you need to know
| Path parameter | Query parameter | |
|---|---|---|
| Where in the URL | Inside the path: /documents/{doc_id} | After ?: ?page=2&size=20 |
| Purpose | Identifies which resource | Changes how you get it: filter, page, sort, flags |
| Required? | Always | Optional if it has a default |
| Missing value | The URL does not match: 404 | 422 if required, default otherwise |
| Validation helper | Path(ge=1) | Query(ge=1, le=100) |
1from typing import Annotated, Literal2from fastapi import FastAPI, Path, Query34app = FastAPI()56@app.get("/documents/{doc_id}/chunks")7def list_chunks(8 doc_id: Annotated[int, Path(ge=1)], # which document9 page: Annotated[int, Query(ge=1)] = 1, # how to slice the result10 size: Annotated[int, Query(ge=1, le=100)] = 20,11 lang: Literal["en", "hi", "ta"] | None = None,12):13 return {"doc_id": doc_id, "page": page, "size": size, "lang": lang}Real responses:
GET /documents/42/chunks?page=2&lang=hi -> {'doc_id': 42, 'page': 2, 'size': 20, 'lang': 'hi'}GET /documents/42/chunks -> {'doc_id': 42, 'page': 1, 'size': 20, 'lang': None}GET /documents/0/chunks?size=500 -> 422 [(['path', 'doc_id'], '... greater than or equal to 1'), (['query', 'size'], '... less than or equal to 100')]GET /documents//chunks -> 404GET /documents/42/chunks?lang=fr -> 422 Input should be 'en', 'hi' or 'ta'Notice the difference in the last lines. An empty path segment does not match the route at all, so it is a 404. A bad query value matches the route but fails validation, so it is a 422, and the error's loc says whether the problem was in path or query.
Design guidance
- Use a path parameter for identity:
/models/{model_id},/documents/{doc_id}. - Use query parameters for pagination, filters, sorting and optional flags:
?page=2&lang=hi&rerank=true. - A good test: if removing the value makes the URL point to a different kind of thing, it belongs in the path.
- Never put prompts, API keys or personal data in either. URLs are written to access logs, proxy logs and browser history, and have length limits (often around 8 KB). Those go in the request body or a header.
A real-life example
A RAG product's first search endpoint was GET /search?q=..., with the user's full question in the query string. A security review found customer questions — some including phone numbers and account details — in the load balancer's access logs, which were kept for 90 days and readable by the whole platform team.
The team moved search to POST /search with the question in a JSON body, and kept only non-sensitive options in the query string (?top_k=5&lang=hi). Document lookups stayed as GET /documents/{doc_id}, because an id is safe to log and GET makes them cacheable.
Follow-up questions to expect
- "How do you accept a list in a query string?" — Declare
tags: Annotated[list[str], Query()] = []and send?tags=a&tags=b. - "Can a path parameter contain a slash?" — Only with the
:pathconverter:/files/{file_path:path}. Validate it carefully to avoid path traversal. - "How do you make a query parameter required?" — Give it no default:
q: str. FastAPI returns 422 if it is missing.