So you may be in charge of an API. Perhaps you are about to dive into making one and are excited to get started. But be careful, because good API design can be hard.
There are lots of things to think about when it comes to designing a good API. Unlike with designing web user interfaces, you may not know all your clients' use cases. Or you may have a variety of clients on different platforms. This difficulty gets amplified if you choose to roll your own conventions over choosing an existing paradigm. Don't do this. You risk spending a good chunk of your time thinking about unimportant things and skimping over the important ones.
One of the reasons I like RESTful web services, or REST over HTTP, is that it drives my thinking towards important needs of my API. I also spend less time thinking about frivolous conventions like, "How do I tell a user something went wrong?" Instead, I think, "How do I tell the consumer their validation failed?" Answer: 400 status code. Done. I will be giving more examples later on, but first, it's important to remember that more paradigms exist beyond just RESTful web services.
Before we dig into the available choices, how do you know which paradigm of API design to choose? Making this decision can be tricky. To make things a bit easier, Phil Sturgeon has some great advice that I will recap here. There are three popular paradigms mentioned: gRPC, REST over HTTP, and GraphQL. They are not competitors but fill different niches.
gRPC is great for internal APIs or APIs that work closely with their clients.
REST over HTTP is great when clients have very similar needs and workflows and could be on different platforms.
GraphQL is great when bandwidth is at a premium and you are not really sure what your clients will need. It is also worth a look when you don't need server-specified caching and other such protocols.
Before moving further, take some time to do some analysis of the available resources.
Why Use RESTful?
Once you are certain REST over HTTP is the right pick for you, let's look at some aspects of RESTful web services that can let you hone in on great API design.
1. RESTful Is Resourceful
I love how RESTful services force me to think in terms of resources. A resource is simply a thing represented in your API. It is NOT a database table or even a domain model entity, necessarily. It frames the entire API. Think of your API as a set of resources your consumers can manipulate. A RESTful mindset encourages you to think about the truly important things.
On top of this, only a limited set of methods can act on these resources: GET, POST, PUT, PATCH, and DELETE. There are a few others that have niche uses, but these are the big ones. This does not mean your entire API will turn into CRUD (Create, Read, Update, Delete). It means you'll focus first on what's in your system before focusing on the actions it performs.
2. Form Over Function
When adopting HTTP services, it is also healthy to adopt a known schema, such as JSON Schema. RESTful services really open up the gate to choose a robust schema spec that has much tooling around it. I find this much better than my own system for showing data to consumers. With a known data modeling like JSON Schema, you can make it easy for consumers to know the shape of the data they are getting back. You can also let them know whether a request field is required. Your consumers can even create validators from it.
3. RestFUL, Not REST
It is not usually common to go the full monty with REST and use hypermedia. However, using RESTful services helps me think about how my consumers will use my API. Even if the links are not spelled out, I often mentally walk from the entry point through a chain of connected resources to understand how my consumers may use my API. This helps me finds missing resources or ones that make no sense.
4. RESTful Helps Fill in the Gaps
Once I have a resource, I find it helpful to walk through the main methods: GET, POST, PUT, PATCH, and DELETE. This lets me see if a resource is read-only. Can I edit existing ones or only create new ones? Perhaps the resource is large enough that it needs partial updating via PATCH. Should the consumer be able to remove it? These are questions that I use regularly.
5. Think About the Unhappy Paths
I find it useful to look at the HTTP status codes to get an idea of what can happen when operating on a resource. Can the resource be not found? How do I know when it was the consumer that made a mistake (4xx) instead of the server (5xx)? Could there be concurrency problems with this resource (409)? I treat the status codes list as a guide, spurring questions such as these and guiding my mind towards a robust API.
6. Tell the World How to Stop Calling You
Ahh, caching. You know, it blew my mind when I was reading the HTTP spec and realized we could cache on the client but have the server tell us how to do it. Seems obvious now, but this is still powerful. Working in HTTP naturally draws me to recognizing how cacheable my resources are and makes me focus on how to teach consumers to cache them.
RESTful Focuses on What Matters
You can spend a lot of time figuring out your own conventions. You can agonize over things like, "How do I tell my consumers how to cache?" or "How do I tell my consumers they made a mistake?" Or you can bow down to the boss's pressure to "just get it done." But if you truly want a good design, look at RESTul web services. If this paradigm fits your needs, let it guide your mind to healthy features for your API. Free your mind to focus on what truly matters. RESTful web services let you focus on how to make your API usable and simple.