---------------------
I'm designing an API, and trying to place PUT and PATCH into my design ideology.
In my experience, most APIs stick to GET and POST almost exclusively. And AFAICT, PUT and PATCH don't really add much that POST doesn't have. In fact, I kind of prefer the idea of having the url tell me what's going on explicitly rather than trying to infer from the request type. For example:
- to create: `POST user`
- to update: `POST user/12354`
vs
- to create: `POST user/`
- to update: `PATCH user/`
--------
I'm working alone on this project, otherwise I'd ask a coworker, but what do you guys think? What feels intuitive and clear to you?
I've never seen PATCH [2] used effectively. I would expect a PATCH request body to be a diff of an existing file which is retrievable with GET. Optimizations are not worthwhile for most projects.
Most APIs do not store binary blobs. Most APIs operate on complicated sets of database tables and should use POST, GET, and maybe DELETE.
[0] https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PU...
[1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201
[2] https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PA...
Show all comments: GET api/comments
Create a comment: POST api/comment/
Show a comment: GET api/comment/1234
Edit the whole comment: PUT api/comment/1234
Edit part of the comment (like an attachment): PATCH api/comment/1234
Delete: DELETE api/comment/1234
That said, PUT and PATCH can be quite useful if you're dealing with CRUD operations. If you want or need your API to be idempotent, use POST for creation and updating. If being idempotent isn't a requirement - or even a negative - then adhere to the convention: POST for creation and PUT/PATCH for update.
PATCH is really nice to support when your objects are even moderately large or you want to reduce bandwidth costs. For example, let's say you have a user object in a NoSQL DB and each user is a JSON object with 100 keys. If you use POST or PUT to update, you're basically requiring that the user of your API...
* Perform a GET to actually fetch the entire user object * POST/PUT the entire object back with the changes
In addition, you're likely going to want the API to track the version of the object, otherwise you run into issues with multiple clients trying to update at the same time. This can be very problematic when updating the entire object. So you're basically wasting cycles on the server fetching data, wasting bandwidth for data that isn't going to be used at all, and possibly writing extra code to handle conflicts.
With PATCH, you don't need to GET anything. You can update fields pretty easily w/o even knowing what's already there:
PATCH /user/12345 { "age": 10 }
Very little bandwidth is used. If you still need versioning along with that (yes, you do if this is more than a pet project) to resolve conflicts, then you can use a HEAD request for the user and return the version of the object in an HTTP header. Multiple patches from different versions can all be successfully applied on top of each other until a conflict arises. But, then you're getting into vector clocks or other solutions that are outside the scope of the question.
Circling back, yes, PUT and PATCH can be very useful. ;)
HTH
But you seem like a thoughtful person, so maybe use CAREFULLY. To indicate to clients that they should handle data with love and attention to formatting.
:)
GET and POST should cover most of your bases. I like PUT and PATCH, too. I think you should use them when you want to keep your HTTP API nice and neat, because they provide useful intuitive signals to developers. Remember, as others have mentioned here, not all clients have the ability to send those verbs, so provide a way to override POST.
Oh, and sort of unrelated, not sure if you need to read this, but just in case you get to feeling playful, keep in mind that WebDAV verbs are for WebDAV. Not that you've mentioned anything WebDAV related, but I've noticed some developers who ask questions like this end up reading the relevant RFCs and start thinking to themselves, "...well what if I..."
If you prefer more of a one query or request to rule them all then GraphQL may align better to your preferences.
I was recently working with the Vultr API, and they follow this pattern as well: https://www.vultr.com/api/#section/Introduction
i.e. use POST to create new things and PUT and/or PATCH to change existing things.
I agree with other commenters that the whole thing is rather silly.
(1) Accept it is all convention so you can do whatever you want.
(2) Accept it is all convention and follow it
I'd recommend (2) personally as that allows your API consumers to grok your API quicker due to existing expectations. If you go with (1) then do whatever feels right.
The convention:
- POST is always used to create something new. This means the URL should not specify any ID for the object being created, though it can for the hierarchy of objects it belongs to. For example to add an address to an existing user with ID 123 use POST /users/123/addresses with a body of address content.
- PUT is usually used to update an existing something, so for address 3 of that user PUT /users/123/addresses/3 with a body like a POST.
- PATCH is used to partially update an existing something, so PATCH /users/123/addresses/3 with a body just like PUT/POST, and the difference being you supply only the properties on the model you want to change. Often used to patch up large models with small changes.
So the URL is the full address to an individual resource in PUT and PATCH (/users/123/addresses/3), whilst for POST it goes to the resource's parent collection (/users/123/addresses). A POST with an ID as per your example for updating would (by convention) be wrong as it would be expected that POST would create a new instance with its own ID so the one in the URL is not just irrelevant but also misleading. As for your PATCH example for update, it would be expected that the URL tells it which resource to update so (again by convention) the API would not know what to update without that extra bit.
In summary - conventions are to help your API consumers get up to speed via existing expectations whilst also matching the main- and side-effects those consumers expect without them needing to refer to your documentation or treat your API as a special snowflake (as they would see it) amongst the many convention-based ones they probably use from elsewhere.
I also created an associated library/spec json-patch-rules[2]
If you're using Mongoose ORM, I made mongoose-patcher[3].
When coupled with fast-json-patch[4] and clone/deep compare on the client, these technologies can make your life really easy.
[1] - http://jsonpatch.com/
[2] - https://github.com/claytongulick/json-patch-rules
Forcing callers to send a PUT with the whole user profile object every time someone updates a single thing is pretty wasteful.
+ if a caller is a caller that listens to events like "user u wants to update their number to 555 555 555, please do that", they don't even have the whole user object, they'd have to make a GET first, then set the new number, then send that whole PUT. That in turn introduces race conditions where their PUT could overwrite some other change someone else made to eg the email address in the meantime.
So there's definitely a case for PATCH! It all depends on your use case. For many systems it might not be something that's an issue.
Yes, it matters. You're misusing POST in the first example.
C = POST R = GET U = PUT/PATCH D = DELETE
Doing anything else is an anti-pattern for interop on the web.