In the previous four parts of this series, we discussed API benefits, strategy, and business models.
Good API design has some core principles which that may differ in implementation. The authors of APIs: A Strategy Guide have a great analogy:
Every car has a steering wheel, brake pedals, and an accelerator. You might find that hazard lights, the trunk release, or radio are slightly different, but it’s rare that an experienced driver can’t figure out how to drive a rental car.
These principles are closely aligned with John Musser’s third key “make it simple, flexible and easily adopted”. We discuss this topic in depth in the API Gold Standard (II) post. Here we give a summary of the main ideas and how they relate to APIdaze’s APIs.
API design and implementation entail non-functional and functional elements. In this post, we focus on non-functional elements. For more resources describing the functional elements and their technical implementation, see for instance API Codex, RESTful Web APIs, or APIs: A Strategy Guide.
Simplicity of API design depends on the context. A particular design may be simple for one use case but very complex for another, so the granularity of API methods must be balanced. It is useful to think about simplicity on several levels including:
- Data Format: Support of XML, JSON, proprietary formats or a combination.
- Method Structure: Methods can be very generic, returning a broad set of data, or very specific to allow very targeted requests. Methods are also usually called in a certain sequence to achieve certain use cases.
- Data Model: The underlying data model can be very similar or very different to what is actually exposed via the API. This has an impact on usability as well as maintainability.
- Authentication: Different authentication mechanisms have different strengths and weaknesses. The most suitable one depends on the context.
- Usage Policies: Rights and quotas for developers should be easy to understand and work with.
Making an API simple may conflict with making it flexible. An API created with only simplicity in mind runs the risk of becoming overly tailored, serving only very specific use cases, and not leaving enough space for others.
To establish flexibility, first find out what the potential space of operations is based on, the underlying systems and data models. You need to define what subset of these operations is feasible and valuable. In order to find the right balance between simplicity and flexibility:
- Try to expose atomic operations. By combining atomic operations, the full space can be covered.
- Identify the most common and valuable use cases. Then design a second layer of meta operations that combine several atomic operations to serve these use cases.
Arguably, the concept of HATEOAS can further improve flexibility because it allows runtime changes in the API and in clients. HATEOAS does increase flexibility by making versioning and documentation easier. However, in API design, essential questions about the space of potential operations and combinations need to be answered the same.
Having an API that is designed with simplicity and flexibility is only the beginning, as a great API design is wasted if developers do not engage with the API and eventually adopt it. At the same time, well thought out API design has a considerable impact on developer experience and adoption. Adoption is an essential part of the developer experience (DX) — we will return to this and cover it in detail in a future post.
John Musser provides a great take on what it means to get developer engagement in his OSCON 2012 talk:
- Making it very clear what the API does
- Providing instant signup
- Providing free access
- Being transparent about pricing
- Having great documentation
In the same slides, he also presents a key metric to improve API design for easy adoption: Time To First Hello World (TTFHW). This is great way to put yourself in the shoes of a developer who wants to use your API to see what it takes to get something working.
When you define the start and end of the TTFHW metric, we recommend covering as many aspects of the developer engagement process as possible. Then optimize it to be as quick and convenient as possible. Being able to go through the process quickly also builds developer confidence that the API is well organized, and things are likely to work as expected. Delaying the “success moment” too long risks losing developers.
For poster child examples of good developer experience and quick TTFHW, check out the Twilio, SendGrid or Context.IO developer portals. Twilio’s Founder and CEO Jeff Lawson has a great take on this from a wider business perspective.
In addition to TTFHW, we recommend another metric: TTFPA – Time To First Profitable App. This is trickier because “profitable” is a matter of definition, depending on your API and business strategy. It is helpful because it forces you think about aspects related to API operations as part of the API program — we will also cover this in a later post.
Example: The APIdaze API
The HTTP/REST interface has a different goal, as it’s here to provide a set of synchronous and atomic actions to APIdaze underlying infrastructure. Should a developer need to place a phone call between two people, manage SIP (Session Initiation Protocol) devices, or get phone numbers, this is the interface that they would use. This is nothing new for any web developer familiar with HTTP/REST web services. This HTTP/REST interface is not HATEOAS based, and APIdaze has its documentation fixed in that regard, mostly because it has not been considered in the original development of this part of the API, for the sake of simplicity.
APIdaze offers free access to its API, so developers can play, test it, and eventually get engaged to run their applications. Working on having great, clear documentation is also a day-to-day task for the technical team.
- Make sure your API is designed to be simple, flexible and easily adopted — whatever that means in the context of your API.
- Find the logical atomic operations which deliver a result that is easily understood and useful for your audience.
- Identify the most common and complete workflows that should be supported, and how can these be done in the fewest number of calls possible.
- At the data model level, find the common combinations of resources that are frequently needed together.
- Make sure your API is not over tailored to your top use cases. It should allow enough flexibility to cover perhaps even unthinkable use cases.
- Make sure your API is a joy to adopt.
- Measure this adoption via TTFHW and ideally also TTFPA.
- Pay attention to include and optimize the whole process a developer would have to go through.
Once your API is designed and implemented in line with your strategy and incorporating API design best-practices, the API can go live into operations requiring appropriate API management. This is what we will cover in the next part of this series.