HTTP is the contract layer underneath nearly every API you'll design or consume. Interviewers use method semantics and status codes as a quick proxy for whether you build APIs that are safe to retry, cache, and reason about under failure. It's a plain-text (in HTTP/1.1) request/response protocol at the application layer — you can read one on the wire, which is exactly what makes it worth actually looking at rather than just memorizing a table.
HTTP (HyperText Transfer Protocol) is the language a browser or app uses to ask a server for something — a web page, a photo, a bank balance — and the language the server uses to answer back. Every request follows the same shape: an action ("get me this" or "create that"), a target, and some extra details, and every response comes back with a code that says whether it worked. It's the plumbing behind almost every "load" or "submit" you do online.
Think of ordering at a restaurant counter. You (the client) state a clear request — "one coffee, medium, oat milk" — and the person behind the counter (the server) either hands it back with a confirmation that it's ready, or tells you why not: they're out of oat milk, the register's down, or you need to join a different line first. HTTP status codes are just that response, standardized: success, "you asked wrong," or "we messed up."
A request is a method + path/URL + headers + optional body. A response is a status line + headers + optional body. Here's a realistic pair for fetching a user resource:
GET /users/123 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Accept: application/json
User-Agent: curl/8.4.0
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 87
Cache-Control: private, max-age=60
ETag: "a1b2c3d4"
{"id":123,"name":"Ada Lovelace","email":"[email protected]","role":"admin"}
And a create operation, which is the case where method semantics actually change your system's correctness:
POST /orders HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
Idempotency-Key: 8f14e45f-ceea-4d6b-9c3f-abc123
{"sku":"WIDGET-1","qty":2}
HTTP/1.1 201 Created
Location: /orders/9981
Content-Type: application/json
{"id":9981,"sku":"WIDGET-1","qty":2,"status":"pending"}
Note the Location header on 201 Created — it points at the newly created resource, and the Idempotency-Key header is an application-level convention (not built into HTTP itself) that lets the server recognize "this is a retry of the same logical request" and return the original result instead of creating a second order.
Idempotent means: calling it once or calling it five times in a row leaves the system in the same final state. GET is idempotent because it doesn't change state at all. PUT /users/123 with the same full body is idempotent — sending it three times still leaves user 123 with exactly that data. DELETE /users/123 is idempotent by convention — the end state ("user 123 doesn't exist") is the same whether you call it once or five times, even though the second and later calls should probably return 404 rather than 204. POST /orders is not idempotent — calling it twice creates two orders, which is exactly why payment and order-creation APIs need an explicit idempotency key: the client generates a unique key per logical operation, sends it on every retry attempt, and the server deduplicates by that key rather than by the network call itself.
GET, HEAD, OPTIONS. Idempotent methods (repeating produces the same end state): GET, PUT, DELETE. POST is neither safe nor idempotent by default; PATCH is typically not idempotent since it applies a partial, sometimes relative, update.PUT after a timeout without an idempotency key, but not a plain POST.Authorization, Content-Type, Accept, If-None-Match (conditional requests against an ETag).Content-Type, Set-Cookie, Cache-Control, ETag, Location (used on redirects and 201 Created).200 OK, 201 Created, 202 Accepted, 204 No Content), 3xx redirection (301/302/304), 4xx client error (400, 401, 403, 404, 409, 429), 5xx server error (500, 502, 503, 504).401 Unauthorized means "you're not authenticated" (missing or invalid credentials); 403 Forbidden means "you're authenticated but not allowed" (identity is known, access is denied) — a distinction interviewers check explicitly.502 Bad Gateway means a gateway/proxy got an invalid response from an upstream server; 503 Service Unavailable means the service is currently overloaded or down for maintenance (often with a Retry-After header); 504 Gateway Timeout means the gateway gave up waiting on upstream to respond at all. Mixing these up in an incident postmortem is a real tell.# Full request/response including headers, timing, and the TLS handshake
curl -v https://example.com
# Just the response headers (fast way to check Content-Type, Cache-Control, ETag)
curl -I https://example.com
# Send a conditional GET using a previously seen ETag — expect 304 Not Modified
curl -H 'If-None-Match: "a1b2c3d4"' -v https://api.example.com/users/123
# Explicit method + JSON body, mimicking a real POST
curl -X POST https://api.example.com/orders \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8f14e45f-ceea-4d6b-9c3f-abc123" \
-d '{"sku":"WIDGET-1","qty":2}'
# In browser DevTools: Network tab → click any request → Headers tab
# shows the exact request/response headers and status code the browser saw
Q: Why does idempotency matter for a payments API specifically?
A: Networks fail in ambiguous ways — a client can time out waiting for a response even though the server successfully processed the request and the response just got lost. If the client blindly retries a plain POST /charge, the customer could be charged twice for one purchase. An idempotency key breaks that ambiguity: the server remembers it already processed that key and returns the original result on retry instead of charging again.
Q: When would you return 409 instead of 400?
A: 400 is for a malformed or invalid request on its own terms — bad JSON, a missing required field. 409 Conflict is for a request that's well-formed but conflicts with the current state of the resource — e.g. trying to create a user with an email that already exists, or a concurrent update that violates an optimistic-locking version check.
Q: Your API is returning 200 OK with {"error": "not found"} in the body. What's wrong with that?
A: It breaks anything that relies on the status code for control flow — caches will happily cache an "error" as if it were valid data, retry logic won't know to retry, and monitoring/alerting built on status-code metrics will silently miss the failure. The status code should reflect the actual outcome; this case should be a 404.
Q: How should a client handle a 429 response?
A: Read the Retry-After header if present and back off for at least that long before retrying, ideally with jitter added so many clients don't retry in lockstep. 429 means the request was understood and could have succeeded, but the client is being throttled — treating it like a hard failure (and giving up) or like a transient network blip (and retrying immediately) are both wrong.
Q: Is PATCH idempotent?
A: Not by default. PATCH {"balance": "+10"} applied twice gives a different result than applied once, so it's not idempotent. PATCH {"status": "shipped"} applied twice gives the same result, so that particular patch happens to be idempotent — but the method itself makes no guarantee either way, unlike PUT where idempotency is part of the contract.
Method and status-code discipline is one of the first things interviewers check when they ask you to design a public API. Idempotency keys come up directly in any "design a payment system" or "design a ride-booking system" prompt — you're expected to volunteer that write-heavy, retry-prone endpoints need one. Status codes drive retry logic in every service mesh and client SDK: 5xx and 429 are usually retryable (with backoff), 4xx generally isn't (the request itself is wrong, retrying won't fix it) — this distinction is exactly what a circuit breaker or retry policy in a distributed system is built around. Cache-Control/ETag headers are the mechanism a CDN or reverse proxy uses to decide whether it can serve a cached response without hitting origin at all.
The most common interview pitfall is treating POST as safely retryable without an idempotency key — a network timeout followed by a client retry can create duplicate resources. Another is returning 200 OK with an error payload instead of a proper 4xx/5xx, which breaks anything relying on status codes for control flow (caches, retries, monitoring). Use 429 Too Many Requests with a Retry-After header for rate limiting rather than a generic 400, and be consistent about 400 (malformed/invalid input) versus 404 (resource genuinely doesn't exist) versus 422 (well-formed but semantically invalid).