418: I'm a teapot, and other bad API responses - RESTful API Design

By Josh Wyse in Developer Posted Apr 9, 2015

RESTFUL API DESIGN: PART II

At Cloud Elements, we integrate with a LOT of APIs. While doing so, we’ve developed some pretty strong opinions on how API responses should look.

Need to brush up on what we covered in our first post? Check it out:

RESTful API Design

10 Step Guide to API Integrations

JSON

Use JSON…please. I would even argue that you don’t need to support anything other than JSON. I understand there may be exceptions to this rule, but JSON is greater than XML and if you disagree with that, you can just get out.

CONSISTENCY

Be consistent with everything. Use camelCase or snake_case, but whatever you do – use it everywhere. Be consistent with HTTP status codes. I’m fine if you just return a 200 and not a 201202 etc., but keep that standard across all of your APIs.

NO WRAPPER OBJECTS

This is an extremely common practice, but it seems unnecessary and redundant. When calling a RESTful API, such as
GET /contacts/{id}you know the resource to be returned is a contact Don’t pollute that resource with data that doesn’t belong to the contact resource and add an envelope.

No:

{ "contact": { "id": 1, "name": "Frank Ricard" } }

No:

{ "data": { "id": 1, "name": "Frank Ricard" } }

Yes:

{ "id": 1, "name": "Frank Ricard" }

METADATA IN THE HEADERS

Please don’t include metadata in the response body. Let’s build off of one of the contact responses from above as an example:

{ "data": { "id": 1, "name": "Frank Ricard" }, "metadata": { "status": 200, "success": true, "nextPageToken": "1af231ji" } }

The contact resource does not contain a metadata object, so once again, don’t pollute the resource. Instead, put this metadata where it goes, in the HTTP response headers. Allow the actual response body to be the resource you’re manipulating. GitHub’s APIdoes this very well.

Return the proper HTTP status codes
See bold print one line above.

ERROR RESPONSES

I’m really just all about consistency and conventions here. As mentioned above, allow the client to rely on the HTTP status code to determine if it’s an error, and then supply as much detail as you can as to what went wrong. I think supplying some type of requestId is a great idea as well, as it makes it easy for support to immediately identify what went wrong. I’ve always thought the Box API did a really great job with their error responses.

EXCEPTIONS TO THE RULES

I do understand that there are some client libraries that do not allow you to get a handle to the HTTP response headers. I also understand that an API may need to support cross domain requests over JSONP. In either of these situations, I understand that some of the rules above may need to be broken. I think Vinay’s recommendation of supporting the ?envelope=true query parameter is a great idea, but may not be something you need your API to support right away.

Check out the next post in the series to learn about error handling in API design:

References - Some other technical resources that provide some great insight and helped us at Cloud Elements:

Read other developer blogs:

If you're planning on integrating your API with APIs of other cloud services, check out this free eBook that gives you everything you need to know: