I'm designing a REST interface and I'm puzzled by what should the insert/update/delete verb return (as content of the response). Consider an inteface for Invoice
entities, accessible at api/invoices
:
GET /api/invoices
returns a list of invoicesGET /api/invoices/123
returns the invoice with ID 123POST /api/invoices
adds a new invoice (ID generated on server)POST /api/invoices/123
updates invoice with ID 123DELETE /api/invoices/123
deletes invoice with ID 123
Its pretty obvious what the first two method should return, but how about the insert/update/delet ones? An obvious answer is that add
should return the newly created item (ie. exactly the same response as GET /api/invoices/id), update
should return the updated item (again, same as a GET) and delete
should probably return nothing (empty content). This all makes sense and is consitent.
But my problems start when considering items that are not so simple as an Invoice entity. For instance consider an add
request that not only adds the item, but actually needs to return some extra information about the add operation: the item was accepted (success), the item is a duplicate (success with info), the item was ignored (success with info, I won't eneter into details why), the item was rejected (failure). Also in my case there is extra information I want to return, like a 'response' info pre-set for the bucket into the newly added items falls. I considered placing all the extra information in the http headers as sort of out-of-band info (like extra status codes in the 200 range and even custom headers) but is a hack, and the 'response' part can be actualy larger than the item itself. So now I'm considering the add
verb to return a completely new type, an item that contains the add info (status, response, ID of the new item, perhpas the entire new item). It certainly gets the job done, but I miss the nice symmetry I had before.
Would this be a good practice (when adding an item of type 'foo' the return is of type 'bar') or is something I'll look back in 6 month and pull my hair because I let the cat out of the bag? If I stick with 'any access on foo returns foo, including add', then the client would have to make an extra call after the 'add' operation to retrieve the information it is really interested in (ie. the 'response').