Designing APIs is easy. Designing good APIs, however, is not.
That’s because when it comes to API design, there are a lot of considerations that must be weighed outside of core functionality. From naming conventions to version management, the details of an API’s design can mean the difference between success and failure.
You could write a book on API design (in fact, lots of folks have). But for the developers out there who don’t want to read an entire book in order to learn how to design an effective API, this blog post provides a quick primer on API design. In particular, I focus on the two biggest factors you should consider when designing APIs: usability and consistency.
Usability and API design
When designing an API, it can be easy to forget about the end-user. After all, the end-user of your API is other developers, and you might not think of developers as end-users. But the reality is that they are, and they need APIs that are highly usable for their needs.
As technical users ourselves, keeping the end-user in mind when designing and developing an API is especially crucial. Where a beautiful frontend can hide the warts of a legacy application, a poorly designed and built API is immediately obvious to the experts that will be consuming it. While usability can be a relatively subjective concept, there are a few key factors that should be taken into consideration to ensure that your API is not only usable but easy to use:
There are a handful of different authentication methods, each of which has their own benefits and drawbacks. Query-based authentication (putting the API key in the query parameters of a request) is the easiest to implement but can make multi-user APIs more difficult to implement. On the other hand, Bearer-token authorization (putting the API key in the Authorization header of a request) is slightly more complicated from a testing standpoint (especially when combined with OAuth authentication), but it is an excellent solution for third-party integrations. Whichever choice you make, identifying how your end-users will work with your API should guide the methods that you support.
Many organizations require the APIs that they use to implement API versioning in order to ensure stability. It doesn't particularly matter how you version your API (I've seen hundreds of arguments over the "right" way to do it), but it is important that you actually do so (except in the event that you are the only consumer of the API, in which case you can likely get away without versioning). This reassures your users that you won't be arbitrarily changing the input parameters or output format without giving them enough time to migrate their implementations.
At their cores, the most extensible and maintainable APIs are treated with the same care as any other user interface. Taking into consideration best practices and ideal patterns can help not only improve the marketability of an API, but also the decision processes made against it in the future. While it's easy to promote usability, a great way to ensure the usability of an API is to create the official SDKs and clients in-house. This ensures that you are not only dog-fooding the API — you are also getting practical experience with how it works from the perspective of the end-user.
Going hand-in-hand with usability in API design is consistency. While it is not always possible (or practical) to follow "best practices" in the context of your API, having an opinion and adhering to it can go a long way towards ensuring the API’s quality — and perhaps most importantly, its maintainability. Consistency can come in all forms, but at its core, it means that endpoint A and endpoint B should not only look similar, but they should work similarly as well. When designing your API, there are a few things that you should consider up front to better encourage design consistency:
Singular vs. Plural Nouns
A hotly debated subject amongst API developers, the reality is that it doesn't matter whether or not you are using singular or plural nouns, only that whatever you choose you should stick with it. While this may seem pedantic, deciding whether your API endpoints will look like /api/authors/1 or /api/author/1 ahead of time will reduce user confusion and streamline the addition of new API endpoints in the future.
HTTP Request Methods
GET, PUT, POST, PATCH, DELETE… While I have a personal opinion of when each of these request methods should be used (something that speaks more to usability than consistency), what matters most when designing your own API's HTTP request method support is that you use your choices consistently. If POST is used to both create new entries and update them in one resource, then you shouldn't use PATCH for the same use cases in another.
Some APIs choose to nest their resources like this: /api/blogs/1/articles. Others choose to keep all of their resources in a global scope, like this: /api/articles?blog=1. While there are merits to each method, the correct solution is one that is specific to each individual API. That said, combining the two methods arbitrarily can lead to confusion amongst your users, so deciding how you will handle resource depth up front can make a difference in not only the design of your API but its architecture as well.
Usability + Consistency = Predictability
If an API is built with usability and consistency in mind, then integrating with that API becomes predictable. While things like documentation and support are important in a popular API, the more predictable an API is, the easier it can be for your end-users to integrate with it (and the easier it is for your development team to expand upon it). Far from a "sexy" word in software development, predictability is the feature that fuels the API fire, ensuring that what you build today will still be used by your customers a year from now.