HTTP is older than most engineers using it, and richer than most APIs that use it. A good API designer knows the protocol well enough to use what is already there instead of inventing it again in JSON.
Methods and What They Mean
| Method | Purpose | Safe? | Idempotent? |
|---|---|---|---|
| GET | Read a resource | Yes | Yes |
| HEAD | Read headers only | Yes | Yes |
| POST | Create / process | No | No |
| PUT | Replace whole resource | No | Yes |
| PATCH | Partial update | No | Maybe |
| DELETE | Remove resource | No | Yes |
| OPTIONS | What is allowed? | Yes | Yes |
- Safe — does not change server state. Browsers, caches, and prefetchers may call them freely.
- Idempotent — repeating the call has the same effect as one call. Critical for retries.
Status Codes That Matter
| Range | Meaning |
|---|---|
| 2xx | Success |
| 3xx | Redirection |
| 4xx | Client error — caller did something wrong |
| 5xx | Server error — your fault, or upstream |
The ones you will use most
- 200 OK — generic success.
- 201 Created — resource created; include
Locationheader. - 202 Accepted — async work started; not yet complete.
- 204 No Content — success, nothing to return.
- 301 / 302 — moved permanently / temporarily.
- 304 Not Modified — caller can use its cached copy.
- 400 Bad Request — malformed input.
- 401 Unauthorized — no or invalid auth (poorly named — really means unauthenticated).
- 403 Forbidden — authenticated but not allowed.
- 404 Not Found — resource does not exist.
- 409 Conflict — request collides with current state.
- 422 Unprocessable Entity — body parsed but semantically invalid.
- 429 Too Many Requests — rate limit exceeded.
- 500 Internal Server Error — generic server error.
- 502 / 503 / 504 — bad gateway, service unavailable, gateway timeout.
The most common API anti-pattern is 200 OK with {"error": "..."} in the body. Don't. Use the status the protocol gives you.
Headers That Earn Their Keep
| Header | Use |
|---|---|
Authorization | Auth credentials (Bearer, Basic) |
Content-Type | What is in the body |
Accept | What the client wants back |
Cache-Control / ETag | Caching |
X-Request-Id | Correlation across services |
Idempotency-Key | Retry safety for non-idempotent ops |
Retry-After | Tell the client when to try again |
Idempotency in Practice
Networks fail. Clients retry. If the original POST actually succeeded but the response was lost, the retry creates a duplicate. The fix is an idempotency key:
POST /payments
Idempotency-Key: 7c3f...e91
Content-Type: application/json
{ "amount": 1000, "currency": "USD" }
The server stores the result keyed by the idempotency key for some window (24h is typical). A retry with the same key returns the original response without re-charging the card. Stripe popularised the pattern; it is now industry standard.
Content Negotiation
One URL can serve multiple formats based on what the caller asks for:
GET /reports/42
Accept: application/json → JSON
GET /reports/42
Accept: text/csv → CSV
GET /reports/42
Accept: application/vnd.api.v2+json → versioned JSON
This same mechanism powers media-type versioning, which we'll revisit in the versioning lesson.
Caching
HTTP has a powerful built-in caching model. Use it.
Cache-Control: public, max-age=300— cacheable for 5 minutes.ETag: "abc123"— opaque version; clients sendIf-None-Match; server returns 304 if unchanged.Last-Modified+If-Modified-Since— older equivalent.Vary: Authorization— separate cache per auth header.
Compression and HTTP/2 / HTTP/3
- Always enable
gziporbrat the gateway. Free latency. - HTTP/2 multiplexes — no per-connection-per-request penalty. Reduces incentive for batching.
- HTTP/3 (QUIC) handles lossy networks better — significant for mobile.
Cert Mapping
| Cert | HTTP topic |
|---|---|
| AWS SAA | API Gateway methods, throttling, response codes |
| AWS Cloud Practitioner | HTTP basics, REST overview |
The next lesson uses these foundations to model REST resources properly.