RESTful Applications – Managing Cross Resource Operations

apirestweb-applications

I have an RESTful api that allows my users to receive enquiries about their business e.g. 'I would like to book service x on date y. Is this available?'. The api saves this information as a resource to the following URI

users/{userId}/enquiries/{enquiryId}

The information shown when this resource is retrieved are the standard sort of things you'd expect from an enquiry – email, first_name, last_name, address, message

The api also allows customers to be created for a user. The customer has a login and password and also a profile. The following URIs expose these two resources

PUT users/{userId}/customers/{customerId}
PUT users/{userId}/customers/{customerId}/profile

The problem I am having is that I would like to have the ability to allow users to create a customer from an enquiry. For example, the user is able to offer their service on the date requested and will then want to setup a customer with login details etc to allow them to manage the rest of the process.

The obvious answer would be to use a URI like

 users/{userId}/enquiries/{enquiryId}/convert-to-client

The problem with this is is that it somewhat goes against a lot of what I've been reading about how to implement REST (specifically from the book Restful Web Services which suggests that URIs should point to resources not operations on resources).

The other option would be to get the client application (i.e. the code that calls the api) to handle some of this application logic. This doesn't quite feel right to me. I have implemented in my design that the client app is fairly dumb. It knows just enough to display the results from the API, and does not contain any application logic.

Would be great to hear what others views are on the best way of setting this up

Am I wrong to have no application logic in the client app? How would I perform this operation purely in the REST api?

Best Answer

I highly recommend reading RESTful Webservices, especially the chapters on the difference between RESTful and RPC style web programming; and the chapters on resource discovery and how to deal with the apparent need for "verbs" (they are usually a different resource in disguise).

Converting an enquiry to a customer does not need a "convert" verb. You wouldn't delete the enquiry just because you create a customer and thus you are simply creating a customer with the information from the enquiry as input.

POST /users/{userId}/customers?enquiry={EnguiryId}

or simply

POST /users/{userId}/customers

with the enquiry information in the request body.

By the way, I use POST on customers because that is the way to do it if the server application is in control of the identifier generation. Only use PUT to create resources if the caller is the one determining the identifiers.

On a side note: have you considered the security and privacy issues relating to including /users/{UserId} in your URI's? Anybody can now start trying different userid's to get at information of different users of your application. You really should consider leaving them off your URI's and having them determined by the authentication information that should be send with each request (and possibly refreshed with each response).