[json] Use of PUT vs PATCH methods in REST API real life scenarios

Though Dan Lowe's excellent answer very thoroughly answered the OP's question about the difference between PUT and PATCH, its answer to the question of why PATCH is not idempotent is not quite correct.

To show why PATCH isn't idempotent, it helps to start with the definition of idempotence (from Wikipedia):

The term idempotent is used more comprehensively to describe an operation that will produce the same results if executed once or multiple times [...] An idempotent function is one that has the property f(f(x)) = f(x) for any value x.

In more accessible language, an idempotent PATCH could be defined as: After PATCHing a resource with a patch document, all subsequent PATCH calls to the same resource with the same patch document will not change the resource.

Conversely, a non-idempotent operation is one where f(f(x)) != f(x), which for PATCH could be stated as: After PATCHing a resource with a patch document, subsequent PATCH calls to the same resource with the same patch document do change the resource.

To illustrate a non-idempotent PATCH, suppose there is a /users resource, and suppose that calling GET /users returns a list of users, currently:

[{ "id": 1, "username": "firstuser", "email": "[email protected]" }]

Rather than PATCHing /users/{id}, as in the OP's example, suppose the server allows PATCHing /users. Let's issue this PATCH request:

PATCH /users
[{ "op": "add", "username": "newuser", "email": "[email protected]" }]

Our patch document instructs the server to add a new user called newuser to the list of users. After calling this the first time, GET /users would return:

[{ "id": 1, "username": "firstuser", "email": "[email protected]" },
 { "id": 2, "username": "newuser", "email": "[email protected]" }]

Now, if we issue the exact same PATCH request as above, what happens? (For the sake of this example, let's assume that the /users resource allows duplicate usernames.) The "op" is "add", so a new user is added to the list, and a subsequent GET /users returns:

[{ "id": 1, "username": "firstuser", "email": "[email protected]" },
 { "id": 2, "username": "newuser", "email": "[email protected]" },
 { "id": 3, "username": "newuser", "email": "[email protected]" }]

The /users resource has changed again, even though we issued the exact same PATCH against the exact same endpoint. If our PATCH is f(x), f(f(x)) is not the same as f(x), and therefore, this particular PATCH is not idempotent.

Although PATCH isn't guaranteed to be idempotent, there's nothing in the PATCH specification to prevent you from making all PATCH operations on your particular server idempotent. RFC 5789 even anticipates advantages from idempotent PATCH requests:

A PATCH request can be issued in such a way as to be idempotent, which also helps prevent bad outcomes from collisions between two PATCH requests on the same resource in a similar time frame.

In Dan's example, his PATCH operation is, in fact, idempotent. In that example, the /users/1 entity changed between our PATCH requests, but not because of our PATCH requests; it was actually the Post Office's different patch document that caused the zip code to change. The Post Office's different PATCH is a different operation; if our PATCH is f(x), the Post Office's PATCH is g(x). Idempotence states that f(f(f(x))) = f(x), but makes no guarantes about f(g(f(x))).

Examples related to json

Use NSInteger as array index Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) HTTP POST with Json on Body - Flutter/Dart Importing json file in TypeScript json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 190) Angular 5 Service to read local .json file How to import JSON File into a TypeScript file? Use Async/Await with Axios in React.js Uncaught SyntaxError: Unexpected token u in JSON at position 0 how to remove json object key and value.?

Examples related to rest

Access blocked by CORS policy: Response to preflight request doesn't pass access control check Returning data from Axios API Access Control Origin Header error using Axios in React Web throwing error in Chrome JSON parse error: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value How to send json data in POST request using C# How to enable CORS in ASP.net Core WebAPI RestClientException: Could not extract response. no suitable HttpMessageConverter found REST API - Use the "Accept: application/json" HTTP Header 'Field required a bean of type that could not be found.' error spring restful API using mongodb MultipartException: Current request is not a multipart request

Examples related to http

Access blocked by CORS policy: Response to preflight request doesn't pass access control check Axios Delete request with body and headers? Read response headers from API response - Angular 5 + TypeScript Android 8: Cleartext HTTP traffic not permitted Angular 4 HttpClient Query Parameters Load json from local file with http.get() in angular 2 Angular 2: How to access an HTTP response body? What is HTTP "Host" header? Golang read request body Angular 2 - Checking for server errors from subscribe

Examples related to put

How to send a POST request with BODY in swift Use of PUT vs PATCH methods in REST API real life scenarios Laravel form html with PUT method for PUT routes What is the main difference between PATCH and PUT request? Curl and PHP - how can I pass a json through curl by PUT,POST,GET Test file upload using HTTP PUT method PHP cURL HTTP PUT What is the syntax for adding an element to a scala.collection.mutable.Map? How to send a PUT/DELETE request in jQuery? How to send PUT, DELETE HTTP request in HttpURLConnection?

Examples related to http-method

Use of PUT vs PATCH methods in REST API real life scenarios Should I use PATCH or PUT in my REST API? curl -GET and -X GET Which HTTP methods match up to which CRUD methods? What is the difference between POST and GET? When should I use GET or POST method? What's the difference between them?