Recently, a colleague asked me for examples of “Beautiful APIs.” Immediately I gave a tongue in cheek response that “beauty is in the eye of the beholder.” Of course to back this up, I quickly elaborated that an API that is beautiful to me may not be beautiful to them. This got me thinking if there is any way to classify or quantify what would make a beautiful API.
If beauty in the eye of the beholder the following are the key “beholders” to any API:
- Developers are the people consuming the API and creating applications.
- Client applications are the applications which the above developers create, which utilize the API for some purpose.
If you recall the following quote from Donald Knuth, where he expressed that “Programming is the art of telling another human what one wants the computer to do.” Now if we change the word “Programming” to “APIs” and, as we’re in 2019, we’ll replace “computer” with “system,” we get the following:
“APIs are the art of telling another human what one wants the system to do.”
Therefore an API is about communicating with a human. A well-designed API is easy to use and makes the developer’s life very smooth. It makes them productive as quickly as possible.
Adhering to the “principle of least astonishment” when designing an API, it means that the design should match the mental model of your audience, there should be no surprises. Or to put it another way, you should minimize the WTFs/minute of the developers using your API.
Adhering to this principle would mean that accessing the API will feel natural to a developer. Nothing should be jarring. For example, authentication tokens should utilize standard security practice, error codes and messages are intuitive (i.e HTTP 200 OK is not an error status, etc.).
When designing your API you should adopt a product mindset. The API is intended for use by someone else. Whether you think of it that way or not and whether you actually sell it or not, you have a product on your hands, intended for use by someone else. It will have a lifecycle and success criteria. Your API should have a Product Manager assigned to making it successful and adopted – the creation of the API should not just be a Jira task. The API needs to be nurtured and grown to success.
One of the challenges that developers have in providing APIs is that they know once their API is being consumed then they must adhere to and support that contract (semantic version FTW). This is a pretty onerous responsibility, especially as business changes and innovation need change, spending time on design upfront helps. Remember that the API contract has a different lifecycle to the API implementation. A great example highlighting this difference in the implementation lifecycle is AWS’s S3 API. AWS CTO, Werner Vogels, says that “S3 could best be described as starting off as a single-engine Cessna plane, but over time the plane was upgraded to a 737, then a group of 747s, all the way to the large fleet of Airbus 380s that it is now.” However, if you look at the API contract the current version of the Amazon S3 API is 2006-03-01.
Ideally, before any code is implemented for your API the API contract, e.g. OAS 3.0, is defined for review by API consumers. Note this contract could be defined in a tool like Stoplight.io or even with annotations in code, but the API is not implemented. Implementation should wait till the API is reviewed by consumers. If an API is the GUI for developers and if you map this to the accepted UI design workflow. Then the contract is a wireframe and the API consumers are UI users validating what is presented in the wireframes. Once the contract is defined and delighting API consumers then implementation can start.
Remember that you are not the user/consumer of your API so the more validation and feedback that you get the better. An additional way to achieve this is to provide a mock implementation of the contract and to ask your API Consumers to begin to code against the mock. As the consumers attempt this they may see use cases and scenarios that were never thought of.
Another aspect to consider when designing an API is the context in which your API will be used. For example, will the API be internal to your organization as part of a microservice architecture, will the API be public and used in mobile apps, etc. The context that the consuming applications are running will affect the type of API that you provide.
- GraphQL APIs lend themselves to mobile apps and help avoid the chattiness that is seen with REST APIs. With GraphQL the client determines what data they want, how they want it, and in what format they want it, rather than walking multiple REST request – responses to find the resource the app requires.
- SSE (Server-side events) if you need to push data from the server to a web application.
- gRPC – when your APIs are internal to your organization and not on the web (i.e. inside a microservice architecture) and when you control the consumer and the provider.
Knowing where the client apps will run, will help to determine what API you should be providing.
UIs for Developer Experience
Once your API is ready for prime time, ready to be consumed, you will make all the assets (documentation, SDK, code snippets, API definitions, endpoints) available in a developer portal, i.e. the water hole that your target developers hang out in. Note the SDK should not just be a thin veneer around the API definition but should contain samples, build tools for creating applications, etc. It should have everything to help reduce complexity and increase developer experience.
Remember if you’re providing a UI application that accompanies your API, then it will only be useful to a developer in certain environments. Today, adoption of CI/CD is the accepted norm for delivery and deployment of applications. A UI is most helpful at the start and end of a CI/CD pipeline, all other intermediate environments should be considered headless. Therefore providing a CLI is more useful to these headless highly automated environments. Thus within a CI/CD pipeline, the following holds:
- API and CLI useful in all environments
- UI useful at the initial and final environments
Providing the correct CLI and GUI experiences helps enhance the over all developer experience for your API.
With a well-designed API, solid supporting documentation, and good support for developers’ existing tools, you will delight the technical consumers of your API every time.
If you have followed the advice in this blog when you’re asked about a beautiful API then you will be able to turn to the mirror and say with confidence: “Mirror mirror on the wall who has the fairest API of all”, and you will know the answer. 😉
Read why API Design is so important.