Not much has been written about API design from user experience standpoint in the public forums, and whatever has been written doesn’t go beyond reiterating coding best practices.
I recently worked on couple of projects to define APIs at Google. In past, I have mostly worked on graphical user experience or internal APIs. It took some effort to understand the subtleties and uniqueness involved in defining external APIs.
I’m sure much remain to be discovered and learnt. But I did notice three aspects that stand in stark contrast to GUI design. In this blog, I will talk about three principles:
1. Opinionated onboarding experience
In contrast to Graphical interface users who interact with the interface regularly, API users prefer “write-and-forget” APIs. They will most likely revisit the code only if it breaks, which should be avoided at all costs. Therefore, unlike GUI, APIs have to be designed for non-repeat interactions.
That’s why, in general, a better experience in API requires stricter design in contrast to the GUI.
GUI experience is geared towards providing simple onboarding experience. It’s okay if users don’t learn the right way in the first session. Users can generally click and play with the interface and learn slowly. Idea is to give users more freedom to experiment with the product even if it’s a possibly flawed process. That’s why most of the popular consumer Apps – Facebook, Gmail, Maps, Uber, or Headspace will let you click anywhere or do anything with the product.
For API users, feedback should be given quicker. Rather than letting users continue with a possibly flawed process, we should fail imperfect API calls with a relevant error (fail-fast design). That way users can avoid writing code that breaks later.
2. Initiated by human but consumed by machines
One quirk of designing an API user experience is the duality of consumption. Initial onboarding has to be designed for humans who will write the code. However, subsequent consumption would be via a program running this code. The program just cares to keep running, and perhaps never break. The human who consumes initially, on the other hand, had a more complex set of requirements.
The onboarding happens either through the GUI or developer documentation. Some best practices here include:
- As quickly as possible the documentation should jump to code examples. Even the GUI experience should lean toward how code can be written to replicate the GUI behavior. For example, in the Google Cloud console, users get an option to generate a REST command for the action they just performed.
- Just mentioning APIs in CRUD format is okay, but a step further would be to illustrate code examples for critical user journeys. For example, if CUJ (critical user journey) is creating resource A, listing resources B, and updating resource C, the documentation should illustrate the corresponding API calls.
- When in doubt, lean toward simple user flow focussed on providing a good learning experience.
3. Preference to simple, orthogonal interactions
In GUI, it’s a good practice to abstract complex sets of working behind simple clicks. It’s okay for this click to result in multiple effects – creating a resource and deleting other resources. As long as it aligns with the mental model of the user, it’s okay to combine complex sets of action.
In contrast, a better-designed API results in just one effect (or action) and avoids side-effects. In other words, API users prefer orthogonally defined APIs. Calling an API should change just one thing without affecting others. If that’s the case, a relatively small set of primitive constructs can be combined in powerful ways by developers to suit their needs.
For example, if calling POST resource A doesn’t delete resource B, users can orchestrate the behavior of their choice by making two independent API calls.
In essence, two API calls to orthogonally defined APIs are better than one API call that results in a complex set of changes.