Anyone that uses or develops APIs is familiar with REST. It is widely used and by some developers considered superior to other ways of doing APIs. Since REST was developed alongside the HTTP 1.1 spec, HTTP status codes are generally used for responses to REST calls.
To me, it seems that using the standard HTTP response codes (a nice list is given here) is overloading a standard server response with the response of a query. While the spec says that for client errors (400 series errors), the response should contain the reason why in the response. I’ve looked at a lot of APIs and the best ones at handling errors return the error response inside of a successful 200 HTTP response. For instance, if you are creating an API for dealing with support tickets and you ask for a ticket ID that doesn’t exist or you don’t have permission to access, returning a 400 series error generally tells the client that something bad has happened when, in fact, the error is kind of minor. Embedding the error in the response seems like a better way to go.
The problem, however, with embedding the error in the response is that the API developer has to come up with his own error codes and convey that to those that use the APIs. Many developers that implement APIs treat anything but a 200 series response as a complete failure and give up. So, the API developer has to make sure that the client implementors properly handle the responses. In general, I find it easier to have one set of parsing code and deal with the errors inside of a successful response.
My argument, of course, is not very compelling as it is simply to swap one way of handling responses and errors with another. Last night, however, I came up with a potential argument that leads credence to what I’m saying. If there is a proxy server or a load balancer in front of the server, it could potentially return an error code which the client may not expect. Let’s take the case where our support ticket server is behind a proxy server and the client requests a particular ticket. If the proxy server or load balancer is misconfigured and we make a request, the proxy server could return a 400 series error, even a 404 error. The client could interpret this as “the ticket doesn’t exist”. This may not be the case; the ticket could exist, but the proxy returned an error. A better way of handling this would be to use 200 series status codes when the request succeeds and embed the API error code inside of the response. If the proxy server returned a 400 series error, the client could always treat it as an error and wouldn’t have to figure out if the support ticket really existed or not.
In addition, the HTTP status codes are not granular enough for many APIs. This would require the API developer to have a secondary set of error codes that would be returned with the 400 series error codes anyway. If that is the case, why not just create one set of error codes and always return 200 series success codes unless something major has happened?
I know that some of this may be confusing (it is crystal clear in my head), but it is worth some thought to consider the best way to handle response codes in APIs. Many people have opinions on this and may think that I have no idea what I’m talking about and HTTP response codes are perfectly fine for RESTful APIs.