I have the following state machine and I want this:
- create a new order
- add items into it (listing is optional)
- confirm order by calling finish
- pay for it
- send it
And this flow is controlled via a REST web service and I’m not sure which method follows the REST principles better.

I came up with two possibilities (numbers below correspond with numbers above):
the first one – operation is specified by the path
1.
POST /create HTTP/1.1
2.
POST /addItem HTTP/1.1
<data>
<itemId>123</itemId>
</data>
GET /listItems HTTP/1.1
3.
POST /finish HTTP/1.1
4.
POST /pay HTTP/1.1
<data>
<price>123</price>
</data>
5.
POST /send HTTP/1.1
the second one – operation is specified in the body
1.
POST / HTTP/1.1
<data>
<operation>create.new.order</operation>
</data>
- returns resId
2.
PUT /{resId} HTTP/1.1
<data>
<itemId>123</itemId>
</data>
GET /items HTTP/1.1
3.
PUT /{resId} HTTP/1.1
<data>
<operation>finish.order</operation>
</data>
4.
PUT /{resId} HTTP/1.1
<data>
<price>123</price>
<operation>pay.order</operation>
</data>
5.
PUT /{resId} HTTP/1.1
<data>
<operation>send.order</operation>
</data>
The second solution seems better but I don’t know if I can specify an operation in the request’s body – is it ok or not?
Also I’m not sure if I should use PUT or POST at 3 and 5 in the second solution because I don’t really update the resourse, I just change the state machine’s state.
If none of these is correct how should I do it?
How about:
From that you get back a
201 Createdresponse, along with aContent-Locationheader which specifies the URL of the just-created order, something like/orders/2876276ok, then to add an item to an existing order:
The message can include url-encoded form data, specifying whatever you’d like to add to the order.
Then,
…gets some representation of the order. You could do content-type negotiation to figure out whether to format it as json, xml, or whatever. The response message would provide all the information about the order that you wish to share with the requester. Date received, status, order items, and so on.
I don’t know what
FINISHis exactly, but from my naive view it is just a special kind of update to the order item, so that is just another POST with special form data. After a POST with finish, the response to aGETwill include a special indicator stating that the order is “complete.”To handle the payment, you may just use another POST on the same order. If your design calls for tracking accounts receivable, then you may have another object entirely. In other words if there is not one payment per order, but if a customer gets billed monthly or on some other rhythm, then you would have another object category like
/accounts/39839. But in the simple case you could just use the order object to track payment state.So,
POSTto an order URL to provide credit-card or paypal information to obtain payment. Subsequently, a GET will retrieve a representation that includes the order has been paid for.The “Send” is not an HTTP request, I would think. Send is something YOU do to fulfill the order after receiving payment. Perhaps some system in your shop can post to
/orders/872872872to mark it sent. Subsequently, a GET will retrieve a representation that includes the order has been shipped, with maybe a tracking number.I would be careful about using
PUT. PUT indicates a insertion of an entire object into a repository, and implicit replacement if the object already exists. But your model doesn’t call for that. The order manager manages the order, and exposes a limited set of operations (create, add item, etc) on each order. Insertion of an entire order is not one of those operations. Therefore PUT seems like the wrong thing in your scenario.PUT would be right if you were inserting a document into a repository. For example imagine an auction where you offer an item for sale. You might use
POSTto create the auction item, then receive/items/29829as the URL for the item. Then a PUT might be used to add an image to the item being auctioned – you might PUT to/items/29829/mainImageor something like that. PUT implies you know the URL of the thing to which you are PUT-ting.you asked:
HTTP has only a limiited set of verbs. Your “order” object has a variety of states. You need to map the HTTP verbs to the state transitions. It makes sense to use POST to the order object for each state transition or state change. You might think of this as specifying “an operation” in the request body, but to me it is specifying the details of the request in the request body. This is precisely what the request body is for.
For more background, check out How to get a cup of coffee.