Klipfolio Labs

Anatomy of a great API

A big part of our role as the Integrations team here at Klipfolio is to facilitate easy connections to services that our customers use on a regular basis. Because we deal with a wide variety of customers, we are exposed to all kinds of services and their APIs. We look at services ranging from as big and complex as Salesforce or Google Analytics to emerging services like Emma.

In the last few years we have seen a lot of different approaches to APIs and we want to share our experience with you. Over a series of blogs we plan to let you in on some of the awesome ways companies have tackled their APIs and some of the not so awesome ways.

At Klipfolio we know that we haven’t built our API perfectly yet and that we have a lot to improve on. Our goal is to include you in our journey of do’s and don’ts as we go. Over the series of the blog, our posts will vary in technical depth and level of detail. This post is intended to give a lay of the land and to explore some topics that we may (or may not) cover in more depth in future posts.

So, storytime. What have we seen that we love and don’t love so much?

Authentication

The starting point of connecting to any API is figuring out how to authenticate to the service. The best case scenario is when the service uses standard OAuth 2.0 as their method of authentication. We have seen a lot of variation in how OAuth is used and deviations from the standard. This sometimes makes it harder to integrate into our application.

Registration

There are even more variations in the registration processes for OAuth applications. Some services make the process convenient through an easily accessible development portal. Other services require a lengthy process of demos and detailed descriptions of your integration use case. As a third-party integrator it is really exciting when we find a service that allows us to create a test integration so that we can start our development in parallel with the app registration process. This gives us the flexibility to move quickly, especially if there is test data to play with.

One of the biggest joys we get is when we come across an API that is clear and consistent. Nerds, we know. What do we mean?

Provide clear documentation

Step one, it has documentation, check! Ideally, an API is well documented with sections that are easily navigable and have obvious labels. Finding crucial information should be intuitive. A good example of this is Mailchimp’s API. Their documentation is extensive and easy to navigate with sections describing authentication, rate limits, and best practices. They are very detailed about their query parameters and give good response examples for each endpoint. They also include error codes and a glossary. Bonus points go to services that have an API playground for users to test an endpoint in as they are consulting the reference docs.

Be consistent

As we start to work with the API comes step two, consistency in API request and response structure. A huge pain point for us is having to navigate through API documentation to decipher all the different behaviours of each endpoint.

You would think that a service that implements the ability to divide data into discrete pages would use a consistent request structure and parameters. After all, a user has to define the right parameters to be to able navigate through all the pages available. Unfortunately, services don’t always follow a consistent model, we’ve seen slight differences in the way pagination is implemented. For example:

Similarly, consistency across response structure for different endpoints in an API is important. It is much easier to consume APIs that have a predictable response. For example:

https://api.example.com/v1/users
{
  “user”: “Jane Smith”
  “e-mail”: “jsmith@acme.com”
  “date_created”: 1510094940
}
https://api.example.com/v1/campaigns
{
  “id”: “84ckhj9”
  “campaign”: “Fall Sale”
  “date_created”: “2017-07-01”
}

See what we mean? We would expect date_created to return the same date format for both responses. They are from the same API, right? Instead their different formats create confusion, make reusability of code more difficult, and reduce the chances of a successful implementation.

Use errors to educate

Step three is having helpful error codes. When something goes wrong, we want to know why and how to fix it. There’s nothing more confusing than mixed messages in an HTTP response. For example:

HTTP/1.1 200 OK
{
	“code”: “404”
  “message”: “Your account does not have the right API access”
}

The HTTP response header indicates that everything is OK, but the actual API response tells a different story. Why not just send the code in the response in the HTTP header? Similarly, there is this example:

HTTP/1.1 400 Bad Request
{
	“code”: “400”
  “message”: “Error”
}

We get it, there was probably something wrong with our query, but what is the point of showing an error message if it is not going to help us figure out what we did wrong? Services that have a special section in their API docs specifically for error messages get a special shout out!

Communicate updates

Finally, step four is proper communication and documentation around changes to the API. We all have a lot of things to keep track of when it comes to integrations so getting a friendly reminder when things are changing in a service is super helpful. The goal is always to be proactive rather than reactive so that nothing breaks on our customers or on us. Being notified well in advance and being able to reference a document or changelog that outlines the changes helps achieve those goals.

We know that we are not the only ones exploring or building APIs and have likely missed some things that are top of mind for you. We would love to hear what you are noticing too! Have you run into major pain points or an API that you absolutely love?

Share