Categorizing APIs. Part 1.
A Practical Framework to Make Better API Design and Architectural Decisions
Introduction
The goal of this article is not simply to categorize APIs for the sake of categorization - this is, after all, a highly subjective exercise. Instead, the purpose is to create a practical framework that helps you think about various important API-related dimensions.
I believe that, in many cases, attempting to answer these questions and applying this type of categorization to your own API can help prompt important architectural and organizational decisions. Even seemingly trivial topics - such as documentation or pricing - can have surprisingly significant effects on both system architecture, team structure, and work processes. In the end, this approach can help you build a product that is not only robust and maintainable but also enjoyable and convenient for both developers and users.
Let’s start from the very basics.
API stands for Application Programming Interface. An API enables communication between separate parts of a system, allowing them to exchange information.
These parts can exist at different levels and can be viewed from different perspectives. The information being exchanged can take many forms. The protocols used may vary - or sometimes there may not even be a network protocol involved at all. Other surrounding characteristics can also differ: documentation quality, accessibility, whether the API is public or private, paid or free, and so on.
So, let’s begin.
Distributed vs. Non-Distributed APIs
The most intuitive understanding of an API usually assumes the presence of a local network, the public internet, or both. In other words, we often associate APIs with network communication.
However, not all APIs rely on network protocols.
Many applications run entirely on the same machine and do not depend on any network layer. They may consist of multiple subsystems, modules, or libraries that exchange information internally. The boundaries between these parts are also defined by APIs - even though no HTTP, TCP, or other network protocol is involved.
These are often referred to as Developer APIs (or library APIs). A Developer API represents programming language-specific constructs - such as classes, functions, interfaces, or modules - that are intentionally exposed for use by other parts of the codebase or by external consumers. In this case, the “interface” exists at the language level rather than at the network level.
On the other hand, we have the more familiar type of APIs that rely on network protocols. These APIs operate across process or machine boundaries and form the backbone of distributed systems. They enable services to communicate over protocols such as TCP, HTTP, gRPC, messaging systems, and others.
Mature vs. Immature APIs
Every API has a certain level of maturity. While this assessment is never perfectly objective, there have been multiple attempts to formalize API best practices into structured maturity models.
Some maturity models emphasize specific dimensions such as maintainability, security, scalability, or observability. Others focus on the core conceptual principles of a particular API style.
When speaking about RESTful (Web) APIs, I personally prefer the Leonard Richardson Maturity Model (RMM), which categorizes REST APIs into four levels:
Level 0 – The Swamp of POX (Plain Old XML)
Level 1 – Resources
Level 2 – HTTP Verbs
Level 3 – Hypermedia Controls (HATEOAS)
There are many excellent resources explaining what each level represents, and I strongly recommend becoming familiar with this model if you work with REST APIs. It captures the essential ideas that distinguish REST as a specific architectural style rather than just “HTTP with JSON.”
Of course, RMM is not the only maturity model. Different API types have their own evaluation frameworks, and different organizations may emphasize different dimensions. Some models make sense only for certain system types. Some are highly opinionated. Some companies impose strict security or governance requirements, while others operate with more flexibility.
The important thing to remember is this: maturity models are tools, not goals. We should not aim to comply with every possible model at the highest level. Instead, we should select the framework that is relevant to our context and use it as a guide for improvement.
Even Developer APIs (library or language-level APIs) have implicit maturity characteristics - although they are rarely formalized. For example, exposing all business logic through a single public method in a massive “God” class would hardly be considered mature design. Instead, we rely on established engineering principles such as single responsibility, encapsulation, clear abstractions, and well-defined interfaces. These principles - often rooted in object-oriented design practices - effectively serve as maturity guidelines for non-network APIs.
In other words, maturity exists everywhere. The difference is simply how explicitly we choose to define and measure it.
Standardized vs. Custom APIs
Most APIs I’ve seen in practice are custom. They typically attempt to follow a general understanding of what a particular API style should look like. Sometimes these attempts align well with the core principles of that style; sometimes they only adopt surface-level characteristics.
Over time, many of these practical experiences have been distilled into more formalized standards - publicly available, opinionated aggregations of best practices. These standards are often created by large tech companies that have faced significant API-related challenges due to scale, complexity, and long-term evolution needs.
Such guidelines are usually extensive documents with multiple sections and subsections. They clearly define expectations using modal verbs like MUST, SHOULD, and MAY, and they provide structured answers to questions such as:
What is the common structure of a response?
What fields are mandatory?
Where should domain-specific data be placed?
What is the standard error format?
What are the requirements for identifiers?
How should pagination be handled?
Which HTTP status codes are recommended?
How should search be implemented?
What naming conventions should be used for fields, headers, and query parameters?
What are the authentication and authorization requirements?
What are the general design recommendations and constraints?
Here are a few well-known examples of RESTful API guidelines:
JSON:API – https://jsonapi.org/format
My personal favorite. I appreciate how flexible yet structured this specification is. I’ll definitely explore it in more detail in future articles.
Zalando RESTful API Guidelines – https://opensource.zalando.com/restful-api-guidelines
A well-known and comprehensive example of internal API standardization. It reflects the level of maturity many growing companies eventually aim for.
Stripe API Design Principles – https://docs.stripe.com/api
The introductory section (before “Core Resources”) provides a concise and practical overview of their API philosophy.
There are many more examples - including guidelines from Microsoft, Google, Meta, and other large technology organizations.
The key distinction here is simple:
A custom API defines its own conventions.
A standardized API follows an externally defined specification or an internally formalized company standard.
An additional - and often underestimated - benefit of standardized API guidelines is ecosystem support.
The more widely adopted a specification is, the more tools, libraries, middleware, and integrations become available out of the box. Validation tools, client generators, server frameworks, documentation platforms, monitoring extensions - all of these are much easier to leverage when your API aligns with a recognized standard.
For example, APIs that follow JSON:API or widely accepted REST conventions can often integrate seamlessly with existing libraries and tooling, reducing the amount of custom solutions you need to build and maintain.
Standardization is not just about design purity.
It is also about reducing cost, accelerating development, and benefiting from a broader ecosystem - often for free.
In general both approaches are valid. The real question is not whether an API is standardized - but whether its design decisions are consistent, intentional, and sustainable over time.
Private vs. Partner vs. Public APIs
This dimension is about accessibility.
Companies build products, and depending on their business model, they may choose to expose APIs to different types of consumers - or not expose them at all.
Private APIs
Private APIs are used internally by a company’s own systems. They enable communication between internal services, applications, or components, but are not accessible to external consumers.
These APIs are often critical for internal architecture and scalability, yet invisible to the outside world.
Partner APIs
Partner APIs are exposed to a limited and controlled audience - typically business partners. Access may require legal review, contractual agreements, and formal approval processes. Only after these steps are completed does a partner receive credentials and integration access.
This model is common in industries where data sensitivity, regulatory constraints, or strategic partnerships play a significant role.
Public APIs
Public APIs are openly available to external developers. Companies adopting this model encourage third parties to build integrations, extensions, or entirely new products on top of their platform.
In many cases, this fosters ecosystem growth and innovation. Personally, I believe that - when feasible - this is often the most scalable and future-proof approach. However, this topic deserves a dedicated discussion on its own.
Monetization and Control
Both Partner and Public APIs may be free, paid, or conditionally paid (for example, free tiers with usage limits).
In almost all such cases, proper authentication and authorization are required. Authentication is not only about security - it also enables billing, usage tracking, analytics, and intelligent rate limiting.
In other words, accessibility is not just a technical decision. It is tightly connected to business strategy, risk management, and long-term ecosystem vision.
Anonymous Access vs. Restricted Access
Another simple but important dimension is this:
Can the API be accessed as-is, or does every request require authentication and authorization?
Restricted Access
Many internal APIs operate within the same physical or virtual private network and may communicate without strict authentication requirements. For example, in a microservices architecture, services inside a trusted environment sometimes rely on network-level security rather than per-request authentication.
However, this approach depends heavily on infrastructure design and trust boundaries. In modern systems - especially zero-trust environments - even internal services are often required to authenticate each other.
APIs exposed over the public internet almost always require authentication. A common architectural pattern is to place an API Gateway in front of backend services. The gateway validates and parses authentication claims, enforces policies, and forwards trusted requests to downstream services.
Anonymous Access
Some APIs allow anonymous access - meaning no authentication is required to call certain endpoints. This is common for public data APIs, documentation endpoints, health checks, or open platforms.
However, anonymous does not mean unprotected.
Public anonymous APIs are typically guarded by infrastructure mechanisms such as Web Application Firewalls (WAF), rate limiting, IP filtering, abuse detection systems, and other protective controls. These measures help prevent exploitation, scraping abuse, and denial-of-service attacks.
In short, authentication is a technical mechanism - but access policy is a strategic decision. Whether an API is anonymous or restricted reflects its purpose, risk profile, and business model. Also it significantly shapes the infrastructure setup.
Documented vs. Undocumented APIs
We can neglect many supporting materials - tutorials, API recipes, blog posts, forums, and videos. They are helpful, but not strictly mandatory.
What is absolutely crucial, however, is a well-structured, comprehensive, and clear API Reference.
I usually distinguish between API Documentation and API Reference:
API Reference – a precise, technical, machine-readable description of the API: endpoints, parameters, request/response formats, error structures, authentication requirements, etc.
API Documentation – human-written explanations, guides, and examples built on top of the technical reference.
The reference is the foundation. Everything else builds on it.
The Real Problem: Outdated Documentation
What can be worse than having no documentation at all?
Outdated documentation.
When documentation does not match the actual implementation, it creates confusion, breaks integrations, and can lead to significant financial and reputational losses. In many cases, incorrect documentation is more dangerous than missing documentation. In case of missing documentation people can just go and find someone who is capable to find out the current state of the system. Outdated documentation has dangerous and misleading effect.
Code as the Single Source of Truth
To avoid such situations, I strongly recommend treating your code as the single source of truth and generating your API specification automatically from it.
When documentation is derived from code every small change, every new pull request auto generates the needed changes or highlights the need to update the corresponding API specification.
There are many tools and libraries that streamline this process. For example, the OpenAPI Specification is widely used for RESTful Web APIs and is supported by a rich ecosystem of tools.
Many developers are used to treating the final artifact of an API service as a Docker image or a packaged binary such as a JAR, .WHL, TAR.GZ, EXE and others. I recommend thinking differently.
The API specification file should be treated as another required build artifact.
Introduce proper versioning for it. Store it in an object storage system such as Amazon Web Services S3, Microsoft Azure Blob Storage or any similar solution. This is how your Continuous Integration (CI) pipeline should end: producing both the deployable service and its corresponding API specification.
Later, your Continuous Delivery (CD) pipeline can retrieve the latest specification, generate an updated API Reference portal, and deploy it wherever needed.
This approach guarantees that your API Reference is always synchronized with the actually deployed service - not with a forgotten wiki page from six months ago.
Exposes SDK vs. Does Not Expose SDK
This dimension is closely connected to the previous one about documentation.
Many modern API specifications enable not only automated documentation but also SDK generation - again reinforcing the idea of using source code (or a generated specification) as a single source of truth.
A good example is the already mentioned OpenAPI Specification, which has a mature ecosystem of generators capable of producing client SDKs in multiple programming languages.
Providing an SDK significantly lowers the barrier to entry for consumers. Instead of manually constructing HTTP requests, parsing responses, and handling errors, developers can rely on typed methods, models, and structured error handling.
In practice, SDK strategies usually fall into one of three categories:
Fully custom implementation
The SDK is written manually, giving full control over abstractions, ergonomics, and developer experience.
Hybrid approach
The API specification is used to generate the structural backbone (models, endpoints, serializers), and custom logic is added on top - for example, retry strategies, authentication helpers, or higher-level abstractions.
Fully auto-generated SDK
The SDK is generated entirely from the API specification document, with minimal or no manual adjustments.
Each approach has trade-offs.
Custom SDKs provide maximum flexibility and polish but require more maintenance. Fully generated SDKs are cheaper to maintain but may lack ergonomic refinements. The hybrid approach often offers a practical balance between control and automation.
Whether to provide an SDK at all - and how to implement it - is both a technical and strategic decision. It directly influences developer adoption, integration speed, and long-term maintenance costs.
Free vs. Paid APIs
Some APIs are completely free - no surprises there.
For paid APIs, there are many possible pricing models, depending on business strategy, usage patterns, and technical considerations. Common approaches include:
Pay per request – Charge based on the number of API calls.
Weighted requests – Some requests count more than others depending on complexity or resource usage.
Subscription model – Fixed payment for a certain time period (monthly, annually, etc.).
Freemium / tiered usage – First N requests are free; after that, different pricing tiers apply.
Burst-based pricing – Pay only for spikes in usage beyond a baseline.
Corporate or private tiers – Custom pricing for enterprise clients or private integrations.
Other variations – Hybrid models, volume discounts, pay-as-you-go credits, etc.
The choice of model depends on how the API aligns with business goals, customer expectations, and infrastructure capacity. Pricing is not just a financial decision - it also influences adoption, usage patterns, and system design.
Other Dimensions - to be continued later
In this article, we’ve covered several key ways to categorize APIs. However, there are many more dimensions that influence API design, behavior, and usage. I’ll review these in the next article:
Backward compatible / Non-backward compatible – How changes impact existing consumers.
Self-served / Available after approval – How easily consumers can access the API.
Supports high throughput / Limited throughput – Performance and scalability characteristics.
Highly cacheable / Poorly cacheable / Non-cacheable – How responses can be cached to reduce load.
Highly available / Non-highly available – Reliability and uptime guarantees.
Write-heavy / Read-heavy / Balanced – Typical usage patterns and system optimization.
Bi-directional / One-directional – Flow of data between systems.
Query (Client) oriented / Server oriented – Who drives the interaction: the client or the server.
These dimensions, combined with the ones we’ve already discussed, help create a more complete picture of the API landscape.
Summary
I believe this categorization can help you recall important considerations when designing or building APIs - and, more importantly, facilitates timely and informed decisions which can help to avoid facing big problems later, save resources, and just create better products.
This framework for categorizing APIs is intended as a starting point, and I’d love to hear your feedback. If you have remarks, suggestions for additional categories or perspectives, let’s continue the discussion in the comments below!
P.S. Some of the dimensions covered here are broad and complex. I’m considering writing dedicated posts to explore a few of them in more detail, so stay tuned for deeper dives in future articles.
P.P.S. Finally, I’d like to draw your attention to the Java API framework JsonApi4j that I recently released. This is a JSON:API-compliant Java framework where I tried to assemble my knowledge into a tool that helps build systems addressing many of the topics discussed above.











Interesting article! I'd like to see some real world APIs categorized with this framework as an example.
This article provides a clear and structured overview of API fundamentals. I will recommend it to my students as a reliable starting point to build a solid foundation before moving to more advanced topics.