There are many articles floating around the internet right now about defining RESTful API standards. I’m guessing this is because Ruby on Rails makes it so easy to build an API that everyone and their mom has started building one. These articles talk about the RFC on HTTP and how REST should fit in. They outline how current implementations are “broken” and want to come up with certain “standards” for governing how a RESTful API should work. These articles make all sorts of claims about how the return type of the data should only be set in the request headers, how the obscure “PATCH” HTTP method should be used, and how doing XYZ does not follow HATEOAS. The problem with these discussions is they propose solutions that are more academic than useful.
I have a response to all of this - ENHANCE YOUR CALM!
Let’s take a step back and think: What is the real purpose of creating an API? The “real purpose” is to increase your user base by making it easy for developers to plug into your system. How does an API accomplish this? By making it simple for developers to integrate with your systems and build awesome applications on top of your systems through all of the functionality you provide. If you make people jump through too many hoops to use your API, they might just not use it – and you get zero new users from that. As a developer who has been building and consuming APIs for several years now, I have found the following rules to be practically (not just theoretically) useful for both the development and consumption of an API:
1. Use GET, POST, PUT, and DELETE to separate out actions. GET should be used to retrieve objects. It should never be used to update an object. There are many reasons for this, but my favorite is you don’t want someone accidentally clicking a hyperlink and screwing up their data set. POST should be for creating objects. Be it parent or child objects – if you are creating an object of sorts, use POST. PUT should be for updating. PUT is when you have an exact URL that you could also use for GETting that object. I know some argue that you can use PUT to create. For example, you could PUT a new item to /pants/12345 which would create a new pants object with id 12345. But honestly, why would your users be creating an object with an id? DELETE deletes an object. I shouldn’t have to explain why.
2. PUT can be used to do partial updates. I know the REST police might say that you have to pass in the entire object each time you do an update, but that can be expensive. Sometimes you have many child objects, while other times an object might just be beefy and sending the whole thing through would be expensive. Why make a slower experience just to adhere so directly to the rules?
3. Add meta data to your responses. This probably breaks HATEOAS or some REST principle in that you expect the object and only the object in your response, but come on. Don’t you want your users to have easy access to errors, error codes, error messages, etc.? Sure you can pass that information in the header somehow, but I’ve seen clients who cannot figure out how to use the header responses correctly. It’s so easy to parse a JSON response. Why make it harder for your users?
4. Return a status and the object on POST and PUT calls. This might violate the tenants of REST, but users need to know when their calls work. Returning the object saves them from having to send a GET call on their end and you from having to handle their separate GET call. This is especially helpful in mobile app development. Who wants a slow mobile app?
5. Return the object type on a GET. By this I mean have your JSON for the banana service look something like ‘….”banana” : {“field1” : 13….}’ Sometimes users like to write generic parsers and it is easier if they can tell which object they are getting back from the response itself.
I’ll leave it here for now. Check in later this week for principles 6 through 11.