There is a lot of interest in REST APIs these days. Unfortunately, most APIs I see are not very mature.
In this post I’d like to share my approach to designing REST APIs:
- Understand the problem domain and application requirements and document them as a state diagram
- Discover the resources from the transitions
- Name the resources with URIs
- Select one or more media types to serialize the various representations identified in the resource model
- Assign link relations to each of the transitions
- Add documentation as required
Note that this is a variation of the design process described in RESTful Web Services. Now, let’s look at each of the steps in detail.
Step 1: Understand the problem domain and application requirements and document them as a state diagram
Without understanding the domain, it’s impossible to come up with a good design for anything.
We want to capture the domain in a way that makes sense for REST APIs. Since the purpose in life for a REST API is to be consumed by REST clients, it makes sense to document the application domain from the point of view of a REST client.
A REST client starts at some well-known URI (the billboard URI, or the URI of the home resource) and then follows links until its goal is met:
In other words, a REST client starts at some initial state, and then transitions to other states by following links (i.e. executing HTTP methods against URIs) that are discovered from the previously returned representation.
A natural way to capture this information is in the form of a state diagram. For bonus points, we can turn the requirements into executable specifications using BDD techniques and derive the state diagram from the BDD scenarios.
For each scenario, we should specify the happy path, any applicable alternative paths and also the sad paths (edge, error, and abuse cases). We can do this iteratively, starting with only the happy path and then adding progressively more detail based on alternative and sad paths.
We can first collect all scenarios and build the entire state diagram from there. Alternatively, we can start with a select few scenarios, work through the design process, and then repeat everything with new scenarios.
In other words, we can do waterfall-like Big Analysis/Design Up Front, or work through feature by feature in a more Agile manner.
Either way, we document the requirements using a state diagram and work from there.
Step 2: Discover the resources from the transitions
You can build up the resource model piece-by-piece:
- Start with the initial state
- Create (or re-use) a resource with a representation that corresponds to this state
- For each transition starting from the current state, make sure there is a corresponding method in some resource that implements the transition
- Repeat for all transitions in each of the remaining states
Step 3: Name the resources with URIs
Every resource should be identified by a URI. From the client’s perspective, this is an implementation detail, but we still need to do this before we can implement the server.
Step 4: Select one or more media types to serialize the various representations identified in the resource model
When extending an existing design, you should stick with the already selected media types.
For new APIs, we should choose a mature format, like Siren or Mason.
There could be specific circumstances where these are not good choices. In that case, carefully select an alternative.
Step 5: Assign link relations to each of the transitions
A REST client follows transitions in the state diagram by discovering links in representations. This discovery process is made possible by link relations.
Link relations decouple the client from the URIs that the server uses, giving the server the freedom to change its URI structure at will without breaking any clients. Link relations are therefore an important part of any REST API.
We should try to use existing link relations as much as possible. They don’t cover every case, however, so sometimes you need to invent your own.
Step 6: Add documentation as required
In order to help developers build clients that work against your API, you will most likely want to add some documentation that explains certain more subtle points.
Examples are very helpful to illustrate those points.
You may also add instructions for server developers that will implement the API, like what caching to use.
I’ve successfully used this approach on a number of APIs. Next time, I’ll show you with an example how the above process is actually very easy with the right support.
In the meantime, I’d love to hear how you approach REST API design. Please leave a comment below.