API errors are first class citizens
It seems to me that error handling is an afterthought in far too many APIs. When designing an API, I implore you to design your error handling too! The way that your API presents an error is key to a good API; developers integrating with your API will judge you on it.
Just because it’s an error doesn’t mean that you can forget your HTTP. You need to be a great HTTP citizen with your error responses as well as with your successful responses. This means that you should:
- Provide the correct status code
- Honour the accept header
- Send the correct content-type
In HTTP there are two acceptable ranges of status code for an error response: 4xx or 5xx.
The 4xx range are for client side errors and the 5xx range are for server side. In general, a 4xx means that the client needs to do something before it tries again. Some like 401 and 403 are related to permissions while most are related to ensuring that the message is a good HTTP message. Use 400 for validation errors.
Nearly all the 5xx are infrastructure related, so in your code you are most likely to be returning a 500 or 503 if something goes wrong at your end. If it’s a 503, consider adding the Retry-After header so that your clients won’t hammer your sever.
An error response should honour the data format indicated in Accept header that was sent by the client. If the client says that it accepts XML, then don’t return an error in JSON or HTML! Similarly, ensure that you set the correct Content-Type header for your response! The client will use this in order to decode the error response.
Provide an error response. Your response should, at a minimum provide two pieces of information:
- Application specific error code
- Human readable message
The code is for the client application. It should never change and allows the client to perform different actions based on the specific error returned. An application error code is required because HTTP status codes are too granular and a client should never have to string match to work out what’s going on!
The human readable error message is for your client developers. You want to help them as much as you can so that you don’t get a support call! The message should provide information on what’s gone wrong and in an ideal world, information on how to fix it.
All codes and messages should also be documented in your API documentation.
If you use a standard media type for your error, then you save on documentation and your clients will be able to use a library to handle them. This is a win-win situation. If you’re using a media type which has error objects defined (e.g.JSON-API), then use that.
If not, use RFC7807: Problem Details for HTTP APIs. This defines both a JSON and XML format for error handling and there are libraries out there for most languages which will decode it for you.
In your documentation, encourage your clients to use an Accept header that includes all the media types you may return. e.g.:
Accept: application/hal+json, application/problem+json
It’s not hard to have great error responses; you just need to care. Poor error response cause developers to give up with an API and go elsewhere, so it’s a competitive advantage to get this right.
Developers integrating with your API will thank you.