API Best Practices: Response Handling

January 30 2015

2 comments 0

Part five of the API design best practices . Read part one: Plan Your API.

Provide Helpful Responses

Building a solid foundation to ensure the scalability and longevity of your API is crucial, but just as crucial is ensuring that developers can understand your API, and trust it to respond with the appropriate header codes and error messages.

In this week’s API best practices, we’re going to cover how to ensure that developers understand exactly what happened with their API call by using the appropriate HTTP Status Codes (something that is often times missed), as well as by returning descriptive error messages on failure.

Use HTTP Status Codes

One of the most commonly misused HTTP Status Codes is 200 – ok or the request was successful.  Surprisingly, you’ll find that a lot of APIs use 200 when creating an object (status code 201), or even when the response fails:


In the above case, if the developer is solely relying on the status code to see if the request was successful, the program will continue on not realizing that the request failed, and that it did something wrong.  This is especially important if there are dependencies within the program on that record existing.  Instead, the correct status code to use would have been 400 to indicate a “Bad Request.”

By using the correct status codes, developers can quickly see what is happening with the application and do a “quick check” for errors without having to rely on the body’s response.

You can find a full list of status codes in the HTTP/1.1 RFC, but just for a quick reference, here are some of the most commonly used Status Codes for RESTful APIs:

200 Ok
201 Created
304 Not Modified
400 Bad Request
401 Not Authorized
403 Forbidden
404 Page/ Resource Not Found
405 Method Not Allowed
415 Unsupported Media Type
500 Internal Server Error

Of course, if you feel like being really creative, you can always take advantage of status code:

418 I’m a Teapot

It’s important to note that Twitter’s famed 420 status code – Enhance Your Calm, is not really a standardized response, and you should probably just stick to status code 429 for too many requests instead.

Use Descriptive Error Messages

Again, status codes help developers quickly identify the result of their call, allowing for quick success and failure checks.  But in the event of a failure, it’s also important to make sure the developer understands WHY the call failed.  This is especially crucial to the initial integration of your API (remember, the easier your API is to integrate, the more likely people are to use it), as well as general maintenance when bugs or other issues come up.

You’ll want your error body to be well formed, and descriptive.  This means telling the developer what happened, why it happened, and most importantly – how to fix it.  You should avoid using generic or non-descriptive error messages such as:

redx   Your request could not be completed
redx   An error occurred
redx   Invalid request

Generic error messages are one of the biggest hinderances to API integration as developers may struggle for hours trying to figure out why the call is failing, even misinterpreting the intent of the error message altogether. And eventually, if they can’t figure it out, they may stop trying altogether.

For example, I struggled for about 30 minutes with one API trying to figure out why I was getting a “This call is not allowed” error response. After repeatedly reformatting my request and trying different approaches, I finally called support (in an extremely frustrated mood) only to find out it was referring to my access token, which just so happened to be one letter off due to my inability to copy and paste such things.

Just the same, an “Invalid Access Token” response would have saved me a ton of hassle, and from feeling like a complete idiot while on the line with support.  It would have also saved them valuable time working on real bugs, instead of trying to troubleshoot the most basic of steps (btw – whenever I get an error the key and token are the first things I check now).

Here are some more examples of descriptive error messages:

greencheckmark   Your API Key is Invalid, Generate a Valid API Key at http://…
greencheckmark   A User ID is required for this action. Read more at http://…
greencheckmark   Your JSON was not properly formed. See example JSON here: http://…

But you can go even further, remember- you’ll want to tell the developer what happened, why it happened, and how to fix it.  One of the best ways to do that is by responding with a standardized error format that returns a code (for support reference), the description of what happened, and a link to the appropriate documentation so that they can learn more/ fix it:

On a support and development side, by doing this you can also track the hits to these pages to see what areas tend to be more troublesome for your users – allowing you to provide even better documentation/ build a better API.

Building an SDK Doesn’t Fix Everything

Last but not least, keep in mind that SDKs or code wrappers/ libraries can be extremely helpful.  However, if you are building a full out SDK instead of a language wrapper that utilizes the hypermedia to handle responses, remember that you are adding a whole new layer of complexity to your API ecosystem – that you will have to maintain.

What SDKs/ Code Wrappers offer is a quick, plug and play way for developers to incorporate your API, while also (hopefully) handling error checks/ responses.  The downside is the more complex your SDK becomes, the more tightly coupled it usually is to your API, making any updates to your API a manual and complex process.  This means that any new features you roll out will receive rather slow adoption, and you may find yourself providing support to your developers on why they can’t do something with your SDK.

When building your SDK you should try to keep it as decoupled from your API as possible, relying on dynamic responses and calls while also following the best coding practices for that language (be sure to watch Keith Casey’s SPOIL talk or read about it here).

Another option is to utilize a SDK building service such as APIMatic.io or REST United, which automatically generates SDKs for your API based on your RAML, Swagger, or API Blueprint spec.  This allows you to offer SDKs, automatically have them update when adding new features (although clients will still need to download the updated version), and offer them without adding any additional workload on your end.

But again, regardless of whether or not you provide an SDK/ Code Library, you will still want to have multiple code examples in your documentation to help developers who want to utilize your API to its fullest capacity, without relying on additional third party libraries to do so.

To recap, use HTTP Status Codes, use Descriptive Error Messages, and having an SDK may be helpful for a lot of your developers – but make sure you take into consideration all of the challenges that come with it, and remember that having an SDK doesn’t replace documentation, if anything – it creates the need for more.

Go to Part 6: API Management →

  • User Authentification, Provisioning, & Throttling
  • The Advantages of using a Proxy for API Management


We'd love to hear your opinion on this post

2 Responses to “API Best Practices: Response Handling”

  1. Hi Mike,
    One thing to be a little be cautious with is not to make the errors useful for hackers trying to get in – for instance you could return specific security related errors such as:

    “user name not found”
    “password incorrect”
    “too many incorrect logins account locked”

    Or as you gave the example: “API key invalid.” But that helps with narrowing things down for a security breach. For instance: if you have errors confirming whether or not the username is correct and then if the username is correct it’ll warn if the password is incorrect – then someone can tell if they have a correct username and go from there.

    So for security related information: usernames/passwords/API keys – I would err on the side of being vague rather than specific for anything that has sensitive information.
    For non-security related errors: absolutely, being specific is absolutely a good idea, but I would be deliberately vague.

  2. Oh, and one other thing I’d throw in is avoid being specific about disclosing any back-end IP or other information. Although it might be good to know that database myPRODserver1234 timed out – that’s another red flag/fail for the API/Service security reviews I’ve been involved with in financial institutions. If you’re using an API gateway layer it kinda blows a hole through that layer of protection even if you do have things segregated off behind firewalls and the like – it’s just best to keep internal stuff away from prying eyes.