Making a Friendly API

Making a Friendly API

As developers and designers we put a lot of effort into making our apps enjoyable but we tend to forget about that when we ship our APIs. Maybe it's time for us to consider that people are actually using our APIs as well?

Sure, some of us are lucky enough to only use brilliant APIs. But you just wait until you have to work with something that makes you shiver when reading the docs. Imagine how nice it would be to make integrations if they were all made with a little bit of love instead?


💡 Why I'm writing about this

I'm currently working on an official release of Wobaka's API and I want the experience to be a delight. So I did a little thinking on what I do and don't appreciate in an API and decided to write it down to hopefully inspire others and my future self.

🙅‍♂️ Things that make APIs hard to use

Having worked with a fair number of API's while developing integrations the past years I've noticed some patterns that can make them unnecessary hard to use.

Format

Please, use JSON. It's 2020 and nobody wants to install libraries or write custom code just to parse your XML.

Bad error messages

Few things makes working with APIs worse than bad error messages. It's happened to me more than once that I've received a "Bad Request" response with no more explanation, just to later discover that they needed a slightly different "Content-Type" header. If the header is wrong, make a developers day better by mentioning it in the response.

Complex authentication

Stateless authentication is simple. Don't even try to use sessions or cookies for your API. It's horrible to work with. Use a token in the Authorization header.

Inconsistent naming

CamelCase, kebab-case or snake_case. It doesn't really matter, as long as you pick one and stick to it. Users can always make mappers to convert back and forth anyway, as long as you are consistent.

Inconsistent format

Use the same structure for the same kind of response. Are you returning a collection? Decide if a list or map is best, but stick to it for other collections to. Also, decide if you're going to use root keys like { user: { … } } or not. Don't mix!

Don't use page numbers

Limit and skip are two conceptually easy ways for humans to reason about lists. We skip X and we only want Y objects. They also mirror how most languages as well as SQL are dealing with lists. Pages and page numbering is an unnecessary abstraction that only creates confusion.

Make your black box slightly transparent

Talking to an API is like sending things into a black box. We have no idea what's happening on the server. However, we can make this a little bit better. For Wobaka's API I decided to reflect the parameters back to the user in the meta object. This way you can see how your parameters were interpreted by us. It looks like this:

# Query
?skip=10&limit=10&query=Foo&show-archived=false
# Response
{
  data: [...]
  meta: {
    paramters: {
      skip: 10,
      limit: 10,
      query: "Foo",
      show-archived: false
    }
  ...
  }
}

Sure it'll add a few bytes to your response but it can make debugging so much easier if things are going wrong.

Unless you have a good reason, optimize for usability instead of saving bytes.

Breaking changes

Don't make them. Increment the API version instead. /v1/v2/v3… is fine and it won't ruin someone's day.

🍻 Let's all be friendly

Remember that time when API mashups was a thing? It was pretty cool. Now, imagine if all API's were super nice to use. What a wonderful time we could have making beautiful things together 🎉.