I've seen tons of examples on how to structure URL's for basic CRUD operations but seen very little when talking about more Command-like operations, or application service calls.
For example, let's say in my application service I have a call like RemoveOldOrders(int customerId) that would remove any order from the system that is over 2 years old for a customer with id "customerId". What would the URL look like on my restful service? What would the payload of the call look like? What HTTP method (POST?) would I use?
My thought is it would be something like this:
/Customer/1/RemoveOldOrders as a POST, with an empty body (as the customerID would come from the url).
Are there good guidelines on something like this?
Update: I feel like I need to clarify my question a bit in lieu of the comment about a possible duplicate post (yes, that post is asking essentially the same thing but I don't really feel the question was answered well).
What if I want to perform an operation against a resource but that operation doesn't fit into the standard HTTP verbs?
Another example: my application is hooked into an ESB and there needs to be a way to force a projection of my resource onto the ESB for processing? In my current SOAP-based web service I'd have a method like:
ExportCustomer(int customerId)
Now, in the case of a RESTful service, how could I represent this action in a uri? Option 1 from Brian Kelly's answer seems like the most logical, something like:
POST http://someapp/api/customer/1/export
or would:
POST http://someapi/api/customer/export/1
be better?
Anytime you want to model verbs like "remove", you should think of DELETE. Similarly, for "create" think POST (and/or maybe PUT), for "read" think GET and for "update" think PUT (or maybe PATCH).
So for your example of "remove old orders", you should definitely use DELETE. Now your only remaining challenge is how to identify the orders that should be removed. Once you figure that out, the URI scheme will fall into place with it.
Here are some options:
DELETE http://your-api.com/old-orders
Here, the meaning and range of old-orders will be determined by the server receiving this request. This frees the client from having to do so, but removes their ability to change that range.
GET http://your-api.com/order-query?days-older-than=730
This returns a Location URI of http://your-api.com/order-query-result/{some ID} that represents the set of old appointments. Then you can simply issue a DELETE on that URI to purge the old records in one fell swoop.
Instead of forcing the client to remember to issue deletion commands of this type, offer some kind of configuration resource that can be manipulated via your API to set some field like purgeRecordsOlderThanDays=730, and just let the server do it automatically for you in a cron-like fashion. That would be my preferred approach.
For exporting, then you need to remove the "export" verb and replace it with an ESB representation of the resource: -
GET http://someapp/customer/{id}
The response includes a link to export: GET http://someapp/customer/{id}/ESB
Getting on the export link returns the ESB representation (with appropriate content type)
For example, let's say in my application service I have a call like
RemoveOldOrders(int customerId) that would remove any order from the
system that is over 2 years old for a customer with id "customerId".
What would the URL look like on my restful service? What would the
payload of the call look like? What HTTP method (POST?) would I use?
RemoveOldOrders(int customerId)
DELETE /oldOrders {customerId: id}
DELETE /customer/{id}/orders?old=true
etc...
You should read more about uniform interface / resource identifiers and the HTTP method specification.
The URL does not really matters. What matters that you should have resource with resource identifiers (URLs) and you have to manipulate them by using an uniform (standard) interface, like the call of HTTP methods.
Related
I'm looking for a best way for implementing an endpoint of REST-full application that will be responsible for creating a new library orders. Let's assume that I have the following resources.
If I want to get all books of a particular author I can use the next endpoint:
HTTP GET
api/books/author/123
If I want to fetch all orders of a particular book I can use the endpoint provided below:
HTTP GET
api/books/456/orders
My question is what will be the most suitable URL and a request model for an endpoint that will create orders?
From my perspective it can be
HTTP POST
api/books/456/orders
And one more question. Is it a good practice in REST to use request models like CreateOrder? If I want to create a REST-full web application can I use the following request model:
class CreateOrder
{
AuthorId: number;
BookId: number;
ClientId: number;
}
Sometimes it makes me confused. Should request models look like our resources or not?
Let's assume that I have the following resources.
Your "resources" look suspiciously like "tables". Resources are closer to (logical) documents about information.
what will be the most suitable URL and a request model for an endpoint that will create orders
For the most part, it doesn't matter what URL you use to create orders. In a hypermedia application (think HTML), I'm going to submit a "form", and the meta data associated with that form are going to describe for the client how to compose a request from the form data.
So the human, or the code, that is manipulating the form doesn't need to know anything about the URL (when is the last time that you looked to see where Google was actually sending your search?)
As far as general purpose web components are concerned, the URL/URI is just an opaque identifier - they don't care what the spelling means.
A thing they do care about is whether the spelling is the same as something that they have cached. One of the consequences of a successful POST /x message is that the cached representation(s) of /x are invalidated.
So if you like, you can think about which cached document should be refreshed when an order is created, and send the request to the identifier for that document.
Should request models look like our resources or not?
It's not necessary. Again, think about the web -- what would the representation of create order look like if you were POSTing form data?
clientId=1&bookId=2
or maybe
bookId=2&copies=3
If the "who is creating an order" is answered using the authorization headers.
In our HTTP requests and responses, we are fundamentally sending message representations - sequences of bytes that conform to some schema. There's no particular reason that those sequences of bytes must, or must not, be the same as those we use elsewhere in the implementation.
Your end-point does not need to always start with /books. You can introduce another end-point /orders for creating or getting orders. So , to create an order , you can :
HTTP POST
api/orders
And does the 'request model' that you mean is the HTTP request body structure ? If yes, it does not need to be 100% match with your back-end persisted/domain model. Just include enough parameters that the server needs to know in order to create an order. (e.g. Include bookId rather than the whole book object etc.)
BTW , to get all books for a particular author , it is more common to use query parameter such as :
HTTP GET
api/books?authorId=123
What you are doing is not REST, it is CRUD over HTTP. REST does not care about your URI structures and resources are very far from database tables. If CRUD is all you need, then download a CRUD generator library https://github.com/search?q=crud+generator&type=Repositories, which will generate all the upper and you won't need to write it manually.
my REST API format:
http://example.com/api/v1.0/products - get all products
http://example.com/api/v1.0/products/3 - get product with id=3
Also, the products can be orginized into a product groups.
What is a proper way to get all product groups according to REST best practices:
http://example.com/api/v1.0/products/groups
or
http://example.com/api/v1.0/productgroups
...
another option ?
I can't agree with Rishabh Soni because http://example.com/api/v1.0/products/groups may lead to ambiguity.
I would put my money on http://example.com/api/v1.0/productgroups or even better http://example.com/api/v1.0/product_groups (better readability).
I've had similar discussion here: Updating RESTful resources against aggregate roots only
Question: About the thing of /products/features or /product-features,
is there any consensus on this? Do you know any good source to ensure
that it's not just a matter of taste?
Answer: I think this is misleading. I would expect to get all features
in all products rather than get all possible features. But, to be
honest, it’s hard to find any source talking directly about this
problem, but there is a bunch of articles where people don’t try to
create nested resources like /products/features, but do this
separately.
So, we can't be sure http://example.com/api/v1.0/products/groups will return all possible groups or just all groups that are connected with all existing products (what about a group that has not been connected with the product yet?).
To avoid this ambiguity, you can add some annotation in documentation. But you can just prepare http://example.com/api/v1.0/product_groups and all is clear.
If you are developing Rest API for your clients than you should not rely on id's. Instead build a meaningful abbreviation and map them to actual id on server side.
If that is not possible, instead of using
http://example.com/api/v1.0/products/3 you can use http://example.com/api/v1.0/products?product_id=3 and then you can provide "product_id" description in the documentation. basically telling the client ways to use product_id.
In short a url must be meaningful and follow a pattern.The variable part must be send by in the url query(part after ? or POST payload)
With this, method to querying the server is also important. If client is trying to get something to the server he should use "GET" http request, similar POST http request if it is uploading new info and "PUT" request if it is updating or creating a new resource.
So by this analogy http://example.com/api/v1.0/products/groups is more appropriate as it is following a pattern(groups in product) while productgroups is more like a keyword with no pattern.
A directory like pattern is more easier to understand. Like in file systems(C:\Program Files\WinRAR), every part gets us to more generalized target.
You can also customize this for specific group- http://example.com/api/v1.0/products/groups?id=3
I have REST API that exposes a complex large resource and I want to be able to clone this resource. Assume that the resource is exposed at /resources/{resoureId}
To clone resource 10 I could do something like.
GET /resources/10
POST /resources/ body of put containing a duplicate of the representation by GET /resources/10 without the id so that the POST creates a new resource.
The problem with this approach is that the resource is very large and complex it really makes no sense to return a full representation to the client and then have the client send it back as that would be just a total waste of bandwidth, and cpu on the server. Cloning the resource on the server is so much easier so I want to do that.
I could do something like POST /resources/10/clone or POST resources/clone/10 but both of these approaches feel wrong because the verb in the URL.
What is the most "restful/nouny" way to build url that can be used in this type of situation?
Since there is no copy or clone method in HTTP, it's really up to you what you want to do. In this case a POST seems perfectly reasonable, but other standards have taken different approaches:
WebDAV added a COPY method.
Amazon S3 uses PUT with no body and a special x-amz-copy-source header. They call this a PUT Object - Copy.
Both of these approaches assume that you know the destination URI. Your example seems to lack a known destination uri, so you pretty much must use POST. You can't use PUT or COPY because your creation operation is not idempotent.
If your service defines POST /resources as "create a new resource", then why not simply define another way to specify the resource other than as the body of the POST? E.g. POST /resources?source=/resources/10 with an empty body.
Francis' answer is a great one and probably what you're looking for. With that said, it's not technically RESTful since (as he says in the comments) it does rely on the client providing out of band information. Since the question was "what is the restful way" and not "what is a good way/the best way", that got me thinking about whether there is a RESTful solution. And I think what follows is a RESTful solution, although I'm not sure that it's necessarily any better in practice.
Firstly, as you've already identified, GET followed by POST is the simple and obvious RESTful way, but it's not efficient. So we're looking for an optimization, and we shouldn't be too surprised if it feels a little less natural than that solution!
The POST + sourceId solution creates a special URL - one that points not to a resource, but to an instruction to do something. Any time you find yourself creating special URLs like that, it's worth considering whether you can work around the need to do that by simply defining more resources.
We want the ability to copy
resources/10
What if we come up with another resource:
resources/10/copies
...and the definition of this resource is simply "the collection of resources that are copies of resource/10".
With this resource defined, we can now re-state our copy operation in different terms - instead of saying "I want the server to copy resources/10", we can say "I want to add a new thing to the collection of things that are copies of resources/10".
This sounds strange, but it fits naturally into REST semantics. For instance, let's say this resource currently looks like this (I'm going to use a JSON representation here):
[]
We can just update that with a POST or PATCH [1]:
POST resources/copies/10
["resources/11"]
Note that all we're sending to the server is metadata about a collection, so it's very efficient. We can assume that the server now knows where to get the data to copy, since that's part of the definition of this resource. We can also assume that the client knows that this results in a new resource being created at "resources/11" for the same reason.
With this solution, everything is defined clearly as a resource, and everything has one canonical URL, and no out-of-band information is ever required by the client.
Ultimately, is it worth going with this strange-feeling solution just for the sake of being more RESTful? That probably depends on your individual project. But it's always interesting to try and frame the problem differently by creating different resources!
[1] I don't know if makes sense to allow GET on "resources/10/copies". Obviously as soon as either the original resource or a copy of it change, the copy isn't really a copy any more and shouldn't be in this collection. Implementation-wise, I don't see the point in burdening the server with keeping track of that, so I think this should be treated as an update-only resource.
I think POST /resources/{id} would be a good solution to copy a resource.
Why?
POST /resources is the default REST-Standard to CREATE a new resource
POST /resources/{id} should not be possible in most REST apis, because that id already exists - you will never generate a new resource with you (the client) defining the id. The server will define the id.
Also note that you will never copy resource A on resource B. So if you want to copy existing resource with id=10, some answers suggest this kind of thing:
POST /resources?sourceId=10
POST /resources?copyid=10
but this is simpler:
POST /resources/10
which creates a copy of 10 - you have to retrieve 10 from storage, so if you don't find it, you cannot copy it = throw a 404 Not Found.
If it does exist, you create a copy of it.
So using this idea, you can see it does not make sense to do the following, copying some b resource to some a resource:
POST /resources?source=/resources/10
POST /resources-a?source=/resources-b/10
So why not simply use POST /resources/{id}
It will CREATE a new resource
The copy parent is defined by the {id}
The copy will be only on the same resource
It's the most REST-like variant
What do you think about this?
You want to create a copy of a specific resource. My Approach in that case, would be to use the following endpoint :
POST /resources/{id}/copy, read it "create a copy of resource {id}"
Will just put it out there, if this can be of help to anyone.
We had a similar scenario, where we were providing "clone vm" as a feature for scaling out on our IaaS offering. So if a user wanted to scale out they would have to hit POST: /vms/vm101 endpoint with request_body being
{"action": "clone", // Specifies action to take, since our users can do couple of other actions on a vm, like power_off/power_on etc.
"body": {"name": [vm102, vm103, vm104] // Number of clones to make
"storage": 50, ... // Optional parameters for specifying differences in specs one would want from the base virtual machine
}
and 3 clones of vm101 viz. vm102, vm103 and vm104 would be spinned.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
I'm currently designing and implementing a RESTful API in PHP. However, I have been unsuccessful implementing my initial design.
GET /users # list of users
GET /user/1 # get user with id 1
POST /user # create new user
PUT /user/1 # modify user with id 1
DELETE /user/1 # delete user with id 1
So far pretty standard, right?
My problem is with the first one GET /users. I was considering sending parameters in the request body to filter the list. This is because I want to be able to specify complex filters without getting a super long url, like:
GET /users?parameter1=value1¶meter2=value2¶meter3=value3¶meter4=value4
Instead I wanted to have something like:
GET /users
# Request body:
{
"parameter1": "value1",
"parameter2": "value2",
"parameter3": "value3",
"parameter4": "value4"
}
which is much more readable and gives you great possibilities to set complex filters.
Anyway, file_get_contents('php://input') didn't return the request body for GET requests. I also tried http_get_request_body(), but the shared hosting that I'm using doesn't have pecl_http. Not sure it would have helped anyway.
I found this question and realized that GET probably isn't supposed to have a request body. It was a bit inconclusive, but they advised against it.
So now I'm not sure what to do. How do you design a RESTful search/filtering function?
I suppose I could use POST, but that doesn't seem very RESTful.
The best way to implement a RESTful search is to consider the search itself to be a resource. Then you can use the POST verb because you are creating a search. You do not have to literally create something in a database in order to use a POST.
For example:
Accept: application/json
Content-Type: application/json
POST http://example.com/people/searches
{
"terms": {
"ssn": "123456789"
},
"order": { ... },
...
}
You are creating a search from the user's standpoint. The implementation details of this are irrelevant. Some RESTful APIs may not even need persistence. That is an implementation detail.
If you use the request body in a GET request, you're breaking the REST principle, because your GET request won't be able to be cached, because cache system uses only the URL.
What's worse, your URL can't be bookmarked, because the URL doesn't contain all the information needed to redirect the user to this page.
Use URL or Query parameters instead of request body parameters, e.g.:
/myapp?var1=xxxx&var2=xxxx
/myapp;var1=xxxx/resource;var2=xxxx
In fact, the HTTP RFC 7231 says that:
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
For more information take a look here.
It seems that resource filtering/searching can be implemented in a RESTful way. The idea is to introduce a new endpoint called /filters/ or /api/filters/.
Using this endpoint filter can be considered as a resource and hence created via POST method. This way - of course - body can be used to carry all the parameters as well as complex search/filter structures can be created.
After creating such filter there are two possibilities to get the search/filter result.
A new resource with unique ID will be returned along with 201 Created status code. Then using this ID a GET request can be made to /api/users/ like:
GET /api/users/?filterId=1234-abcd
After new filter is created via POST it won't reply with 201 Created but at once with 303 SeeOther along with Location header pointing to /api/users/?filterId=1234-abcd. This redirect will be automatically handled via underlying library.
In both scenarios two requests need to be made to get the filtered results - this may be considered as a drawback, especially for mobile applications. For mobile applications I'd use single POST call to /api/users/filter/.
How to keep created filters?
They can be stored in DB and used later on. They can also be stored in some temporary storage e.g. redis and have some TTL after which they will expire and will be removed.
What are the advantages of this idea?
Filters, filtered results are cacheable and can be even bookmarked.
I think you should go with request parameters but only as long as there isn't an appropriate HTTP header to accomplish what you want to do. The HTTP specification does not explicitly say, that GET can not have a body. However this paper states:
By convention, when GET method is
used, all information required to
identify the resource is encoded in
the URI. There is no convention in
HTTP/1.1 for a safe interaction (e.g.,
retrieval) where the client supplies
data to the server in an HTTP entity
body rather than in the query part of
a URI. This means that for safe
operations, URIs may be long.
As I'm using a laravel/php backend I tend to go with something like this:
/resource?filters[status_id]=1&filters[city]=Sydney&page=2&include=relatedResource
PHP automatically turns [] params into an array, so in this example I'll end up with a $filter variable that holds an array/object of filters, along with a page and any related resources I want eager loaded.
If you use another language, this might still be a good convention and you can create a parser to convert [] to an array.
FYI: I know this is a bit late but for anyone who is interested.
Depends on how RESTful you want to be, you will have to implement your own filtering strategies as the HTTP spec is not very clear on this. I'd like to suggest url-encoding all the filter parameters e.g.
GET api/users?filter=param1%3Dvalue1%26param2%3Dvalue2
I know it's ugly but I think it's the most RESTful way to do it and should be easy to parse on the server side :)
Don't fret too much if your initial API is fully RESTful or not (specially when you are just in the alpha stages). Get the back-end plumbing to work first. You can always do some sort of URL transformation/re-writing to map things out, refining iteratively until you get something stable enough for widespread testing ("beta").
You can define URIs whose parameters are encoded by position and convention on the URIs themselves, prefixed by a path you know you'll always map to something. I don't know PHP, but I would assume that such a facility exists (as it exists in other languages with web frameworks):
.ie. Do a "user" type of search with param[i]=value[i] for i=1..4 on store #1 (with value1,value2,value3,... as a shorthand for URI query parameters):
1) GET /store1/search/user/value1,value2,value3,value4
or
2) GET /store1/search/user,value1,value2,value3,value4
or as follows (though I would not recommend it, more on that later)
3) GET /search/store1,user,value1,value2,value3,value4
With option 1, you map all URIs prefixed with /store1/search/user to the search handler (or whichever the PHP designation) defaulting to do searches for resources under store1 (equivalent to /search?location=store1&type=user.
By convention documented and enforced by the API, parameters values 1 through 4 are separated by commas and presented in that order.
Option 2 adds the search type (in this case user) as positional parameter #1. Either option is just a cosmetic choice.
Option 3 is also possible, but I don't think I would like it. I think the ability of search within certain resources should be presented in the URI itself preceding the search itself (as if indicating clearly in the URI that the search is specific within the resource.)
The advantage of this over passing parameters on the URI is that the search is part of the URI (thus treating a search as a resource, a resource whose contents can - and will - change over time.) The disadvantage is that parameter order is mandatory.
Once you do something like this, you can use GET, and it would be a read-only resource (since you can't POST or PUT to it - it gets updated when it's GET'ed). It would also be a resource that only comes to exist when it is invoked.
One could also add more semantics to it by caching the results for a period of time or with a DELETE causing the cache to be deleted. This, however, might run counter to what people typically use DELETE for (and because people typically control caching with caching headers.)
How you go about it would be a design decision, but this would be the way I'd go about. It is not perfect, and I'm sure there will be cases where doing this is not the best thing to do (specially for very complex search criteria).
I'm building a collection of RESTful resources that work like the following: (I'll use "people" as an example):
GET /people/{key}
- returns a person object (JSON)
GET /people?first_name=Bob
- returns a list of person objects who's "first_name" is "Bob" (JSON)
PUT /people/{key}
- expects a person object in the payload (JSON), updates the person in the
datastore with the {key} found in the URL parameter to match the payload.
If it is a new object, the client specifies the key of the new object.
I feel pretty comfortable with the design so far (although any input/criticism is welcome).
I'd also like to be able to PUT a list of people, however I'm not confident in the RESTfulness of my design. This is what I have in mind:
PUT /people
- expects a list of objects in JSON form with keys included in the object
("key":"32948"). Updates all of the corresponding objects in the datastore.
This operation will be idempotent, so I'd like to use "PUT". However its breaking a rule because a GET request to this same resource will not return the equivalent of what the client just PUT, but would rather return all "people" objects (since there would be no filters on the query). I suspect there are also a few other rules that might be being broken here.
Someone mentioned the use of a "PATCH" request in an earlier question that I had: REST resource with a List property
"PATCH" sounds fantastic, but I don't want to use it because its not in wide use yet and is not compatible with a lot of programs and APIs yet.
I'd prefer not to use POST because POST implies that the request is not idempotent.
Does anyone have any comments / suggestions?
Follow-up:::
While I hesitated to use POST because it seems to be the least-common-denominator, catch-all for RESTful operations and more can be said about this operation (specifically that it is idempotent), PUT cannot be used because its requirements are too narrow. Specifically: the resource is not being completely re-written and the equivalent resource is not being sent back from a GET request to the same resource. Using a PUT with properties outside of it's specifications can cause problems when applications, api's, and/or programmers attempt to work with the resource and are met with unexpected behavior from the resource.
In addition to the accepted answer, Darrel Miller had an excellent suggestion if the operation absolutely had to be a PUT and that was to append a UUID onto the end of the resource path so an equivalent GET request will return the equivalent resource.
POST indicates a generic action other than GET, PUT, and DELETE (the generic hashtable actions). Because the generic hashtable actions are inappropriate, use POST. The semantics of POST are determined by the resource to which an entity is POSTed. This is unlike the semantics of the generic hashtable methods, which are well-known.
POST /people/add-many HTTP/1.1
Host: example.com
Content-Type: application/json
[
{ "name": "Bob" },
{ "name": "Robert" }
]
Using PUT is definitely the wrong verb in this case. POST is meant to do exactly what you are asking. From the HTTP specification:
The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource...
As such, if you want to update multiple resources in a single call, you have to use POST.
Just be cause PUT is required to be idempotent and POST is not, does not mean that POST cannot be idempotent. Your choice of HTTP verb should not be based on that, but based on the relationship of the requested resource and the resource acted upon. If your application is directly handling the resource requested, use PUT. If it is acting on some other resource (or resources, as in your case), use POST.
I really don't see any easy way you could use PUT to create an arbitrary set of people. Unless, you are prepared to have the client generate a GUID and do something like,
PUT /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
On the server side you could take the people from the list and add them to the /People resource.
A slight variation to this approach would be to get the server to include a link such as
<link rel="AddList" href="/PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}"/>
in the People resource. The client would need to know that it needs to PUT a list of people to the AddList link. The server would need to make sure that each time it renders the /People resource it creates a new url for the AddList link.
Regarding Darren Miller's suggestion of using PUT to a GUID (I can't comment...), the point of using PUT would be to achieve idempotency for the operation. The litmus test if idempotency would be this conversation between the client and server:
PUT /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
204 NO CONTENT (indicates that it all went well)
client loses connection and doesn't see the 204
client automatically retries
PUT /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
How would the server differentiate the two? If the GUID is "used up" so to speak then the server would have to respond 404 or 410. This introduces a tiny bit of conversational state on the server to remember all the GUIDs that have been used.
Two clients would often see the same I guess, because of caching or simply keeping stale responses around.
I think a smart solution is to use POST to create an (initially empty, short lived) holding area for a resource to which you can PUT, i.e. clients need to POST to create the GUID resource instead of discovering it via a link:
POST /PeopleList/CreateHoldingArea
201 CREATED and Location: /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
PUT /PeopleList/{1E8157D6-3BDC-43b7-817D-C3DA285DD606}
This would mean that the lost idempotency would not result in much overhead; clients simply create new GUIDs (by POSTing) if they didn't see the initial 201 CREATED response. The "tiny bit of conversational state" would now only be the created but not yet used holding areas.
The ideal solution would of course not require any conversational state on the server, but it eludes me.