⏱️ Slide Timing: 1 min - Welcome and frame the session: every website and every Python `requests.get()` call rides on the same protocol — HTTP - Promise: by the end, everyone can read a raw HTTP request/response, explain what REST means, and call a real API from Python - Bridge: start from the most basic question — what actually happens when you type a URL into a browser
⏱️ Slide Timing: 3 min - Analogy: HTTP is like a standardized order form at a restaurant — client fills it out, server fills the order, no memory of your last visit - Stateless is the counterintuitive part — ask students how logins "remember" you if the protocol has no memory - Bridge: apps use cookies/tokens on top of HTTP to fake statefulness — we'll touch this in the auth slide ❓ Ask: "If HTTP forgets everything between requests, how does a website keep you logged in?"
⏱️ Slide Timing: 3 min - Client initiates — server never contacts you first in plain HTTP - Every Python `requests.get(url)` call is playing the "client" role in this exact picture - The arrows are the whole mental model for this entire deck — everything else is detail on top of "request out, response back"
⏱️ Slide Timing: 4 min - Walk through top to bottom: client sends a request line + headers, server processes, server replies with a status + headers + body - The "Note" boxes are where your backend code (or the API you're calling) actually does work — everything else is just envelope - Bridge: let's see what these messages actually look like as raw text
⏱️ Slide Timing: 3 min - Scheme + host + port get you to the right server; path + query + fragment tell that server what you want - Fragment is the one piece that never leaves the browser — good trivia: `#profile` never appears in server logs - Students will build query strings constantly with the `requests` library — worth lingering on that box
⏱️ Slide Timing: 3 min - This is literally what your browser or `requests` library sends over the wire — nothing hidden - Point out there's no body on a GET — data goes in the URL/query string, not the payload
⏱️ Slide Timing: 3 min - Same shape every time: status line, headers, blank line, body — that pattern never changes - This blank line trips people up when they try to hand-write raw HTTP — it's the hard boundary between metadata and payload
⏱️ Slide Timing: 4 min - PUT vs PATCH is the classic mix-up: PUT replaces the whole object, PATCH edits just the fields you send - These five methods cover roughly 95% of everything students will do calling APIs - Bridge: map these methods onto REST resource design next
⏱️ Slide Timing: 3 min - POST carries a body describing the new resource; note the required `Content-Type` header - DELETE typically has no body — the URL alone identifies what to remove
⏱️ Slide Timing: 3 min - 404 is the one everyone already knows — anchor the rest of the ranges to that familiar one - 401 vs 403 is a common interview question: 401 means "who are you," 403 means "I know who you are, still no"
⏱️ Slide Timing: 2 min - 201 Created is the expected response to a successful POST — note the new `id` in the body - Well-designed APIs put a human-readable `error` message in the body even on failure — always print `response.text` when debugging
⏱️ Slide Timing: 3 min - JSON maps almost 1:1 onto Python dicts and lists — that's why `response.json()` is so convenient - Point out the types available: string, number, boolean, null, array, object — no dates, no sets, no tuples
⏱️ Slide Timing: 3 min - `Content-Type` describes what you're sending; `Accept` describes what you want back — students often confuse the two - Missing `Content-Type: application/json` on a POST is one of the most common bugs in early API code
⏱️ Slide Timing: 2 min - Analogy: a restaurant menu is an API — you don't need to know the kitchen, just what you can order and what comes back - Bridge: REST is simply the most common *style* of designing these web APIs
⏱️ Slide Timing: 4 min - Key mental shift: URLs name *things*, HTTP methods say what to *do* to them — `/deleteUser?id=42` is not RESTful, `DELETE /users/42` is - Nesting resources (`/users/42/orders`) reads almost like a sentence — "orders belonging to user 42" - This is a convention, not an enforced standard — different teams bend the rules; the goal is predictability for the client
⏱️ Slide Timing: 3 min - Same URL, `/users/42`, different verb, completely different action — that's the whole idea of REST in one picture - This GET/POST/PUT-PATCH/DELETE mapping is often called "CRUD" — Create, Read, Update, Delete ❓ Ask: "If /users/42 is the resource, what URL would list *all* users?"
⏱️ Slide Timing: 2 min - Frame Postman as the "training wheels" step — see the request/response shape visually before writing `requests` code - Every concept covered so far (method, URL, headers, status, body) maps directly onto a labeled field in the Postman UI
⏱️ Slide Timing: 4 min - Top bar: method dropdown + URL bar + Send button — literally `requests.get(url)` as a UI - Tabs (Params / Authorization / Headers / Body) are exactly the pieces from earlier slides, just in dedicated boxes instead of a raw HTTP request - Bottom panel: status, time, size, then the parsed JSON body — the same information as `response.status_code`, `response.elapsed`, `response.json()` ❓ Ask: "Which tab would you click to add an Authorization header for an API key?"
⏱️ Slide Timing: 4 min - Live-demo both if time allows — GET first to build confidence, then POST to show the Body tab - Point out the method-color convention: GET is green, POST is orange/yellow in Postman — same visual language across the tool
⏱️ Slide Timing: 3 min - Directly mirrors the "never hardcode keys" pitfall from the Python auth slide — same discipline, different tool - Switching environments (e.g. dev vs. prod) is just a dropdown — one more reason teams standardize on this instead of hardcoded values
⏱️ Slide Timing: 4 min - Live-run this if possible — jsonplaceholder.typicode.com needs no API key, perfect for a first demo - `response.status_code` and `response.json()` are the two attributes students will use in nearly every script they write
⏱️ Slide Timing: 4 min - The `json=` vs `data=` distinction is the #1 gotcha students hit — emphasize it explicitly - Point out how little code this is compared to the raw HTTP text two demo cycles ago — `requests` builds the message for you
⏱️ Slide Timing: 3 min - Tie straight back to the URL anatomy slide — `params` is just a Python-friendly way to build that `?key=value` section - Never hand-build query strings with string concatenation — `params=` handles escaping special characters safely
⏱️ Slide Timing: 4 min - 401 Unauthorized almost always means a missing or malformed Authorization header — students will see this often - Tie back to the `.env` / `python-dotenv` habits from earlier sessions — same discipline applies to API keys
⏱️ Slide Timing: 3 min - `raise_for_status()` is the idiomatic shortcut — it raises `HTTPError` automatically on any 4xx/5xx response - Common bug: calling `.json()` on an error response that isn't actually JSON — check status first
⏱️ Slide Timing: 3 min - This five-step flow is the same whether you're calling a weather API or a production ML endpoint — reinforce it as the reusable pattern - Good moment to preview: later sessions on building your own API will flip this diagram around, server side instead of client side
⏱️ Slide Timing: 3 min - These five cover the overwhelming majority of "my API call isn't working" questions in office hours - Suggest students bookmark this slide specifically — the fastest debugging checklist for API issues
⏱️ Slide Timing: 2 min - Suggest students screenshot this slide — it's the reference they'll reach for on every future assignment involving an API
⏱️ Slide Timing: 1 min - Highest priority to bookmark: MDN HTTP docs for day-to-day lookups, JSONPlaceholder for risk-free practice calls
⏱️ Slide Timing: 2 min - Close the loop back to the opening promise: raw HTTP, REST concepts, and a working Python call, all covered - Practice prompt: JSONPlaceholder or any open public API works — the goal is muscle memory on status codes and `.json()`