Indicating Problems in HTTP APIs
Wednesday, 15 May 2013
A common part of HTTP-based APIs is telling the client that something has gone wrong. Most APIs do this in some fashion, whether they call it a “Fault” (very SOAP-y), “Error” or whatever.
Most of them define a new format for just this purpose; for examples, see Amazon’s, OpenStack’s, Twitter’s, Facebook’s, and SalesForce’s. Twitter’s is fairly representative:
{"errors":[{"message":"Sorry, that page does not exist","code":34}]}
Here, they associate a human-readable message and an error code with the error. That’s a good start, but how is it related to the HTTP status code? And, how am I supposed to know how to find that code?
Good HTTP APIs don’t make developers hunt through documentation to find things like this; self-documenting formats give is a way to communicate these kinds of details in a way that’s easy to find.
Good HTTP APIs also use media types to indicate the format of the content, for similar reasons; however, most of these don’t, and as a result developers and tools again need to understand that they’re working with a particular API, rather than just examining the message.
Of course, there’s a good reason these formats are so casually defined; doing it the “right” way can be onerous, with a trip through IANA and the media type review list. Who wants to bother - especially when you have enough market power to force your users to suck it up?
I think we can do better. Clients shouldn’t have to pick through 30 slightly different formats and implement parsers specific to each one; it’s a waste of energy. People creating APIs shouldn’t have to guess what a good format looks like, only running into problems down the road. And they certainly shouldn’t have to register new media types for “Fault” formats of every API they create.
So, a while back I decided to come up with a generic format for indicating the details of a problem encountered in using an HTTP-based API. The current draft has an example:
HTTP/1.1 403 Forbidden
Content-Type: application/api-problem+json
Content-Language: en
{
"problemType": "http://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"problemInstance": "http://example.net/account/12345/msgs/abc",
"balance": 30,
"accounts": ["http://example.net/account/12345",
"http://example.net/account/67890"]
}
Notice that there’s a firm association between the problem type and the HTTP status code it’s conveyed within; that the problem type is identified with a URL, allowing folks to look it up, reference it unambiguously, and even reuse it in other APIs. Also, see how the format is extensible, so that you can convey machine-readable details of a problem. The optional “problemInstance” property even gives a unique identifier for this occurrence of the problem, to allow your support folks to figure out what’s going on.
Current APIs can introduce this format in a backwards-compatible fashion using content negotiation; if the client includes “Accept: application/api-problem+json” in the request, you know that they understand the format. Likewise, client tools can now abstract out problems into a common interface, rather than forcing developers to dig through the format.
There’s also a healthy dose of advice about how to use HTTP well (“RESTfully”, if you must), and Erik Wilde has also included an XML-based format whose canonical data model is the JSON, for those APIs that still choose to use XML.
To be clear - this isn’t going to solve world hunger, but I do think that APIs that choose to adopt it will avoid a few headaches, and their users will appreciate not having quite so many API-specific special cases to deal with. After all, the whole point of using HTTP for APIs is to get as much leverage as we can out of shared code and concepts.
Please have a read through the draft; lots of folks have reviewed it, and I think it’s nearly ready, but I’d still love any feedback you have. I’m going to be pushing for its use in IETF HTTP-based APIs, as well as others I come into contact with.
15 Comments
Matthew Kerwin ಠ_ಠ said:
Wednesday, May 15 2013 at 10:56 AM
Ruben Verborgh said:
Thursday, May 16 2013 at 3:19 AM
Larry Garfield said:
Thursday, May 16 2013 at 5:47 AM
Colin Taylor said:
Monday, May 20 2013 at 1:53 AM
Mark Nottingham said:
Monday, May 20 2013 at 4:34 AM
Leandro López said:
Thursday, May 23 2013 at 5:36 AM
aviflax.com said:
Friday, May 31 2013 at 12:32 PM
Mark Nottingham said:
Sunday, June 2 2013 at 3:58 AM
andreineculau.myopenid.com said:
Sunday, June 16 2013 at 9:23 AM
Mark Nottingham said:
Wednesday, June 19 2013 at 7:00 AM
aniket-patil.myopenid.com said:
Monday, June 24 2013 at 5:15 AM
Mark Nottingham said:
Tuesday, June 25 2013 at 12:17 PM
boxaniket.wordpress.com said:
Monday, July 22 2013 at 5:15 AM
Mark Nottingham said:
Tuesday, July 30 2013 at 5:20 AM
boxaniket.wordpress.com said:
Monday, August 5 2013 at 10:29 AM