You are specifying the successful responses for create, update and delete endpoints in an HTTP API. How do you choose between status 200, 201 with a Location header, and 204, and when would you return a body at all?
answer
- 201 + Location = created
- 200 = success with a body
- 204 = success, no body ever
- DELETE → 204 (or 200/202), be consistent
- Never 200 with success:false
basics
~20 s201 plus a Location header when the request created a new resource; 200 with a body when you have something useful to return; 204 when the operation succeeded and there is genuinely nothing to send. Deletes typically return 204.
solid answer
~50 s- **201 Created** — the request brought a new resource into existence. Include `Location` pointing at it, and usually the representation in the body so the client does not need a second round trip. - **200 OK** — success with a body. Use it for updates that return the stored representation, and for creates only when there is no single new resource URL to point at. - **204 No Content** — success, and the response deliberately has no body. Typical for `DELETE`, and for updates where the client already knows the resulting state. Guidance I apply: prefer returning the representation on writes (`200`/`201` with a body) because servers normalize, set timestamps, and compute derived fields — sending them back saves a GET and prevents client-side drift. Reserve `204` for cases with truly nothing to say. Never return `200` with an error payload inside; the status line is the contract.
go deeper
Know the three codes and their triggers: created → 201 with Location, success with data → 200, success with nothing to return → 204.
Explain why returning the representation on writes is usually better than 204, and how PUT-upsert uses 201 versus 200 to signal insert versus replace.
Talk about generic consumers — retries, gateways, monitoring — and enforcing consistency across services rather than per controller.
Set a house rule for write responses and encode it in the API guidelines and linter so every team's creates and deletes look the same.
## The status line is part of the contract Generic clients — proxies, SDK generators, retry libraries, monitoring — read the status code, not your JSON. Choosing 2xx codes deliberately is what lets them behave correctly without understanding your domain. ## 201 Created Meaning: the request resulted in one or more new resources. The response should carry `Location` with the URL of the primary new resource: ``` POST /orders HTTP/1.1 201 Created Location: /orders/42 Content-Type: application/json {"id":42,"status":"new","createdAt":"2026-08-12T10:00:00Z"} ``` Two practical points. First, `Location` is what makes 201 useful — a 201 without it forces the client to parse the body and guess the URL template, which couples it to your routing. Second, including the body is optional but almost always right: the server has just computed the id, timestamps, defaults, and any normalization, and returning them saves a follow-up GET. 201 also applies to PUT when the PUT created the resource rather than replacing one — that distinction is exactly how a client learns whether its upsert was an insert. ## 200 OK The default success with a body. Use it for: - reads, - updates (`PUT`/`PATCH`) where you return the resulting representation, - POST that performed a *process* rather than creating an addressable resource (a validation call, a calculation, a search). A POST that creates several resources, or creates something with no meaningful individual URL, is better served by 200 with a body describing what happened than by a 201 whose `Location` would be a lie. ## 204 No Content Success, and the client must not expect a body — the response has none, and headers such as `Content-Type` are meaningless. It is the natural answer to `DELETE`, and to writes where returning state is pointless (a toggle the client already knows the outcome of, a bulk no-op). The cost is diagnostic: 204 gives an operator nothing in a log or a browser network tab, and gives the client nothing to reconcile against. That is why many teams' default is "return the representation" and 204 is the exception, not the rule. A subtlety worth knowing: 204 must not have a body, so if you later want to add one you must change the status code too — a contract change for clients that assert on it. ## Deletes Three defensible answers, and consistency matters more than the choice: - `204 No Content` — deleted, nothing to say. Most common. - `200 OK` with a small body — deleted, and here is what was deleted or a summary. - `202 Accepted` — deletion was queued (cascades, GDPR erasure, large object cleanup). Deleting something that is already gone is the classic question. `404` is defensible and honest; `204` is defensible on the grounds that DELETE is idempotent and the client's goal — "it is not there" — is satisfied. Pick one, document it, and be uniform, because clients write retry logic against it. ## Anti-patterns **200 with an error inside.** `HTTP/1.1 200 OK` + `{"success": false}` breaks every generic consumer: retries do not trigger, dashboards show a healthy service, and gateways cache the failure. The status line must reflect the outcome. **201 for updates.** Some frameworks default to it. It tells the client something new exists when nothing did. **204 with a body.** Some stacks will happily write bytes after a 204; intermediaries may drop or mangle them, and clients that respect the spec never read them. **Inconsistency across endpoints.** One create returning 201, another 200, a third 204 forces every client to special-case your API. Fix it at the framework level, not per controller. ## Quick decision rule Did something new come into existence at a URL? → **201 + Location** (body recommended). Otherwise, do you have anything useful to return? → **200 with body** if yes, **204** if genuinely no.
- What should DELETE return when the resource is already gone?Either 404 (honest about the current state) or 204 (the client's desired end state holds, which fits DELETE's idempotency). Both are used in practice; what matters is picking one, documenting it, and applying it uniformly, because clients build retry logic on it. 404 is slightly more informative for debugging, 204 is friendlier to retries.
- Should a POST that creates a resource return the created representation in the body?Usually yes. The server has just assigned the id, timestamps, defaults and any normalized values, so returning them saves the client a GET and prevents its local copy from drifting. The exception is very large representations or fan-out creates, where a 201 with Location alone keeps the response small and lets the client fetch on demand.
saying these in an interview costs you the question
- Returning 200 with an error object in the body instead of a 4xx/5xx status
- Omitting the Location header from a 201 response
- Sending a body with 204
- Using 201 for an update that created nothing
- Choosing a different success code per endpoint with no rule behind it