Don’t make me think!
API design is a huge topic these days and you find a lot of information about how to design good APIs. Unfortunately, most of it is about tools or technology: Use Tool X for great APIs! Use technology Y and everything will be fine!
Admittedly, we need good tooling to get our job done efficiently. And it is tempting! Let us just add an annotation to that class – et voilà: We have exposed an API. Now let us just put that vendor’s API gateway in front of it for dealing with the cross-cutting magic like authentication, rate limiting, etc. and we are done. The next 5 story points from the backlog easily burnt down. Let’s sprint on!
The problem is that technology is just a tiny part of creating a successful API. Creating a successful API mostly depends on meeting the needs and demands of its users – the developers who (shall) use it.
Let us call the degree to which an API meets the needs and demands of its users “API eXperience”, or short: AX 1. If this reminds you of UX (“User eXperience”): This association is intended. AX is UX, just for API users and not for UI users. In its core, it also aims at meeting the users' needs and expectations as good as possible.
The key to great AX is on the functional and organizational level, not on the technology or tool level. The users of your APIs usually have the same tooling you have. Thus, from a technical perspective, consuming your API is a no-brainer for them. But if your API is overly complicated, if it is inconsistent, if it is poorly documented or alike, they will reject it and look for a better alternative offering – probably the API your worst competitor offers.
All these things that make developers reject an API are not rooted in the tools or technology you use. They are rooted in the functional design of your API and the encompassing parts that complement its approachability. If the functional design sucks or the encompassing parts are missing (or suck, too), developers will reject your API and avoid it.
There are many things that add to good AX as well as there are anti-patterns that destroy it. I will discuss them over time in future posts. In this post, I discuss a first anti-pattern I call “concept spill”.
“Concept spill” can probably be explained best using an example from daily life: Imagine you want to attend an event in a different city, say a concert of your favorite artist. As the event will go deep into the night, you decide to stay overnight in a hotel. You also decide to go there by public transport because of your ecological conscience – well, also because you do not want to drive a car in a strange city and want to avoid the hassle at the venue.
You make your bookings. The day of the event arrives. You take the train. You arrive at the train station of the city where the event takes place. You are a bit late. You need to go to the hotel first, change clothes and continue to the event venue. You have the addresses of the hotel and the venue. You leave the train station and try to buy a ticket to continue to the hotel by public transport (subway, tram, bus or alike, depending on the city).
And that is where – at least in Germany where I live – the trouble starts: You go to the next ticket vending machine and it just shows several buttons with numbers or letters (again, depending on the city) on them. That’s it. Nothing else. Pressing some buttons, the machine displays different prices, some quite inexpensive, some really expensive. You do not know which button you need to press to get the right ticket. All you have is a hotel name and an address.
Now you need to sit down and learn all the concepts of the local transport association, how they organize their tariff area using rings, combs, zones, you name it, and how they map to the numbers or letters on the vending machine. You also need to figure out in which zone the train station is and in which zone the hotel is. You also might need to figure out where the venue is and if there are less expensive options available than single trip tickets (e.g., a 24h ticket or alike).
In short: You wanted to solve the problem to get to your hotel (on time) using public transport. But the local transport association first forced you to learn all their concepts, how they organized their tariff area, what tariffs they have, how to map them to your route, etc. to solve your actual problem.
You had one problem. Now you have two.
That is “concept spill”. It means that in order to use another service to solve your actual problem, you first need to understand its internal concepts.
Using a service that suffers from concept spill significantly increases the user’s intellectual load.
You need not only to understand the concepts that apply to solve your actual problem. You also need to understand the internal concepts of the service you use. Instead of making it easier for you to solve your problem, the service you want to use makes it harder for you.
Coming back to the example for one more time: If you would have been able just to enter the address of the hotel or – even better – just its name and then get the right ticket, then you immediately would have been able to proceed with your problem, which is arriving at the hotel in time and not to learn about the concepts of some transport association.
Such a user interface at the ticket vending machine would not have exposed internal concepts to the user. As a consequence, it would not have forced the users to understand the internal concepts before they can use the machine. The users can remain in the realm of their own problems – no additional intellectual load imposed.
And if the printed ticket additionally would have contained instructions which bus or tram to board and at which station to get off, it would have even reduced the intellectual load of your original problem a bit.
Avoiding concept spill
You see “ticket vending machines” like the one I described in the example all the time in IT: Internal concepts, directly exposed in the API, not caring a bit about the user’s needs and context. APIs that scream at you: “I do not care about your needs, problems or context! I am solely driven by the conceptual world of my creators. Thus, if you want to use me, understand their way of thinking first. Deal with it!”
To be fair: I think most often the originators of APIs that suffer from concept spill had nothing bad in mind. It just never came to their mind that their internal concepts are not obvious for their users or that the users do not want to learn about them (because they are already occupied with their own problems).
This raises the question: How can we avoid concept spill?
Avoiding concept spill is very simple and extremely hard at the same time: You need to understand what your users want from you, which questions they want to ask your service. You need to understand their contexts – at least the most important ones – in which they use your service. And you need to understand which problems they want to solve with your service in those contexts.
This drives the design of your API: The questions your users ask your service in order to solve their particular problem in their context. Thus:
API design always starts with your users, their context, their problems and their needs.
The questions they want to ask your service in their contexts shape the design of you API, not your internal concepts, data or implementation.
If you take this into account, if you are willing to go the extra mile to understand your users, their contexts, problems and needs, you are much more likely to come up with an API they love (i.e., great AX) than if you let your internal concepts let drive the design of your API.
Often I then get from the people creating the API that they cannot anticipate who will use their API and how it will be used. Sorry to be harsh, but that is just a lame excuse for not doing the required homework.
While you can be surprised by usages patterns you did not anticipate, with a bit of good will and effort it is always possible to understand the most common usage scenarios and base the API design on them. Additionally, you can use beta phases to validate your assumptions and adjust your API design if needed based on the feedback of your users.
In a world where APIs become more and more relevant, where more and more revenue streams flow through APIs, API eXperience (AX) becomes essential. AX is a lot about the additional intellectual load an API imposes on its users. Overly complicated, inconsistent, poorly documented or alike APIs offer a poor AX and very likely will be rejected by developers.
In this post we discussed one AX anti-pattern: Concept spill.
“Concept spill” is when you want to use an API, but before you can use it you first need to understand the internal concepts of the service that is exposed by the API. This means an increased intellectual load: You do not only need to deal with the problem you try to solve, but you also need to understand external concepts not related to your problem.
To avoid concept spill, you must design APIs from the point of view of their users, their contexts, problems and needs, not based on your internal concepts, data or implementation.
I hope this post gave you some brief hints toward creating great APIs that your users will love. In some future posts (not immediately following this one but a bit more scattered) I will discuss additional API design anti-patterns and how to deal with them. Stay tuned … ;)
I used to call this “Developer eXperience” (DX), but since I have seen multiple concurrent uses of the term “Developer eXperience” pop up lately, I switched to the more concise term “API eXperience”. ↩︎