PUT vs POST
PUT vs POST for REST APIs: idempotency, which one creates vs replaces a resource, and the mistake most APIs make.
Last updated
The short answer
POST creates a new resource and lets the server assign its URL, so calling it twice can create two resources. PUT replaces a resource at a URL the client already knows, and calling it twice with the same body should leave the server in the same state — that's what 'idempotent' buys you.
| Dimension | PUT | POST |
|---|---|---|
| Idempotent | Yes — repeat calls, same result | No — repeat calls, more resources |
| Target URL | Specific resource (/orders/42) | Collection (/orders) |
| Semantics | Replace the resource entirely | Create a new subordinate resource |
| Who picks the ID | Client already knows it | Server usually assigns it |
| Typical success status | 200 OK or 204 No Content | 201 Created |
| Partial update | Not intended — that's PATCH | Common in practice (loosely) |
Choose PUT when
- →You're updating a resource at a URL the client already owns, like saving a user's profile at /users/42.
- →You want retries to be free — a dropped connection and a resubmit should never create duplicates.
- →You're replacing the entire resource representation, not patching one field.
Choose POST when
- →You're creating a new resource and letting the server assign its ID and URL, like submitting a new order.
- →The action isn't really a resource update at all — triggering a job, sending an email, processing a payment.
- →You're sending data that doesn't map cleanly onto REST resource semantics, like a search with a large payload.
The catch nobody mentions
Idempotent doesn't mean 'safe' or 'side-effect free' — a PUT handler that decrements a counter each call, rather than setting an absolute value, breaks the idempotency guarantee even though the verb promises it. Using PUT doesn't make retries safe automatically; your handler has to actually implement replace-with-this-representation semantics for the guarantee to hold.
Common mistakes
POST /users/123Posting to a specific resource URI usually means you meant to update it, and POST makes no idempotency promise — a retried request can apply the change twice. PUT or PATCH names the intent correctly.
PUT /users/123PUT /usersPUT targets a specific resource at a known URI. Putting to a collection asks the server to replace the entire collection, which is almost never intended and which most APIs simply reject.
PUT /users/123 with only the changed fieldsPUT replaces the whole resource, so omitted fields should be cleared. Servers that quietly merge instead are behaving like PATCH under a PUT label, which means clients cannot rely on either behaviour.
Questions
What does idempotent actually mean here?
Sending the same request twice has the same effect as sending it once. It does not mean the response is identical — a second PUT may return 200 where the first returned 201 — only that the server ends up in the same state.
When should I use PATCH instead?
When you are sending a partial update. PUT means replace-with-this, so a PUT missing a field should null it. PATCH exists precisely so partial updates do not have to pretend to be full ones.
Can PUT create a resource?
Yes, when the client chooses the identifier — PUT to a URI that does not exist yet is a valid create, returning 201. That is the main case where the choice between the two is genuinely open.
Does any of this matter in practice?
It matters for retries. Proxies, load balancers and client libraries retry idempotent methods automatically and refuse to retry POST, so mislabelling turns a safe retry into a duplicate order.
What status code should each return?
201 with a Location header when something was created, 200 or 204 when it was updated. Returning 200 for everything works and throws away information the client could have used.