HTTP Methods, Status Codes, and Headers

9 min read

If REST is the architectural style, HTTP is the alphabet you write it in. Every API call you ever test boils down to three things: a verb (the method), a number (the status code), and a stack of headers (metadata about the request and response). This lesson teaches each in the depth a working QA engineer actually needs — and flags the handful you should know cold.

HTTP methods (verbs)

The method tells the server what kind of operation you want. The five you'll use 99% of the time map cleanly onto CRUD operations:

  • GETread. Retrieve a resource. No request body. Should never modify state. Safe to retry.
    GET /api/users
    GET /api/users/123
    
  • POSTcreate. Add a new resource. Has a request body. Not idempotent — calling twice creates two rows.
    POST /api/users
    Body: {"name": "Alice", "email": "alice@test.com"}
    
  • PUTreplace. Replace the entire resource at a known URL. Body should contain every field. Idempotent — calling N times leaves the same state as calling once.
    PUT /api/users/123
    Body: {"name": "Alice", "email": "alice@new.com", "role": "admin"}
    
  • PATCHpartial update. Change just the fields you specify. Body contains only those fields. Usually idempotent if the API is well-designed.
    PATCH /api/users/123
    Body: {"email": "alice@new.com"}
    
  • DELETEremove. Drop a resource. Idempotent — deleting an already-deleted resource still leaves it deleted.
    DELETE /api/users/123
    

Two more you'll occasionally meet:

  • HEAD — same as GET but the server returns only headers, no body. Useful to check whether a resource exists without downloading it.
  • OPTIONS — asks the server which methods are allowed on a resource. Browsers send these automatically as CORS preflight checks.

POST vs PUT vs PATCH

This trio confuses everyone at first. The cleanest rule:

VerbUsed forBody shapeIdempotent?
POSTCreate newWhole resourceNo
PUTReplace existingWhole resourceYes
PATCHUpdate part of existingOnly changed fieldsUsually

If you PUT /users/123 with no email field, a strict API will clear the email — because PUT means "replace with this." If you PATCH /users/123 with no email field, the email is left untouched.

Status codes

The server's first answer to your request is a three-digit number. Codes are grouped by their first digit:

  • 2xx — Success. Your request worked.
  • 3xx — Redirect. Look elsewhere for the resource.
  • 4xx — Client error. Your request is wrong (bad input, missing auth, wrong URL).
  • 5xx — Server error. The server fell over. Not your fault.

The codes you should know without looking up:

  • 200 OK — generic success, usually with a body.
  • 201 Created — successful POST that created a resource.
  • 204 No Content — success with no body (typical after DELETE).
  • 301 Moved Permanently / 302 Found — redirects.
  • 304 Not Modified — cached copy is still valid.
  • 400 Bad Request — request is malformed (missing field, invalid JSON).
  • 401 Unauthorized — auth missing or invalid.
  • 403 Forbidden — auth is valid, but you can't do this action.
  • 404 Not Found — resource doesn't exist.
  • 405 Method Not Allowed — the URL exists but doesn't support this verb.
  • 409 Conflict — request collides with current state (e.g. duplicate email).
  • 422 Unprocessable Entity — request is well-formed but semantically wrong.
  • 429 Too Many Requests — rate limit exceeded.
  • 500 Internal Server Error — something on the server crashed.
  • 502 Bad Gateway / 503 Service Unavailable — upstream failure or overload.

Where the codes live on the number line

The most common interview trap: the difference between 401 and 403. 401 means "I don't know who you are" — auth missing or invalid. 403 means "I know who you are, but you can't do this." Permission tests should expect 403, not 401.

A second trap: APIs that return 200 with {"error": "User not found"} in the body. That's a design bug — the status code should reflect the outcome (404 here). When you spot this in the wild, raise it; don't bake the bad behaviour into your tests.

For a printable reference, the HTTP Status Codes cheat sheet lists all the standard codes side by side.

Headers

Headers are key/value metadata attached to both requests and responses. They're how clients and servers communicate everything except the payload itself.

Common request headers

  • Content-Type — what type of data is in the body. Most common: application/json. Also application/xml, multipart/form-data (file uploads), application/x-www-form-urlencoded (HTML forms).
  • Authorization — the credential. Authorization: Bearer eyJhbGciOiJI... for JWT, Authorization: Basic dXNlcjpwYXNz for basic auth.
  • Accept — what the client wants back. Accept: application/json says "send me JSON, please."
  • User-Agent — what the client claims to be. Sometimes inspected by servers; rarely matters for tests.
  • X-Request-Id — a custom header to trace a request through logs. Common in production systems.

Common response headers

  • Content-Type — what the server actually sent (mirror of the request header but on the response side).
  • Content-Length — size of the response body in bytes.
  • Cache-Control — caching rules. max-age=3600 means "cache for an hour." no-store means "never cache."
  • ETag — a fingerprint of the response. Send it back as If-None-Match to ask "has this changed?"
  • X-Rate-Limit-Remaining / Retry-After — rate-limit signals.
  • Set-Cookie — sets a cookie on the client. Common in login flows.

When debugging an API call, the headers often tell you more than the body. A 401 with no WWW-Authenticate header? The server probably forgot to set it. A 200 with Content-Type: text/html when you expected JSON? You hit an error page that's pretending to be a success.

A complete picture

Putting it together, a typical authenticated POST looks like:

POST /api/orders HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJI...
Accept: application/json

{"productId": 42, "quantity": 2}

And a typical response:

HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/orders/9012
X-Request-Id: req_abc

{"id": 9012, "status": "pending", "total": 49.98}

Method, URL, headers, body. Status code, headers, body. Every API test you write asserts on some combination of these.

⚠️ Common mistakes

  • Using GET for state changes. Browsers, proxies, and crawlers freely re-issue GETs and pre-fetch links. A GET /users/123/delete will eventually be triggered by a bot — making destructive GETs is one of the oldest API security bugs.
  • Treating 401 and 403 as interchangeable. They mean different things. Permission tests should expect 403; auth-failure tests should expect 401.
  • Asserting only on status codes. A 200 response with the wrong body is still a bug. Always check status and a key field of the body.

🎯 Practice task

Map verbs and codes to a real API. 20 minutes.

  1. With curl: curl -i https://jsonplaceholder.typicode.com/users/1. The -i flag prints headers. Copy the status line and the response headers — what Content-Type did the server send?
  2. Send a POST: curl -i -X POST https://jsonplaceholder.typicode.com/posts -H "Content-Type: application/json" -d '{"title":"hi","body":"y","userId":1}'. What status code did you get? Why is it not 200?
  3. Send a request to a non-existent path: curl -i https://jsonplaceholder.typicode.com/no-such-thing. What status came back?
  4. Send a DELETE: curl -i -X DELETE https://jsonplaceholder.typicode.com/posts/1. Note the status. (JSONPlaceholder is a fake — it returns success without actually deleting anything.)
  5. Open the HTTP Status Codes cheat sheet. Memorise the eight codes called out above (200, 201, 204, 400, 401, 403, 404, 500). These eight cover the bulk of what you'll see day to day.
  6. Stretch: explain to a colleague the difference between PUT and PATCH using the user-record example. If they understand it after one minute, you've got it.

You can now read any HTTP transaction at a glance. The final lesson of this chapter unpacks what's inside a request and a response — JSON bodies, XML, and how to make sense of both.

// tip to track lessons you complete and pick up where you left off across devices.