Design depends largely on constraints.
Charles Eames
APIs are a necessary design element in any infrastructure that interconnects components digitally. APIs allow various components to communicate, and looking at it this way shows what general pattern APIs actually are. When we say “pattern” here, we refer to the general communication interactions that APIs support. Note that this is at a higher abstraction level than specific technologies that define concrete ways of implementing patterns.
Since APIs are such a general pattern, the question arises whether there is one right way to design APIs. But unsurprisingly, the world is a little bit more complicated.
A good example is the “REST versus GraphQL” debate, which has been happening for several years in various forms. If we look past the strange debate that one API approach is generally better than another, it doesn’t take long to see that this question compares things on a different level. Let’s briefly look at these levels because they give us a great way to distinguish patterns (which we call API styles) from technologies.
REST is a pattern, meaning that there is no “REST technology” or “REST protocol.” HTTP is a useful foundation for implementing that pattern, but it also takes media types (the web’s term for the payloads being exchanged via APIs) to end up with a RESTful architecture that can be implemented.
On the other hand, GraphQL is a technology that defines how clients can query into a data model managed on the server. It defines everything that is necessary to use GraphQL APIs, which most importantly are exchange formats, and the semantics of how exchanging them makes a GraphQL API work. GraphQL is not the only way how the query pattern can be turned into a specific technology, but currently it’s the most visible. Other technologies based on this query pattern are OData in the space of enterprise IT and SPARQL with a more research-oriented slant.
What this shows us is that it is helpful to distinguish between the general design pattern that an API is using and a specific technology that is a way to implement this design pattern. That way, we can have more focused discussions either about the general design approach that an API is taking, or about a specific technology that is then used for the concrete API design.
We call these different design approaches API styles. In the following section, we will look at the five fundamental styles in the API space and what their properties and typical application areas are. Looking back at the comparison from earlier, these are based on two out of the five styles; the first once focuses on resources as the most fundamental API abstraction, while the second one focuses on query capabilities as an API’s main abstraction.
APIs Are Languages
Before we dive into the styles, let’s take a step back and look at what APIs really are. They are nothing but a language that defines how various applications can communicate. Like any other language, API languages need two key elements to work. API languages need ways for how individual messages can be exchanged (you can think of this as sentences when you look at human languages). API languages also need ways of how the exchange of messages turns into a meaningful conversation (you can think of this as the shared goal of having a meaningful conversation when you look at human languages).

Figure 6-1. APIs are languages: messages and conversations
Because APIs are languages in the IT space, it also is important to think about the main abstractions they are based on. These main abstractions manifest themselves in the communication patterns and in the communicated elements (the exchanged messages).
In the following discussion of the five API styles, we take a close look at the main abstraction that an API style is built on (the “first principle” of the API style), and at the fundamental interaction patterns. In all these cases, we look at how this presents itself for the API consumer (who “sees” only the API and not the implementation) and for the API developers (who have to develop the code that implements the API).
Let’s look at two simple real-world examples of how the problem being solved can be important in determining an appropriate solution.
For an API that allows things to be submitted, such as an order, it can make a lot of sense to use an API with a rather traditional control flow. If an API supports a purchase process, there is probably a workflow of requesting product information, supplying purchasing information, receiving the purchase confirmation, and supplying shipping information. All of this works well in traditional request/response APIs, and styles using this pattern may be particularly well suited to representing the act of purchasing something as a guided process.
For an API that notifies consumers of certain events, it may be useful to look at an API style with a different interaction pattern. For example, if an API can notify consumers when a customer’s address has changed, it would be useful if the API triggered an event, and consumers would be listening for that and get notified when it happens. This way, consumers don’t have to do any kind of polling, and these events can be propagated and processed in a fast and efficient way.
It is important to keep in mind that all styles can be used to design and implement working APIs for both of these scenarios. It is simply that the problem addressed by an API is an important constraint when it comes to deciding which style and technology to pick. As the saying goes, “If the only tool you have is a hammer, every problem looks like a nail.” When you consider styles as being tools in your API toolbox, then the more APIs you are working with, the more likely it is that having more than one “style tool” can help you to solve problems in a better way.
There are other important constraints, of course. These include the API landscape, the expected audience of the API (private/partner/public), knowledge about consumer preferences, and more. We will discuss these additional constraints in more detail in “How to Decide on API Style and Technology”, but first we will discuss the individual styles.
The Five API Styles
API styles are API interaction patterns, based on the interaction model and the main abstractions upon which an API is built. Being an interaction pattern means that the API style will determine how an API is designed and how this design will be implemented in a specific technology.
One of the most important aspects of API styles is that, ideally, an API’s design constraints, the choice of style, and technology for implementation should be aligned. If that’s not the case, this misalignment may lead to poor designs (when the design constraints and the style do not align) or poor implementations (when the style and the technology are not aligned).
The five styles presented here have been selected based on interaction patterns and technologies that have been or are popular in the API space. It certainly would be possible to come up with a different list of styles, but the ones we present here have worked well for us in our API practice, and they provide a useful framework for better understanding the many API technologies that are in existence.
For each of the styles, the most important aspects are the interaction model and the main abstractions, and these are the topics we focus on when describing the styles. As we will discuss after a description of the styles, none of them is inherently “better” or “worse” than the other ones; they all have specific histories and motivations. Their suitability depends on the constraints of a given API design task.
For each of the styles, we show a figure that illustrates the main properties of the style, i.e., the interaction model and the main abstractions. We also describe how that style maps into technologies and will give some well-known examples.
Tunnel Style
The tunnel style has its roots in mostly thinking about how to expose existing capabilities from an IT perspective. It goes back to ideas such as remote procedure call (RPC), which looks at designing distributed systems in a way that they mostly “feel” like a local system. The idea is that an API is defined for existing “procedures” (or whatever the name is that a programming environment is using to call a named code unit). APIs then become a simple extension of what in a local programming scenario would be simply calling a named procedure.
The tunnel style is convenient from a developer’s point of view because it can take very little effort to create APIs. The main abstractions of this style are procedures, and often they already exist. Tools can be used to expose procedures as APIs, in which case a lot of the task of “creating the API” can be automated. There still should be some management layer for securing the APIs, but that can be addressed with using a component such as an API gateway.
Figure 6-2 shows this simple model: APIs are exposed by implementations, and typically each implementation has its one “endpoint” where all exposed procedures are available as APIs. All calls of these procedures are “tunneled” through that endpoint, where the style’s name originates. If consumers are using APIs exposed in different implementations, they have to use their individual endpoints.

Figure 6-2. API styles: tunnel style
One problem is that the “API endpoint” has little to do with the actual API it is exposing. It is simply a technical access path (the “tunnel”) that all calls have to go through. This can make it slightly complicated to manage security and other issues at the network level. Accessing the APIs behind the endpoint looks identical, meaning that it is harder to manage APIs with components that are not embedded into the implementation.
While the API management issue may be seen as a purely technical issue, there is a deeper problem with the tunnel style: it is very much focused on exposing implementations, meaning that there is no step where an API is first considered from the consumer perspective, then designed with that perspective in mind, and eventually implemented so that the API meets the needs of consumers.
The tunnel style was the style of choice for the first wave of “web services” (in the late 1990s and early 2000s) that used SOAP, an XML-based protocol for remotely calling procedures. There probably isn’t just a single reason why SOAP did not end up delivering the promises that most people were looking for. But it certainly did not help with adoption rates that most SOAP endpoints directly exposed implementation details that were often hard to understand and use for potential API consumers.
SOAP (and other tunnel-style protocols) use HTTP as a simple transport protocol to “tunnel” to the endpoint. This was one of the main reasons why the design ended up this way, because it was relatively easy to add these endpoints to HTTP firewall configurations, and thus it was assumed that this design would help with adoption.
Another advantage of the “tunnel” approach is that SOAP and similar protocols could be tunneled through different “transport protocols.” That way, IT and specifically security teams were able to gradually transition between various transport protocols while they were making sure that the transport protocol was robust and secure to use as a tunnel.
However, a second wave of “web services” started looking at HTTP in a different way. They asserted that HTTP was designed to interact with individual resources (on the web, these would be pages, images, and similar resources) and that an API style more in line with the web would be a more appropriate way to design and implement APIs. This is how the resource style came into existence.
Resource Style
In contrast to the tunnel style, the resource style starts with a consumer-oriented focus. The focus is on which resources to expose to consumers so that they can interact with these resources. The word resource in this context should be interpreted loosely and in fact can be assumed to be similar in scope to what you would have in resources as web pages when designing a web site. There can be resources for persistent concepts such as products, product categories, and customer information. But there also can be resources for process-oriented concepts such as ordering products or selecting a shipping option. In short, everything that is a concept worth identifying because it is used in interactions between the provider, and the consumer is turned into a resource.
As shown in Figure 6-3, the general structure is not all that different from the tunnel style. But that’s really just looking at it from a very high level. The big difference is how the components in the diagram are created. While the procedures in the tunnel style are simply exposing what is defined in the implementation, the resources now create a model that has been derived from a consumer perspective.

Figure 6-3. API styles: resource style
For example, the implementation of an ordering process may have a variety of resources to work through. These might very well resemble the web pages that you go through on many shopping websites: make product selections by browsing products and potentially adding them to your cart, proceed to the checkout, make your payment, and finally provide your shipping information. Every step along that path is a resource that you are interacting with, and designing a shopping website to a large degree means mapping the various aspects of the overall shopping process to resources.
In a well-designed resource-oriented shopping API, these steps will be represented by individual resources. They probably need some information to link up the individual steps (such as a shopping cart identifier and later an order identifier), and we will discuss in “Hypermedia Style” how this can be handled in a more elegant way. But apart from this, the API consumer will use the API based on how the API’s function was decomposed in individual resources, much like these processes in real life also are a sequence of well-defined interactions.
The idea of resources gives us a great way to expose the relevant aspects of an API’s functionality and at the same time allows us to hide implementation details behind the resources. However, what this style lacks is the ability to better represent the fact that, oftentimes, there are workflows across these resources. If all that matters is exposing resources, then maybe this is not such an issue. But oftentimes there are processes (or other kinds of relationships) across the resources, and if that’s the case, then the hypermedia style adds a crucial element to the resource style to address those concerns.
Hypermedia Style
The hypermedia style takes the resource style and adds the web’s essential ingredient: links between resources. Just as on the web, the most important paths across resources can be navigated by simply using links between them (instead of having to know each resource individually and enter its URI in the browser’s address bar); the hypermedia style does the same but for the resources of an API.
This means that on the surface, the hypermedia style looks similar to the resource style. The main abstractions of a hypermedia API are its linked resources, and the resources themselves are exposed in a similar way as in the resource style. But as an essential difference, in the hypermedia style, another fundamental abstraction is that of links between resources, as shown in Figure 6-4.

Figure 6-4. API styles: hypermedia style
Since we mention the web as a well-known example of a hypermedia system, it’s worth pointing out a crucial difference with APIs: on the web, humans read pages and then decide which link to follow. For hypermedia APIs, this decision is usually made by a machine. This means that links need to have machine-readable labels so that machines can identify the available options and then make a choice. These labels are conceptually similar to the text of a link that humans click on web pages, but the labels are represented in the machine-readable representation of resources, which nowadays in many cases will be JSON.
In the same way as on the web, where you can “navigate” with your browser by using links, the same can be done in a hypermedia API, where you can “navigate” across resources using the links between them. To understand the crucial difference to the resource style, just imagine a web without links: it wouldn’t be the same at all, would it?
There are two main advantages of hypermedia APIs over resource APIs, and they both are a direct result of the added links.
Links help with scenarios that have “main workflows,” because consuming the API then becomes a question of following the right links to get the job done. A well-designed hypermedia API will always provide all the links necessary to choose the available next step. Some of these links can depend on context. For example, in a shopping API, the part of the workflow where shipping information is necessary might provide different options, depending on the identity of the customer and other contexts such as ordered goods and shipping destination. Designing these options into the API results in a good developer experience (DX) because it is immediately apparent which possible next step a workflow provides.
Links span resources, and it doesn’t matter whether these resources are provided by one API or several APIs. This means that hypermedia is a great way to provide a unified and easy-to-use experience across resources, even if these are provided by various APIs. As we will discuss in Chapter 9, API design and good DX do not just apply to individual APIs; they also are important across an API landscape. Because hypermedia can link across APIs, it becomes easier for developers to work with several APIs when these are providing links interconnecting resources across APIs.
All of this sounds very positive, and it certainly is true that the success of the web as a very large and very scalable information system indicates that hypermedia may be a good pattern to follow. Some popular APIs are using the hypermedia style, but it still is much less frequently used than the resource style.
One reason is that for developers, working with hypermedia can be challenging initially. As software developers, the traditional mindset is that the code we’re writing is the control flow and that we’re using functions (“Tunnel Style”) or resources (“Resource Style”) along the way. Being steered by data that we receive requires a change in mindset and programming practice, and this may be one reason why the hypermedia style is only slowly gaining momentum.
Like everything in technology, there is no single solution that is best for all problems, and the same is true for API styles. While hypermedia does have some useful attributes, it can also lead to “chatty” APIs that require a number of interactions to access all required information. If an API consumer from the very beginning just knows what they want, wouldn’t it be more efficient to let them say what they want? This is the idea behind the query style covered in the next section, which builds on a model where the API provides access to a potentially complex set of resources and allows a consumer to write a query to get exactly what they want.
Query Style
The query style is rather different from the resource and hypermedia styles, because it provides a single entry point to access a potentially large set of resources. The idea of the query style is that these resources are managed in a structured form by the API provider. This structure can be queried, and the response contains the query results. At some level, this can be seen as similar to how databases work. They have an underlying data model for the data they store, and a query language that can be used to select and retrieve parts of that data, as shown in Figure 6-5.
As with databases, the choice of the data model and the query language can differ based on the technology. But the important aspect is that each API request becomes a specific query to be interpreted and resolved by the API, and as such the model is rather different from the resource and hypermedia models where resources have rather fixed representations that can be retrieved by API requests.

Figure 6-5. API styles: query style
One advantage of the query style is that each consumer can request exactly what they want. This means that with a well-constructed query, it may be possible to combine results that would have required numerous requests in resource/hypermedia APIs. However, for this to work, consumers need to have a good understanding of the underlying data and query models (so that they know how to use the query API properly and effectively) as well as a good understanding of the API’s domain model (so that they know what to query for in the potentially complex domain model provided by the API).
As mentioned earlier, there is no “one best style for an API” without taking constraints around the API into account. Given today’s trends in API technologies, it seems that query-style APIs are particularly successful when it comes to building single-page applications (SPAs). These applications use private APIs that are often just used within the same organization by the backend team and frontend developers, working on mobile or web apps, for example. In this scenario, shared domain knowledge is very good, changes to the data model can be coordinated across teams, and generally speaking the higher efficiency is worth the higher coordination effort.
All styles described so far (in “Tunnel Style”, “Resource Style”, “Hypermedia Style”, and “Query Style”) share one fundamental assumption: the API is used in a request/response manner in which the consumer sends a request and expects a response. This is a useful pattern when the consumer is the starting point of an interaction, but how about scenarios where something happens on the server side and the API consumer would like to be notified? This is a scenario where the fifth and last style, the event-based style, is a good fit.
Event-Based Style
In contrast to the styles discussed so far, the fundamental idea of the event-based style is to reverse the interaction pattern. Instead of consumers requesting something from the provider, the provider creates events that are then delivered to consumers of the API. This interaction pattern immediately raises the question: how is this delivery done, and how is it even known that a consumer is interested in receiving certain types of events?
This fundamental issue can be resolved only by introducing some form of infrastructure, which can be done in a variety of ways. Sometimes this infrastructure takes the form of a Publish/Subscribe (PubSub) pattern, and sometimes it is a more decoupled layer that manages events by types and then allows events to be produced and consumed based on these types. In either case, this general pattern is shown in Figure 6-6.

Figure 6-6. API styles: event-based style
Generally speaking, the idea of the event-based style is that interactions are triggered by events, and therefore the idea of an API is based on events as the main abstraction. There are two general cases of how this is being achieved in specific architectures.
One approach is that event consumers (clients in the usual API terminology) are directly connected to event producers, and the stream of events that these producers are generating is delivered to the consumers. This sometimes can be as low-level as getting a stream of measurements from some device, where each event represents a measurement that the device has taken. In this case, subscription means getting an event stream from that source.
Another approach is that event consumers connect to a delivery fabric (sometimes referred to as message broker) that decouples them from event producers. The fabric takes care of managing events, and consumers must subscribe to certain event types so that the fabric can make sure that events of this type are delivered to subscribers. In this case, the architecture is much more centered around the delivery fabric, and all event producers and consumers are connected to this fabric.
As in the other styles, the main abstractions are procedures (“Tunnel Style”), resources (“Resource Style” and “Hypermedia Style”), and schemas/queries (“Query Style”). This means that when using the event-based style, everything should be driven from events. AsyncAPI is a description language that focuses on events (which it calls messages) and that has gained some popularity recently.
One interesting difference of the event-based style is the underlying architecture. All the other styles are inherently decentralized because they assume synchronous interactions between consumers and producers. In most cases where the event-based style is used today, it uses the delivery fabric (the message broker) mentioned earlier and thus relies on a centralized infrastructure that everybody interacts with. While modern products such as Kafka are highly scalable and resilient, this is a remarkable difference when compared to the decentralized approaches that other styles are based on.
How to Decide on API Style and Technology
After going through these five styles, the question is how to choose among them and then how to settle on a technology that implements that style. We’ll look at these questions in the next two sections.
Picking a Style
As is usual in all design and engineering work, there is no “single best style” that can be picked among the five styles that we have discussed. It all depends on the constraints, and these constraints can be largely grouped into three categories:
Problem
As discussed in the individual styles, each style has a certain focus and certain strengths. Thus, it is important to think about the problem that is addressed with an API. Is it one that’s mostly centered on providing access to structured and possible complex data? Maybe the query style is a good fit. Is it a problem that exposes processes that consumers should be able to navigate through? Maybe the hypermedia style is a good fit. Or is it a problem where things happen that consumers want to learn about? Maybe the event style is a good fit.
Consumers
Every API is built for consumption, and thus an API’s consumers always should be an important design aspect. Since APIs ideally are reused, it’s not always possible to plan for all consumers and their constraints, but it makes sense to design with at least some consumers in mind and to make assumptions about others. Consumer input can be in the shape of preferred styles or technologies, but it also can be a question of how easy an API should be able to understand or use and what kind of scenarios will drive the adoption of the API.
Context
Most APIs are part of an API landscape. That landscape can have a different audience and scope, depending on whether the API is meant for private, partner, or public consumption. But in all of these cases, it is important to take that bigger context into account. In the end, the goal of an API should be to be a good API in the context of how it is consumed. For this reason, if an API landscape does favor a certain style, this definitely is an argument in favor of using that style for a new API that is designed within that landscape.
In the end, it is important to think about picking a style as one part of the API process, and “Design Thinking” tells us to always be mindful about consumers. Before jumping into designing the actual API, it is therefore important to first think whether the style will fit the needs of the consumer, and then of course pick a technology corresponding with that has to be seen the same way.
Choosing a Technology for a Style
Once you’re done picking a style, the next task is to pick a technology that works well for the style. As previously mentioned, each of the styles has various choices that you can make.
For example, for the resource style, there is REST as an architectural pattern, but that doesn’t mean that REST gives you concrete technologies. For REST, choosing HTTP as a protocol is a popular choice, and for the representation format it’s probably safe to say that JSON by far overshadows any other representation (such as the XML that was popular before JSON).
For the query style, it’s probably fair to say that GraphQL by now is by far the most popular choice. There are alternatives such as SPARQL, which is typically used in scenarios that center around technologies that are part of the Resource Description Framework (RDF) technology stack. The big advantage that GraphQL has is that it plugs into a JSON-based ecosystem. While GraphQL does not use JSON for queries, it returns results in JSON that make it easy to process in JSON-focused environments.
For the event-based style, there is currently some momentum behind implementing all of an organization’s APIs that way. As we’ll discuss in the following section, that’s not the only way of approaching this, but it is an idea that does have some momentum, and whenever this approach is discussed, Kafka is often mentioned. While in that case Kafka often turns into a crucial and central piece of an organization’s API strategy, it also is possible to treat events more on a per-API basis. In that case, specific protocols such as Server-Sent Events (SSE) or WebSockets can be used to send events to browser-based applications, for example.
Avoid Painting Yourself into a Style Corner
Like many things in architecture, there is rarely a single best way of approaching all problems in a design space. The same is true with API styles. There is no “best” API style. They all have strengths and weaknesses that depend on the problem that is being addressed.
In this book, one of the goals we have is to not just look at individual problems and solutions. This means that we don’t want to focus on looking at just one API and recommending how to decide which style (and technology) to use for this API. We always want to “zoom out” and look at the bigger picture, as we’ll discuss in Chapter 9.
The reality of the bigger picture is that APIs are constantly evolving and changing, and designing the landscape for change is an important consideration. In the past, we have seen approaches that were sometimes rather rigid on styles and technologies. There were SOAP-focused landscapes (based on the tunnel style), HTTP-focused landascapes (based on the resource style or, less frequently, on the hypermedia style), and in recent years there has been quite a bit of momentum toward GraphQL-focused landscapes (based on the query style). The most recent wave seems to be in the form of EDA, often in conjunction with Kafka, which is using the event-based style.
One approach to take is to not “pick” one of the styles (and a technology) as the single design to go with, but instead to embrace diversity and to make sure that the API landscape has some diversity. This is a topic often discussed in the context of Chapter 2, where one of the goals is to find a balance between bringing some order and organization to the API landscape, but without the landscape restricting things too far. This is a tricky balance to get right and would warrant a whole book in itself.
But, coming back to the styles that we have discussed in this chapter (and to the opening quote that “design depends largely on constraints”): for large organizations, it rarely is a good choice to be too restrictive and to try to solve every problem with one style. Instead, treating API styles (and technologies) as a function of the problem that an API is addressing will make it easier to cultivate an API landscape with a better balance of diversity and coherence.
All too often, our classical IT background may lead us down the road of thinking that in order to achieve interoperability and economies of scale, we must tightly control technologies. Instead, what can lead to more resilient and flexible landscape is to acknowledge the fact that there is no best API style and that for now we are embracing more than one style being used in our API landscape.
Summary
In summary, API styles are a way to look at API design that focuses less on specific technical details and focuses on general interaction patterns for APIs. We have discussed five API styles along with their main abstractions and scenarios where they tend to be good fits. We also discussed how to pick a style matching your problem and how to then move on to picking a technology that matches the style.
Finally, we briefly discussed the relationship of API styles and diversity in your API landscape. If there is one important takeaway from this section, it’s to have a more nuanced view of the sometimes passionate debates around API technologies. APIs may be used to expose very different capabilities and may be intended and designed for very different consumers. Not painting yourself into a style corner is an important consideration and will only become more important with your API landscape evolving and growing over time.