Contents

Simplify Your API: A Path to Efficiency and Ease

Łukasz Rola

20 Sep 2023.23 minutes read

Simplify Your API: A Path to Efficiency and Ease webp image

When choosing the right tool, it’s important to consider its cost and how well it meets our needs. We want it to do what we need it to do and be of good quality. Sometimes, when two tools are equally good, it’s better to pick the simpler one because it saves time. APIs are like gateways to tools, and it’s important to manage their complexity well. If your business relies on API services, keeping things simple can give you an advantage in the market.

In this article, we’ll talk about how complications can cause problems in APIs. We’ll look at things that can make APIs more complicated, like what they need to do and how they’re built. The article will help you:

  • Avoid making things needlessly complicated.
  • Find out where complications are coming from.
  • Make existing solutions simpler and more efficient.

What is Complication

complication

Photo by Timo Volz on Unsplash

Before we proceed, it’s crucial to clarify the concept of complication. According to the dictionary, complication refers to:

something that makes a situation more difficult, or the act of doing this

In the context of APIs, it encompasses every factor that adds difficulty to API usage or development.

Please note that “complication” and “complexity” are often used interchangeably, even though they have slightly different meanings. When we delve into the dictionary’s definition of complexity, it pertains to:

the state of having many parts and being difficult to understand or find an answer to

In the case of APIs, complexity can be associated with the structure (such as the number of endpoints, headers, and attributes within the message body) or the underlying system hidden beneath the API (including the number of modules or microservices). Complexity can indeed be one of the contributing factors to complication.

Given this distinction, in the subsequent sections of this article, I will primarily refer to “complication” rather than “complexity.” This choice is intended to highlight the specific challenges and difficulties that can arise in the context of API design and usage.

Problems of an Over-complicated API

Numerous issues can be attributed to complications in an API, with the most common being:

API integrator perspectiveAPI provider perspective
Frequent integration failures Problems with testing
Long time spent reading documentation Difficulties with monitoring
Many requests to the API support team Difficulties with scaling
Long integration time Long time spent on integrators’ requests
Big effort put into maintenance Long time spent on delivering new features
Big effort put into maintenance

If you observe any of these indicators, it is crucial to make an effort to understand the underlying causes and determine whether they arise from API complications. If this is the case, you should take the time to reflect on why your API has become so intricate. This reflection is essential to either eradicate the source of the problem or minimize its impact effectively.

In the subsequent sections of this article, we will explore the factors that impact API complication.

Factors of API complication

So many things can complicate an API that it would be almost impossible to identify all of them and describe them in a single article. However, almost all of these factors can be classified into one of the following groups:

  • Functional Requirements: Encompasses all expectations related to the provided functionalities.
  • Non-functional Requirements: Encompasses all expectations related to performance, reliability, security, and other quality attributes.
  • Poor API structure: Refers to a suboptimal design and organization of the API’s components, endpoints, and interactions.

In the subsequent sections, we will delve into these distinct groups, shedding light on the specific challenges and associated considerations.

Functionalities provided by API

The primary purpose of an API is to expose functionalities that can be used by integrators. But when we keep adding new features, the API can become more complicated. So, it’s really important to carefully pick which functions to include in the API. Usually, we base this choice on what clients want most. However, we can also think about other things, like how it fits with the API provider’s business plan.

Let’s consider an example of a bookstore API to illustrate it better. In this scenario, we are exposing an endpoint for fetching available books along with their prices in the currency selected by the API client using the following query parameter:

GET /book-store-api/books?price.currency=USD

{
  "books": [
    {
      "id": "04b1d68-3a85-4ec0-a4e6-8d7a936d4c02",
      "title": "Clean Code: A Handbook of Agile Software Craftsmanship",
      "author": "Robert C. Martin",
      "stock": 3,
      "price": {
        "amount": 15,
        "currency": "USD"
      },
      "description": "Unlock the secrets to writing pristine, 
      maintainable, and efficient code that stands the test of time. 
      Discover essential principles, patterns, and best 
      practices that empower you to create software that is
      not only functional but also a joy to read and work with. 
      Take your programming skills to the next level 
      with this indispensable guide to achieving clarity, 
      simplicity, and excellence in your code."
    },
    {
      "id": "9d2bf831-7fe4-4fb3-ba8c-aa724ac5a773",
      "title": "The Pragmatic Programmer: Your journey to mastery",
      "author": "David Thomas, Andrew Hunt",
      "stock": 5,
      "price": {
        "amount": 17,
        "currency": "USD"
      },
      "description": "Your essential guide to mastering 
      the art of pragmatic software development. Learn how 
      to approach coding challenges with a practical 
      mindset, leverage powerful tools, and adopt 
      efficient techniques that lead to success in 
      any programming project. Unravel the secrets 
      of effective team collaboration, debugging, 
      and problem-solving to become a highly 
      skilled and adaptable developer. Packed 
      with timeless wisdom and real-world advice, 
      this book is your roadmap to becoming 
      a truly pragmatic programmer."
    }
  ]
}

The selection of the price currency introduces a complication in this scenario, giving rise to the following challenges:

  1. Currency Fluctuations: Book prices can be unstable since they depend on exchange rates, potentially leading to discrepancies in book pricing for customers.
  2. Refund Policy Complexity: Implementing a refund policy for purchases made in different currencies can be intricate, as the refund amount may vary due to exchange rate fluctuations.
  3. Exchange Rate Mechanism: An implementation for fetching and managing exchange rates is required to ensure accurate currency conversions.
  4. Handling Failures: Failures related to fetching exchange rates need to be handled gracefully to avoid service disruptions.

While all of these challenges can be handled successfully, it’s essential to carefully consider if the potential business value of providing the API in multiple currencies outweighs the costs and challenges described above.

This example teaches us that we should be careful when choosing features to implement. Adding new functionality has its cost, and it often exceeds the implementation cost. Thoughtful consideration is necessary to strike the right balance between providing value and managing complexity in an API.

Non-Functional requirements

Non-functional requirements pertain to the overall properties of a system that are not directly related to a specific domain. In the book “Fundamentals of Software Architecture” authored by Mark Richards and Neal Ford, these are referred to as Architecture Characteristics and are defined as follows:

the important aspects of the system independent of the problem domain

The book also emphasizes the need to minimize these requirements rather than incorporating as many as possible:

Applications could support a huge number of architecture characteristics… but shouldn’t. Support for each architecture characteristic adds complexity to the design. Thus, a critical job for architects lies in choosing the fewest architecture characteristics rather than the most possible.

I wholeheartedly agree with this perspective. Each non-functional requirement can introduce additional complication to an API. In the following section, we will explore various non-functional requirements, such as accessibility, reliability, performance, backward compatibility, portability, and security. Our analysis will delve into how these requirements can complicate an API.

Accessibility

Accessibility refers to the practice of designing products, services, or digital content in a manner that enables as many individuals as possible to use and access them. Let’s delve into how incorporating internationalization can introduce intricacies to your API.

Consider the previous example of an API for a bookstore. To support multiple languages, language selection can be implemented through a Language header, as shown below:

English response:

GET /book-store-api/books?price.currency=USD
-h Language:en

{
 "books": [
   {
     "id":"04b1d68-3a85-4ec0-a4e6-8d7a936d4c02",
     "title": "Clean Code: A Handbook of Agile Software Craftsmanship",
     "author": "Robert C. Martin",
     "stock": 3,
     "price": {
       "amount": 15,
       "currency": "USD"
     },
     "description": "Unlock the secrets 
     to writing pristine, maintainable, 
     and efficient code that stands the 
     test of time. Discover essential principles, 
     patterns, and best practices that 
     empower you to create software 
     that is not only functional but also 
     a joy to read and work with. Take 
     your programming skills to the next 
     level with this indispensable guide to 
     achieving clarity, simplicity, and 
     excellence in your code."
   },
   {
     "id":"9d2bf831-7fe4-4fb3-ba8c-aa724ac5a773",
     "title": "The Pragmatic Programmer: Your journey to mastery",
     "author": "David Thomas, Andrew Hunt",
     "stock": 5,
     "price": {
       "amount": 17,
       "currency": "USD"
     },
     "description": "Your essential guide to 
     mastering the art of pragmatic software 
     development. Learn how to approach 
     coding challenges with a practical mindset, 
     leverage powerful tools, and adopt efficient
     techniques that lead to success in any 
     programming project. Unravel the secrets
     of effective team collaboration, debugging,
     and problem-solving to become a highly 
     skilled and adaptable developer. Packed 
     with timeless wisdom and real-world advice,
     this book is your roadmap to becoming 
     a truly pragmatic programmer."
   }
 ]
}

Polish response:

GET /book-store-api/books?price.currency=USD
-h Language:pl

{
 "books": [
   {
     "id":"04b1d68-3a85-4ec0-a4e6-8d7a936d4c02"
     "title": "Czysty kod. Podręcznik dobrego programisty",
     "author": "Robert C. Martin",
     "stock": 3,
     "price": {
       "amount": 15,
       "currency": "USD"
     },
     "description": "Opanuj sztukę eleganckiego 
     programowania. Odkryj tajniki pisania czystego, 
     łatwego w utrzymaniu i efektywnego kodu, 
     który przetrwa próbę czasu. Poznaj 
     podstawowe zasady, wzorce i najlepsze 
     praktyki, które umożliwią Ci tworzenie 
     oprogramowania, które nie tylko działa, 
     ale także sprawia przyjemność podczas 
     czytania i pracy z nim. Podnieś swoje 
     umiejętności programistyczne na wyższy 
     poziom dzięki niezastąpionemu 
     przewodnikowi do osiągnięcia 
     klarowności, prostoty i doskonałości 
     w Twoim kodzie."
   },
   {
     "id":"9d2bf831-7fe4-4fb3-ba8c-aa724ac5a773",
     "title": "Pragmatyczny programista",
     "author": "David Thomas, Andrew Hunt",
     "stock": 5,
     "price": {
       "amount": 17,
       "currency": "USD"
     },
     "description": "Twój niezbędny przewodnik 
     do opanowania sztuki pragmatycznego 
     tworzenia oprogramowania. Naucz się
     podejścia do wyzwań programistycznych 
     z praktycznym umysłem, korzystaj 
     z potężnych narzędzi i stosuj wydajne 
     techniki, które prowadzą do sukcesu 
     w każdym projekcie programistycznym. 
     Rozwiąż tajemnice efektywnej współpracy 
     zespołowej, debugowania i rozwiązywania 
     problemów, aby stać się wysoce 
     wykwalifikowanym i elastycznym programistą. 
     Wypełniona ponadczasową mądrością 
     i praktycznymi wskazówkami, ta książka
     stanowi mapę drogową prowadzącą do 
     osiągnięcia statusu prawdziwie 
     pragmatycznego programisty"
   }
 ]
}

While internationalization might appear to have limited complications, it does introduce challenges. From an integrator’s perspective, it may seem like merely an additional header for language selection. However, for API developers, implementing the mechanism entails careful consideration. One major impact of internationalization is on future maintenance. Each newly returned content that depends on the language needs to be translated into all supported languages. Although translation processes can be automated, the involvement of human translators is essential to ensure the quality of translations, leading to additional costs for the API-developing company. Moreover, the speed of API development can be affected. Simple tasks that could be completed in a day might end up taking a week due to waiting for translation completion.

Thus, it becomes crucial to thoughtfully choose the supported languages and limit them to those most relevant from a product standpoint. Adding new supported languages might seem simple during development, but it can entail high maintenance costs in the long run.

Liability

In the context of architecture, liability refers to the responsibility or accountability of a system or component for specific behaviors, functions, or outcomes. It’s one of the architecture characteristics that aims to define the ownership and obligations of different elements within a system’s design. In the case of APIs, liability could be associated with fulfilling requirements related to legal obligations, certification, and API specifications.

To better illustrate the problem, let's go back to bookstore API and imagine the given scenario:

The bookstore has decided to expand its payment options and introduce new payment methods, such as cryptocurrencies (e.g., Bitcoin, Ethereum) and digital wallets (e.g., Apple Pay, Google Pay).

In this scenario, the introduction of new payment methods may require the API to comply with regulations and considerations such as:

  1. Cryptocurrency Regulations: Since cryptocurrencies operate on decentralized networks, there may be specific regulations related to their use for financial transactions. The API would need to ensure compliance with relevant cryptocurrency regulations, including anti-money laundering (AML) and know-your-customer (KYC) requirements.
  2. Digital Wallet Regulations: For digital wallets, the API may need to comply with regulations specific to each wallet provider and ensure secure handling of customer data, such as payment credentials and personal information. Additionally, Apple Pay and Google Wallet entail specific refund procedures that require careful and accurate handling.
  3. Data Protection and Privacy Laws: With the introduction of new payment methods, the API must address any data protection and privacy concerns associated with handling additional financial and personal information.
  4. Financial Security Standards: The API needs to adhere to industry-standard security measures to protect sensitive payment data and prevent fraud or unauthorized access.
  5. User Consent and Agreements: Depending on the payment methods, the API may need to obtain explicit consent from users to process payments using specific payment options and adhere to any agreements or terms of service associated with those methods.

By integrating new payment methods into the bookstore API, the organization must carefully assess and fulfill these new legal obligations. This may involve updating the API’s functionality, security protocols, and payment processing mechanisms to comply with the regulatory requirements associated with the chosen payment methods. Additionally, apart from the development costs of implementing these mechanisms, it may necessitate employing legal specialists to ensure full compliance.

Performance

When discussing API performance, two critical aspects come to mind: API response time, measuring how long it takes to process a single request, and API throughput, quantifying how many requests the API can handle within a given unit of time. Enhancing API performance can be achieved through the implementation of various mechanisms, such as pagination for efficiently retrieving and presenting large data sets and server-side caching to store frequently requested data and reduce redundant processing. By adopting these optimization techniques, the API can deliver faster response times, handle a higher number of requests, and provide users with a smoother and more responsive experience.

On the other hand, implementing these mechanisms can introduce additional complexities to the API. Let’s examine how the introduction of server-side caching can complicate the Bookstore API. The endpoint described earlier, which retrieves available books, presents a suitable opportunity for implementing reverse caching. This is particularly applicable when there are infrequent changes to the book list, its stock, prices, and exchange rates:

From the client’s perspective, server-side caching should be transparent if implemented correctly. However, if not done properly, the client may receive outdated responses, or the cache implementation could adversely impact API performance. To avoid these issues, API providers must meticulously consider potential challenges and pitfalls, such as:

  1. Cache Invalidation: Ensuring the cache is promptly updated or invalidated when the underlying data changes, preventing clients from receiving stale or incorrect information.
  2. Cache Expiration Policies: Defining appropriate expiration policies to strike a balance between data freshness and cache efficiency, avoiding unnecessarily long-lived or short-lived cached data.
  3. Data Consistency: Guaranteeing data consistency between the cached data and the backend source to prevent inconsistencies and data discrepancies.
  4. Cache Size and Memory Management: Managing the cache size and memory usage to prevent excessive resource consumption and ensure scalability.
  5. Performance Impact: Testing the caching mechanism thoroughly to assess its impact on API performance and to avoid introducing new performance bottlenecks.
  6. Security Considerations: Addressing potential security risks associated with caching sensitive data, ensuring that sensitive information is not stored in the cache and access controls are appropriately configured.

It’s crucial to carefully consider whether to implement a cache mechanism, so it’s worth thinking twice before proceeding with the decision.

Backward compatibility

Ensuring backward compatibility is an almost ubiquitous expectation from APIs, but achieving it can be approached in several ways, often involving API versioning with various approaches. Decisions related to backward compatibility hold significant influence over API complication, making it a substantial topic that I’ve elaborated on in two separate articles:

  • Breaking Changes in APIs: This article explores options that can minimize the occurrence of breaking changes or even eliminate them entirely, thus ensuring smoother transitions for API consumers.
  • Effective versioning of web API: In this article, I delve into the choices surrounding API versioning and their impact on future API development, enabling better decision-making when it comes to version management.

While achieving backward compatibility, it remains crucial to make informed decisions that are optimal for a given API use case.

Portability

API portability is a critical characteristic that enables an API to be easily transferred and adopted across various platforms and systems without the need for extensive modifications. Supporting multiple data formats is a significant aspect of portability, as it allows the API to cater to a wider group of clients. However, it is important to recognize that implementing support for multiple formats can also complicate your API.

For instance, let’s consider the Bookstore API, where we want to offer support for both JSON and XML data formats, achieved through content negotiation mechanisms.

JSON version of books endpoint response

GET /book-store-api/books?price.currency=USD
-h Accept:application/json
{
 "books": [
   {
     "id":"04b1d68-3a85-4ec0-a4e6-8d7a936d4c02",
     "title": "Clean Code: A Handbook of Agile Software Craftsmanship",
     "author": "Robert C. Martin",
     "stock": 3,
     "price": {
       "amount": 15,
       "currency": "USD"
     },
     "description": "Unlock the secrets to writing 
     pristine, maintainable, and efficient code 
     that stands the test of time. Discover 
     essential principles, patterns, and best
     practices that empower you to create 
     software that is not only functional but 
     also a joy to read and work with. Take 
     your programming skills to the next 
     level with this indispensable guide 
     to achieving clarity, simplicity, and 
     excellence in your code."
   },
   {
     "id":"9d2bf831-7fe4-4fb3-ba8c-aa724ac5a773",
     "title": "The Pragmatic Programmer: Your journey to mastery",
     "author": "David Thomas, Andrew Hunt",
     "stock": 5,
     "price": {
       "amount": 17,
       "currency": "USD"
     },
     "description": "Your essential guide 
     to mastering the art of pragmatic 
     software development. Learn how 
     to approach coding challenges with 
     a practical mindset, leverage powerful
     tools and adopt efficient techniques 
     that lead to success in any programming 
     project. Unravel the secrets of effective 
     team collaboration, debugging, and 
     problem-solving to become a highly 
     skilled and adaptable developer. Packed 
     with timeless wisdom and real-world 
     advice, this book is your roadmap to 
     becoming a truly pragmatic programmer."
   }
 ]
}

XML version of books endpoint response:

GET /book-store-api/books?price.currency=USD
-h Accept:application/xml

<?xml version="1.0" encoding="UTF-8" ?>
<root>
   <books>
       <id>04b1d68-3a85-4ec0-a4e6-8d7a936d4c02</id>
       <title>Clean Code: A Handbook of Agile Software Craftsmanship</title>
       <author>Robert C. Martin</author>
       <stock>3</stock>
       <price>
           <amount>15</amount>
           <currency>USD</currency>
       </price>
       <description>Unlock the secrets to 
       writing pristine, maintainable, and 
       efficient code that stands the test of
       time. Discover essential principles, 
       patterns, and best practices that 
       empower you to create software that
       is not only functional but also a joy 
       to read and work with. Take your 
       programming skills to the next level
       with this indispensable guide to achieving 
       clarity, simplicity, and excellence 
       in your code.
       </description>
   </books>
   <books>
       <id>9d2bf831-7fe4-4fb3-ba8c-aa724ac5a773</id>
       <title>The Pragmatic Programmer: Your journey to mastery</title>
       <author>David Thomas, Andrew Hunt</author>
       <stock>5</stock>
       <price>
           <amount>17</amount>
           <currency>USD</currency>
       </price>
       <description>Your essential guide 
       to mastering the art of pragmatic 
       software development. Learn how 
       to approach coding challenges 
       with a practical mindset, leverage 
       powerful tools, and adopt efficient 
       techniques that lead to success 
       in any programming project. 
       Unravel the secrets of effective 
       team collaboration, debugging,
       and problem-solving to become 
       a highly skilled and adaptable 
       developer. Packed with timeless
       wisdom and real-world advice, 
       this book is your roadmap to 
       becoming a truly pragmatic programmer.
       </description>
   </books>
</root>

Supporting multiple formats can introduce several challenges:

  1. API integrators have to indicate the content type in which they want to receive data; otherwise, they will receive the default format if one is set.
  2. Proper documentation must be provided to guide clients on how to use and handle different formats effectively.
  3. Every API modification must be implemented across all supported formats to maintain consistency and avoid discrepancies.

As with previous cases, it’s worth considering whether fulfilling the portability requirement brings sufficient business value that compensates for the potential growth in complication.

Security

Security is an imperative requirement for web APIs. It establishes the parameters under which clients can access different components of an API, encompassing conditions such as the level of access granted and the frequency of allowable requests for a specific client. This pivotal aspect ensures the protection and controlled utilization of API resources, contributing to a secure and regulated interaction between clients and the API’s functionalities.

One of the most prevalent methods for client authorization involves the utilization of JWT (JSON Web Token) in conjunction with mechanisms like OAuth 2.0. JWT offers a compact and self-contained way to represent authorization information between parties, making it a popular choice for securing API interactions. OAuth 2.0, on the other hand, provides a standardized framework for authorization, enabling secure delegation of access rights to clients without sharing sensitive credentials. Together, these technologies form a robust foundation for safeguarding API resources while streamlining the process of granting controlled access to authorized clients.

However, the implementation of JWT and OAuth 2.0 introduces set of challenges and considerations that require careful handling to ensure the integrity and effectiveness of the security, such as:

  1. Token Validity and Expiry: Managing token lifespan and renewals effectively.
  2. Token Revocation: Promptly invalidating compromised or lost tokens.
  3. Token Scope: Defining and managing access rights accurately.
  4. Token Storage and Transmission: Securely storing and transmitting tokens.
  5. Authorization Code Flow: Implementing and managing this multi-step flow correctly.
  6. Token Leakage and Impersonation: Preventing unauthorized access and data leakage.
  7. Token Management and Auditing: Monitoring token usage and activities.

Though authorization is nearly inescapable, scenarios do arise where it can be relinquished. For instance, in the development of an internal MVP where security holds diminished relevance, opting out of extensive authorization can expedite the MVP’s creation without compromising its purpose.

Poor API structure

Even when an API has streamlined its functional and non-functional requirements, the potential for overcomplication remains if an inefficient structure is in place. In this segment, we will delve into principles and trade-offs that guide the establishment of an optimal API structure tailored to the specific use case.

API cohesion

Since the API acts as the gateway to a component, the component cohesion principles outlined in Robert Martin’s book “Clean Architecture” remain equally applicable to the API’s design. We can apply these rules to the context of the API:

  • REP (Release Equivalence Principle): Incorporate elements into the API that are released as a unit, avoiding the creation of multiple APIs with the same version number
  • CCP (Common Closure Principle): Include within the API elements that undergo change for the same reasons and at the same time.
  • CRP (Common Reuse Principle): Integrate into the API only functionalities that are commonly reused by API integrators.

As gleaned from the book, these principles “tend to fight each other”, necessitating a careful balance between them. By adapting the book’s diagram to an API context, we uncover the following trade-offs:

api diagram

Neglecting REP (painful integration): This can lead to a poor integrator experience, requiring integration with numerous APIs. In such scenarios, integrators must ensure compatibility between APIs, which adds complexity and overhead to their tasks.

Neglecting CCP (painful development): This can lead to cumbersome development. When this principle is overlooked, it often indicates the presence of tight coupling between multiple APIs, which can substantially hinder the API’s progress. Due to this coupling, the development of these APIs must be carefully coordinated, introducing complications and challenges.

Neglecting CRP (painful releases): When this principle is disregarded, we frequently encounter an unwieldy API that has been developed by multiple teams. This scenario typically results in protracted release cycles and extensive scopes of changes, thereby elevating the risk of introducing failures.

Endpoint granularity

Another crucial question to consider is:

How many endpoints do you have, and how extensive are they?

The straightforward answer is that an endpoint should encompass all the essential data needed to fulfill the client’s requirements and nothing more.

However, is this goal always attainable?

In situations with multiple clients with diverse needs, achieving this balance can become challenging. What becomes essential is understanding the consequences of having endpoints that are either too extensive or excessively small.

For instance, let’s revisit the Bookstore API and its functionality that provides information about authors and their available books. One implementation option involves crafting an endpoint that returns all data related to books, authors, and their works:

{
 "authors": [
   {
     "id": "704b1d68-3a85-4ec0-a4e6-8d7a936d4c02",
     "name": "Robert C. Martin",
     "availableBooks": [
       {
         "id": "c1bdc5c6-7a49-4c45-8e3c-2f47e65a0375",
         "title": "Clean Code: A Handbook of Agile Software Craftsmanship",
         "stock": 3,
         "price": {
           "amount": 15,
           "currency": "USD"
         },
         "description": "Unlock the secrets 
         to writing pristine, maintainable, and
         efficient code that stands the test of time. 
         Discover essential principles, patterns, 
         and best practices that empower you 
         to create software that is not only functional 
         but also a joy to read and work with. 
         Take your programming skills to the 
         next level with this indispensable 
         guide to achieving clarity, simplicity, 
         and excellence in your code."
       },
       {
         "id": "e8c8a24b-5792-4d16-87d5-9e3c8e0b43e8",
         "title": "Clean Architecture: A Craftsman Guide to Software Structure and Design",
         "stock": 2,
         "price": {
           "amount": 20,
           "currency": "USD"
         },
         "description": "Design Software Systems 
         for Maximum Maintainability and Flexibility. 
         Explore the principles and patterns 
         behind building clean, robust, and adaptable 
         software architectures, guided by industry 
         expert Robert C. Martin. Uncover the secrets
         to crafting systems that stand the test of time, 
         fostering a deep understanding of architecture 
         design that empowers developers to create 
         software that is as elegant as it is efficient."
       }
     ]
   },
   {
     "id": "9b5f0b3e-820d-45c7-9847-eb3e3b33ab8f",
     "name": "David Thomas",
     "availableBooks": [
       {
         "id": "9d2bf831-7fe4-4fb3-ba8c-aa724ac5a773",
         "title": "The Pragmatic Programmer: Your journey to mastery",
         "stock": 5,
         "price": {
           "amount": 17,
           "currency": "USD"
         },
         "description": "Your essential guide 
         to mastering the art of pragmatic 
         software development. Learn how 
         to approach coding challenges with 
         a practical mindset, leverage powerful 
         tools, and adopt efficient techniques 
         that lead to success in any programming 
         project. Unravel the secrets of 
         effective team collaboration, debugging, 
         and problem-solving to become 
         a highly skilled and adaptable developer. 
         Packed with timeless wisdom and real-world 
         advice, this book is your roadmap to 
         becoming a truly pragmatic programmer."
       }
     ]
   },
   {
     "id": "ccd61b63-9449-4186-b6f3-ae0fbc3d038a",
     "name": "Andrew Hunt",
     "availableBooks": [
       {
         "id": "9d2bf831-7fe4-4fb3-ba8c-aa724ac5a773",
         "title": "The Pragmatic Programmer: Your journey to mastery",
         "stock": 5,
         "price": {
           "amount": 17,
           "currency": "USD"
         },
         "description": "Your essential guide 
         to mastering the art of pragmatic 
         software development. Learn how to 
         approach coding challenges with a 
         practical mindset, leverage powerful tools, 
         and adopt efficient techniques that 
         lead to success in any programming project. 
         Unravel the secrets of effective team 
         collaboration, debugging, and problem-solving 
         to become a highly skilled and adaptable 
         developer. Packed with timeless wisdom 
         and real-world advice, this book is your 
         roadmap to becoming a truly pragmatic 
         programmer."
       }
     ]
   }
 ]
}

Alternatively, a HATEOAS approach could be adopted::

{
 "authors": [
   {
     "id": "704b1d68-3a85-4ec0-a4e6-8d7a936d4c02",
     "name": "Robert C. Martin",
     "availableBooks": [
       "/book-store-api/books/c1bdc5c6-7a49-4c45-8e3c-2f47e65a0375",
       "/book-store-api/books/e8c8a24b-5792-4d16-87d5-9e3c8e0b43e8"
     ]
   },
   {
     "id": "9b5f0b3e-820d-45c7-9847-eb3e3b33ab8f",
     "name": "David Thomas",
     "availableBooks": [
         "/book-store-api/books/9d2bf831-7fe4-4fb3-ba8c-aa724ac5a773"
     ]
   },
   {
     "id": "ccd61b63-9449-4186-b6f3-ae0fbc3d038a",
     "name": "Andrew Hunt",
     "availableBooks": [
       "/book-store-api/books/9d2bf831-7fe4-4fb3-ba8c-aa724ac5a773"
     ]
   }
 ]
}

Determining the better approach is context-dependent. The first option boasts a comprehensive structure, ensuring that a single API call can potentially retrieve all required data. Yet, this comes with a trade-off, as it increases response payload size and documentation complexity. In contrast, the second option simplifies the structure, but it may require multiple API calls even for simple tasks, like listing authors and their book titles. The decision hinges on factors like data complexity, network considerations, and the user experience you aim to provide.

This example underscores that there isn’t a definitive answer regarding the ideal size of a specific endpoint. However, while designing endpoints, it’s prudent to bear in mind the following trade-off:

how big is scope of your endpoint

  • When your endpoints are too small, API clients will require a multitude of API calls to meet their requirements, thus escalating integration complexity.
  • When your endpoint becomes too large, it might result in extended response times due to a substantial payload, and documenting and using such a complex endpoint could prove challenging.

Summary

In this article, we discussed what API complication is and why it’s important to consider. We explored the potential problems associated with complex APIs and examined factors that can impact API complexity, such as functional and non-functional requirements, as well as inefficient API design. As we learned from the article, while complete avoidance of complexity may not always be possible, there are strategies to reduce it in many cases.

TL;DR

  • The simplicity of your API can influence its adoption.
  • Factors contributing to API complexity often fall into categories like functional requirements, non-functional requirements, and poor API structure.
  • Select your API’s functionalities thoughtfully.
  • Minimize non-functional requirements to the essential ones.
  • Pay attention to your API’s structure and take care of API cohesion and endpoint granularity.

Reviewed by: Michał Matłoka

Blog Comments powered by Disqus.