8

For example I need to update the status of a "Purchase Order" from "Draft" to "Sent". What's the best way of doing this?

Do I just the update the status field in the client side and then just POST the whole entity to /purchase_order/1

And how about events? For example I want to trigger that all Purchase Orders be set to "Sent", what's the best practice for this, in terms of the endpoint and the responsibilities of the client?

wnoveno
  • 201
  • 2
  • 4

2 Answers2

8

If you google "REST partial update" you will get a lot of opinions.

Having said that I'll give you my thoughts.

A PUT should be used for a full update of a resource so only changing one parameter you are better off PUTting to /purchase_order/1 a recent result of a GET to /purchase_order/1 with the status field changed from draft to sent.

Depending on the semanics of your system you might consider a draft and a sent item to be different resources (with different primary keys) and so a GET to /purchase_order/1, change the status, then POST to /purchase_order/ (although I'm guessing that in this case purchase orders don't become new purchase orders when thir status changes).

Another option would be to send a PUT to /purchase_order/1/status with a value of sent, this could then be interpreted on the server side as an update to the sub resource status of the resource purchase_order. You could even return 303 pointing back at the /purchase_order/1 resource to let the client know that a different resource than they interacted with has changed and where to find that resource.

You could consider the PATCH verb but if you follow the semantics properly then you shouldn't just send the requested state, but rather a content-type that you specify that lists a set of operations you wish to be applied.

If an action is going to have side effects then you need to make this clear in your API. So be careful when using PUT, which is designed to be idempotent.

Encaitar
  • 3,053
  • 19
  • 26
1

Please check this Stackoverflow question.

Basically you have two possibilities:

  • Use a PATCH request
  • Use a POST request with the partial data you want to update and return a 303 HTTP status code. This is used to indicate that the POST request has been executed and a resource has been changed. This returns also the location of the changed resource.

I use the second approach in my applications. E.g. for a changed Order:

{
  "id": 1,
  "status": 2
}

Then change the Order on the server and return a 303 status code with the location of the changed Order.

For the events: Theoretically to follow exactly the REST methodology you would have to create for each Order a POST request with the changed Status and receive the location of the resource back. However in practice you can send an array of the changed Orders to the server and receive a list of the resource locations.

devz
  • 243
  • 1
  • 2
  • 8
  • 2
    Why using `POST` instead of `PUT` ? The update of a status is idempotent , thus i don't understand why you recommend to use `POST`... (`POST` is not safe nor idempotent) – AilurusFulgens Feb 26 '16 at 10:05
  • 1
    I think you only really need to use 303 if you are pointing them to a different resource (see other) rather than the resource they POSTed to. – Encaitar Feb 26 '16 at 10:11
  • @AilurusFulgens one **should not** to use `POST` to modify existent resource, but `PUT` is really worst because it replace entire resource with provided parameters. – Andre Figueiredo Dec 31 '17 at 15:29
  • @Encaitar I also think using POST + 303 is not a good approach. Does not make sense creating a new item over an existent and then pointing to new. It's basically a "DELETE old item" + "POST new item", then receiving 201 + location header info. – Andre Figueiredo Dec 31 '17 at 15:35