Path parameters, query strings, type hints that actually do something — build your first real FastAPI app and test it live in /docs.
Day 57 of 80
Two short pages from the official FastAPI docs. Both are well-written and have interactive examples.
Pay attention to how type hints in function parameters change FastAPI's behavior — not just what type is expected, but how validation errors look in the response. The docs show you actual error JSON.
These are two different ways to pass data to a route. You'll use both today.
Path parameters are part of the URL itself: /prompts/42 — the 42 is the prompt's ID. Use these when you're identifying a specific resource.
Query parameters come after a ? in the URL: /search?platform=Kling&q=golf. Use these for filtering, searching, and optional inputs.
In FastAPI, path parameters go in the URL pattern with curly braces. Query parameters are just extra function arguments with default values.
fastapi_test.pyCreate this file in your DVP Prompt Vault project folder. It's a standalone FastAPI app — not connected to the database yet, just in-memory data. The goal is to feel how routes work before adding complexity.
from fastapi import FastAPI
app = FastAPI(title="DVP Prompt Vault API")
# In-memory data — we'll connect to SQLite on Day 58
prompts = [
{"id": 1, "platform": "Kling", "shot": "Golf swing", "prompt": "Cinematic slow motion golf swing, morning mist..."},
{"id": 2, "platform": "Runway", "shot": "Ocean", "prompt": "Aerial ocean view at golden hour..."},
{"id": 3, "platform": "Veo", "shot": "City skyline", "prompt": "Time-lapse city skyline at dusk..."},
]
# Route 1: GET /prompts — return all prompts
@app.get("/prompts")
def get_prompts():
return prompts
# Route 2: GET /prompts/{prompt_id} — return one prompt by ID
@app.get("/prompts/{prompt_id}")
def get_prompt(prompt_id: int):
for p in prompts:
if p["id"] == prompt_id:
return p
return {"error": "Not found"}
# Route 3: GET /search?platform=Kling&q=golf
# Both parameters are optional — they have default values of None
@app.get("/search")
def search_prompts(platform: str = None, q: str = None):
results = prompts
if platform:
results = [p for p in results if p["platform"].lower() == platform.lower()]
if q:
results = [p for p in results
if q.lower() in p["shot"].lower() or q.lower() in p["prompt"].lower()]
return results
prompt_id: int is doing real work. Try visiting /prompts/abc — FastAPI returns a 422 Unprocessable Entity error with a clear message. You wrote zero validation code for this.# From the folder containing fastapi_test.py
uvicorn fastapi_test:app --reload
# You should see:
# INFO: Uvicorn running on http://127.0.0.1:8000
# INFO: Application startup complete.
pip install fastapi uvicorn if needed.In plain Python, def get_item(item_id: int) is just a hint — Python doesn't enforce it. You can call get_item("hello") and Python won't complain.
FastAPI changes this. When you define a route with prompt_id: int, FastAPI hooks into the type hints and validates every incoming request. Try these URLs after running your app:
/prompts/1 — works, returns prompt with ID 1/prompts/2 — works, returns prompt with ID 2/prompts/abc — FastAPI returns a 422 error: "value is not a valid integer"/prompts/99 — passes validation (99 is a valid int) but returns your custom "Not found" error/docsWith the server running, open http://localhost:8000/docs. You'll see all three routes listed. For each one:
For /search, test a few combinations: platform only, q only, both, neither. Notice that query parameters appear as form fields in the docs UI automatically.
These are optional but worth doing if you finish early:
prompts list and verify it shows up in /prompts without restarting (the --reload flag handles this)GET /platforms route that returns a unique list of all platforms in your dataget_prompt function to return a 404 status code instead of a plain error dict — look up HTTPException in the FastAPI docsresponse_model=list[dict] to the get_prompts decorator and observe how it changes the docsIf you define /prompts/search after /prompts/{prompt_id}, FastAPI will try to match "search" as an integer and fail. Always put specific routes before parameterized ones. In this app, /search is at a different path so it's fine — but keep this in mind when you add more routes.
fastapi_test.py with uvicorn --reload/docs UI/prompts/abc returns a 422 validation error automatically/prompts/{id}) and query parameters (?platform=Kling)= None makes a query parameter optionalYou'll build api.py — a proper REST API with Pydantic models for validation, connected to your SQLite database, with GET, POST, and DELETE routes. This is the core of the DVP Prompt Vault API.