Designing web APIs
Today you can hear API word used everywhere. But what exactly is API? If you check wiki page you will see:
An application programming interface (API) is a connection between computers or between computer programs
Simply speaking API is a contract provided to the outside world which guarantees specific outcome, and thus it is important that API is well designed.
In order to expose a good contract one must consider the following questions:
- who are the users?
- what can they do?
- how do they do it?
- what do they need to do it?
- what do they get in return?
- where do the inputs come from?
- how are the outputs used?
Besides those questions, good API design is not influenced by different provider perspectives (data, code, business logic, software architecture and human organization).
Web API is an API which can be accessed over the web using the HTTP protocol. It is a framework that helps you create and develop HTTP based RESTful services.
In order to describe API you can use API description format. The OpenAPI specification (OAS) is one of the programming language-agnostic REST API description formats. The OAS is community driven and can be contributed to through its github repository. This format provides a simple and structured way to describe and share a programming interface. An API description format is a machine-readable document that can be used in numerous ways, including to generate API reference documentation. Always explore documentation in order to use the format efficiently.
Designing usable APIs
The easy-to-use APIs are understandable by people and programs, they tend to be as informative as possible, and both success and error feedback provide enough information to understand what has been done and/or fix the problem. To design totally straightforward flows, you must follow these rules:
- ensure that each goal provides a straightforward interaction
- ensure that inputs and outputs are consistent between goals
- when possible, prevent errors by adding data to existing goals to create new goals
- when possible, aggregate goals but only if it makes sense for the consumer from a functional perspective
- each goal of the chain must be stateless
A well guessed API operations are created by defining conventions and following common practices and standards. Being consistent in API design makes the API easier to use and design process simpler. It is a good idea to have localization and internationalization features integrated in your API, so you should always check if it's needed. For each goal dealing with lists consider whether paging, filtering and sorting features will facilitate in use. An easy-to-use API is always guiding consumers, thus why you should consider providing as much metadata as possible (e.g. hypermedia links).
The API should return structured data. Data properties should be arranged properly. This can be done by: grouping properties in data structures, naming them by using patterns and/or sorting them. Also, you should pay attention on keeping the number of properties and depth levels as low as possible.
A well-organized API provides well-organized feedback. The feedback should be categorized and sorted by importance.
Last, but not least, goals need to be organized. Group goals by focusing on functionality and not representation. Besides, don't be tempted to create does-it-all goals, it's always better to have straightforward goals, without side-effects.
Always aim to split data structures, goals and even APIs into smaller but functionally significant elements when possible.
API security is not something which can be neglected in the beginning and assumed that it will be handled later. Regularly, there are news about a company having been "hacked" through their APIs. This is why designer of API should contribute heavily to API security by minimizing attack surface.
To have API secured, operations should only expose and request what is actually needed, On the other hand consumers should only be allowed to use what they really need. Every API design should be done from the user's perspective, keeping in mind what is needed to control access.
In general, in software world, we must always check what can be requested, provided or done through API, as API involves sensitive material. Sensitive data controls a wide range; exactly what should be considered sensitive might not be obvious and should be identified with the help of tech, security, business and legal experts.
API designers must be aware of potential leaks due to the underlying protocol or architecture in order to fully secure the API design.
As every software which is heavily used, API also evolves. Each API evolution must be carefully designed in order to avoid breaking changes, which can cause problems not only on the consumer's but also the provider's side. Breaking changes can be introduced on the following:
- output data
- input data
- feedback (both success and error)
- security level
Depending on the context, breaking changes might be acceptable (e.g. private APIs with consumers inside organization).
Both designers and developers of the API will have to live with previous poor design choices in order to avoid introducing benevolent but breaking changes. To evolve the design API versioning should be introduced. API versioning is design + implementation + product management matter.
Designing APIs with extensibility in mind eases the design for evolutions, lessens the risk of breaking changes and favors API reusability.
Network communication efficiency if an important topic that any API designer must be aware of. Network communication efficiency is important even in our day-to-day life, imagine that you need to setup "smart" kitchen with ADSL bandwidth… On mobile phones, network-inefficient APIs can have significant impact on user experience.
When designing network-efficient APIs you should take into consideration that optimization should be done first on protocol level, and then you can revisit the design level. Some ways that can be used in order to ensure network communication efficiency are:
- activating compression
- persisting connections
- enable caching
- conditional requests
On contrary, the ways to make network communication efficient on design level, one can design API with the following things in mind:
- enabling filtering
- choosing relevant data for list representation
- aggregating data
- proposing different data representation
- enabling expansion
- enabling querying (by using GraphQL)
- providing more relevant data
- creating different API layers
Consumer-to-provider communication is not the only way of communication. You can also design asynchronous goals, notify consumers of events, stream data and process multiple elements in a single call.
API designers need to be aware of consumers' context(s) (including their network environments, habits and limitations). But we need also to carefully consider provider's limitations.
Personal preferences, fashion trends and cutting-edge technologies should be ignored and/or questioned in order to design ideal solution for all API design matters.
Even the simple things need documentation. Everyday objects can come with various types of documentation to help users how to build them, as well as to help the people in charge of building these objects to actually build them.
For each type of documentation which needs to be delivered, API designers should participate in their creation. A detailed reference documentation is a good thing, but it's not enough. User guide must be there as well; it will provide all needed information on how to use API, including how to obtain credentials and tokens. Each of the documentation mentioned should be exhaustive in examples.
Leveraging an API description language can be of great help when creating documentation. A good documentation also helps to test API design, so by providing exhaustive information for each goal should lead to use API correctly.
When API evolves, it's crucial to keep track of modification and inform users of changes.
API documentation is vital for end user, but we must think about the people who will evolve and maintain the API. During API design process we need to stick to some guidelines. These guidelines will help during building and validating new APIs to be exposed. There are different types of guidelines:
- reference guidelines: a minimum API design guidelines that need to be created
- use-case guidelines: ready-to-use "recipes" or solutions
- design process guidelines: cover methods, tools and processes
Those guidelines require us not only to write them, but also to evolve them and make people aware of them. Once guidelines are available our work is not finished! We need to review it from time to time, evolve it and fix it.
In order to design effective and useful APIs, API designers must challenge and deeply analyze the needs their API needs to fulfill. The design process must not be done alone, it's recommended to work with others on reviews.
API design process is hard, but rewarding. This article provides a guideline for establishing a path to well-design APIs.