API Design and Management: Principles, Practices, Preferences
API Design and Management: Principles, Practices, Preferences
and Management
Principles, Practices, Preferences
03 Welcome Letter
Charleigh Smith, Editorial Assistant at DZone
DZONE RESEARCH
APIs are a much-discussed topic in the developer space. At web-specific or web-likely API design approaches”. The
a conference, the question “What Is an API?” can even be responses from the DZone audiences, alongside Esposito’s
used as an icebreaker. On DZone alone, we have hundreds of interpretations, make this trend report engaging and
articles claiming to have the definitive answer to a somewhat enlightening for developers and non-devs alike.
simple question.
Justin Albano, a Software Engineer at Catalogic Software, Inc.,
Our audience suggests that an API is “any interface between writes a guide to successful API design in article, “Effective
software systems”, with some developers specifying that only API Design: 5 Principles to Keep Customers Coming Back”.
REST or SOAP APIs are included in their definition. Others say In this, Albano outlines the key points to keep in mind when
it must be written in HTTP. No matter their view, developers designing and documenting an API. Some examples include
agree that the space has evolved tremendously over the past language independence, simplicity, and consistency.
two years. This advancement has put more pressure on API
Dmitry Sotnikov, the Chief Product Officer at 42Crunch
designers to create clear and objective documentation and
and curator of APIsecurity.io, also chimes in with their
has relied on developers to take on the role of peer mentors,
article “Secure API Design With OpenAPI Specification”.
teaching one another how to work with specific APIs.
In it, Sotnikov focuses on API security, giving examples of
While the majority of devs have worked with APIs, many weaknesses and how to solve them. If used correctly, the
consider their experiences with REST to be the most practices shared in this article can protect your design from
valuable. REST is defined as “a way for one software system up to 95 percent of possible attacks.
to get whatever it wants from another system with as little
Continue reading to find out more about how to create and
prior knowledge of that system as possible”. Essentially REST
document your own API design, keep it safe and secure, and
APIs are building bridges from one system to another in the
find out where other devs stand in the API discussion!
quickest way possible.
DZone Publications
Meet the DZone Publications team!
Publishing Refcards and Trend Reports year- DZone Mission Statement
round, this team can often be found editing At DZone, we foster a collaborative environment that empowers
contributor pieces, working with Sponsors, developers and tech professionals to share knowledge, build
and coordinating with designers. Part of their skills, and solve problems through content, code, and community.
everyday includes working across teams,
We thoughtfully — and with intention — challenge the status
specifically DZone’s Client Success and Editorial
quo and value diverse perspectives so that, as one, we can inspire
teams, to deliver high-quality content to the
positive change through technology.
DZone community.
Lindsay is a Publications Manager at DZone. Reviewing contributor drafts, working with sponsors,
and interviewing key players for “Leaders in Tech,” Lindsay and team oversees the entire Trend
Report process end to end, delivering insightful content and findings to DZone’s developer audience.
In her free time, Lindsay enjoys reading, biking, and walking her dog, Scout.
As a Publications Manager, Melissa co-leads the publication lifecycle for Trend Reports — from
coordinating project logistics like schedules and workflow processes to conducting editorial
reviews with DZone contributors and authors. She often supports Sponsors during the pre- and
post-publication stages with her fellow Client Success teammates. Outside of work, Melissa passes
the days tending to houseplants, reading, woodworking, and adoring her newly adopted cats,
Bean and Whitney.
With twenty-five years of experience as a leader and visionary in building enterprise-level online
communities, Blake plays an integral role in DZone Publications, from sourcing authors to surveying
the DZone audience and promoting each publication to our extensive developer community, DZone
Core. When he’s not hosting virtual events or working with members of DZone Core, Blake enjoys
attending film festivals, covering new cinema, and walking his miniature schnauzers, Giallo and Neo.
John Esposito works as technical architect at 6st Technologies, teaches undergrads whenever they
will listen, and moonlights as research analyst at DZone.com. He wrote his first C in junior high and
is finally starting to understand JavaScript NaN%. When he isn’t annoyed at code written by his
past self, John hangs out with his wife and cats Gilgamesh and Behemoth, who look and act like
their names.
In October 2020, DZone surveyed a global audience of software developers, architects, and other IT professionals in order to
understand how APIs are currently designed and managed.
Methods:
We created a survey and distributed it to a global audience of software professionals. Question formats included multiple
choice, free response, and ranking. Survey links were distributed via email to an opt-in subscriber list, popups on DZone.com,
and short articles soliciting survey responses posted in a web portal focusing on integration-related topics. The survey was
opened on September 15, 2020 and closed on October 9, 2020. The survey recorded 113 responses. Free-response answers were
coded by the survey creator.
In this report, we review some of our key research findings. Many secondary findings of interest are not included here.
Additional findings will be published piecemeal on DZone.com.
Interacting robustly with any given system requires knowing three key points:
3. How anyone working on these systems in the future is likely to think about these systems
System designers learn all three of these from direct experience, but points (2) and (3) depend on systems not directly
experienced because:
• The systems currently interacting may interact with other (unknown) systems in the future.
So we wanted to offer the API designers and managers, who need to know points (2) and (3), some information about how APIs
currently work, and how people who design and manage APIs currently experience them at a scale beyond their immediate
experience. For this research target, we did not generate any a priori hypotheses. The purpose was simply to provide empirical
data and analytical commentary.
Have you ever designed an API? Note: Even if you have not consciously designed an API, answer “yes” if you have
hypothesized how future clients could best plug into your code over any length of time.
Table 1
Percent n
Yes 80.4% 90
No 19.6% 22
Observations:
1. The respondent pool was moderately senior with the average (arithmetic mean) number of years as an IT professional 15.7.
The survey population’s right-shifted experience distribution skewed answers to this question. Of senior software
professionals (defined as “have more than 5 years of experience as an IT professional”) 94.2% (n=65) designed an API,
while only 38.9% (n=7) of junior developers have designed an API.
2. The vast majority (97.6%, n=82) of developers who designed any API (i.e., responded “yes” to this question) also designed a
REST API.
Since we didn’t ask about any further subtypes of API (e.g., abstraction level, protocol), we don’t know how many of the
API designers designed only REST APIs (beyond the eight that didn’t design a REST API). Given our broad definition of
API, it seems exceedingly unlikely that most developers who have designed an API have designed only a REST API.
Moreover, we might imagine that experience designing different subtypes of API could result in significantly different
thought patterns. For example, a kernel developer who designs syscalls might think much more about low-level
resource management problems than a web developer who must anticipate unboundedly high request volume
variance. Further subtyping of API design types might be a useful area for future research.
3. People who have designed an API think somewhat differently about the term’s meaning than people who have not.
In response to the ranking question, “To me, ‘API’ denotes (1 = most properly denotes to 5 = least properly denotes),”
the definition, “Any interface between software systems” scored highest among respondents who had designed an
API, while “a REST API specifically” scored highest among responds who had NOT designed an API.
Our guess is that, in the age of the web, the non-specialist developer is more likely to have worked regularly with REST
APIs than with other APIs. Or to put it another way, there are many more passive consumers of REST APIs than of
other interfaces generally regarded as APIs.
A little background: REST is hypertext for computers — a way for one software system to get whatever it wants from another
system with as little prior knowledge of the target system as possible. To make this happen, REST takes advantage of the
orthogonality of three features of the web:
In this model, maturity is measured along a dimension of “webbiness,” with the “least maturely REST” implementations
treating http as, effectively, nothing but an otiosely high-level transport layer (if conveniently well-tooled).1 And the most
mature take full advantage of the three “webby” dimensions mentioned above.
We asked a question that maps the Richardson maturity model, but with one additional permutation stuck in just in case his
data got too old:
What approach to discovery and content negotiation does the REST API that you designed take? If you have designed more
than one REST API, choose the answer that is true of the REST API you’ve designed most recently.
Table 2
Approach Percent n
Observations:
1. Real-world REST may have matured over the past two years.
In 2017, we asked a similar population an analogous question but worded somewhat differently. Then, only 30.9% of
respondents reported building REST services at Richardson Level 2 versus 48.8% in 2020. And slightly more reported
Richardson Level 3 — 15.9% versus 13.8% in 2020. We can’t make a firm statistical claim here because neither survey
population targets nor response sizes are normalized between the two surveys.
Further, the 2017 question asked for percent of REST services ever created at each maturity level, while the 2020
question focuses on REST service most recently created. But solidifying this possible “maturation of REST in the wild”
might be an interesting future research goal.
2. Senior developers (defined as “have more than five years of experience as an IT professional”) are more likely to build
“maximally webby” (Richardson Level 3) REST APIs.
That is, no junior developers (defined as “have less than or equal to five years of experience as an IT professional”) have
reached HATEOAS in their most recent REST API, while 15.2% (n=10) of senior developers did. Maybe this is because
HATEOAS is difficult — more specifically, the kind of difficult that requires “mechanical sympathy” engendered by
years of experience with the web (of the sort that preceded the Fielding dissertation), rather than simply cleverness or
theoretical understanding of distributed systems.
3. High-volume (C10k) APIs may be more likely to be maximally mature (HATEOAS) but less likely to be almost-maximally
mature (Richardson Level 2) [see Figure 1 on the next page].
1
Fowler, M. (2010, March 18). Richardson Maturity Model. martinfowler.com. https://martinfowler.com/articles/richardsonMaturityModel.html
Richardson Level 2
HATEOAS
0 10 20 30 40 50 60
Perhaps high-volume APIs are more likely to be designed for one-off requests (“give me exactly this thing”) than complex
content negotiation and discovery (i.e., true hypermedia). The current C10k segment is too small to support any conclusions.
For now, our account must remain a wild guess, but it would be interesting to know if request volume and hypermedia-ness
are inversely related.
To the former, no contract is perfect, as no abstraction is leak-proof. API documentation — even a simple method signature
— is sufficient to use an API, until it isn’t. When the explicit presentation of the design communicates too little to relate clearly
to the problem at hand, understanding some of the API designer’s or manager’s reasoning helps the user make educated
guesses about what is likely to happen. This guess-the-mind-of-the-designer experience is familiar to every developer. But it
figures even more prominently in the development process when the interface itself is as far as the user’s mind is able to reach
(i.e., when the implementation source is not available).
And to the latter, this peer-to-peer learning happens both by direct absorption of theories communicated explicitly by others
(e.g., Dijkstra’s declarations from on high, Fielding’s REST dissertation,2 a random developer rant-blogging) and also by drawing
analogies between others’ experiences and the problem at hand — the sharing of war-stories.
For this research target, we generated some a priori hypotheses from theories that reflect our experience in software
development. Where our research was designed to test any hypothesis, the hypothesis is presented along with the theoretical
reasoning that engendered it. Extra commentary is offered where hypotheses were falsified.
2
Fielding, R. T. (2000). Architectural styles and the design of network-based software architectures [PhD Dissertation]. https://www.ics.uci.
edu/~fielding/pubs/dissertation/top.htm
Answer options were scored as weighted sums, for which a rank of one counts as five points and a rank of five counts as one
point. Respondents ranked five definitions of API from highest to lowest, as shown in Table 3 below:
Table 3
Observations:
1. The most capacious definition of API came out on top by a comfortable margin. But the “REST API specifically” definition
was not far behind (259 vs. 285 points).
This suggests that the mental association between the concepts “API” and “REST” is stronger than the strict technical
sense of the term API. Moreover, the combined score (510) of the two often-web definitions “a REST API specifically”
and “a REST or SOAP API specifically” greatly exceeds the score of the most generic definition.
Because the question required all options to be ranked, it does not quite follow that developers think web API before
they think generic API when they hear “API.” But it does appear that “web,” or at least “distributed and probably via
XML and probably with WSDL” (for SOAP), figures very prominently in developers’ mental picture of APIs in general.
2. Notwithstanding observation one, http itself seems overall less tied to the sense of API than higher-level, web-specific or
web-likely API design approaches (REST or SOAP).
This may suggest that the http abstraction is fairly opaque: Developers think of what you do with an API on top of http
more than the fact that your systems talk http. This is consistent with the observation that the full three dimensions
of the web’s API-enabling power — URI flexibility, verb multiplicity, and request/response chains — are not always
exploited (see p. 6, para. 2).
3. However, a caveat — the dominance of Java developers in our respondent pool, and in our general research population,
skewed these results significantly.
Apparently, Java developers think of API in less “webby” terms than others, and the “webby” sense dominates
the meaning of API among non-Java developers. Among Java developers (defined as anyone whose primary
programming language at work is Java), the definitions of API were ranked as shown in Table 4 and 5.
Table 4 Table 5
RANKING OF API DEFINITIONS BY JAVA SPECIALISTS RANKING OF API DEFINITIONS BY NON-JAVA SPECIALISTS
Any interface designed for public consumption 2 A REST or SOAP API specifically 2
Any interface that uses http 5 Any interface that uses http 5
Every approach to API versioning involves tradeoffs, of course. And the kind of design and management decision that involves
tradeoffs is precisely the kind that benefits from standing on the empirical shoulders of giants. We wanted to sketch these
giant shoulders by learning how software professionals actually think about approaches to REST versioning.
We asked: Rank the following ways to version a REST API (1 = best to 3 = worst):
Answer options were scored as weighted sums, for which a rank of one counts as three points and a rank of three counts as
one point. Respondents ranked three approaches to REST API versioning from highest to lowest, as shown in Table 6 below:
Table 6
Observations:
1. The highest-ranked approach to REST API versioning, version number in URL, is (a) the most resource-dependent (the
actual URI must change) and (b) the least involved with http negotiation itself (involves no headers).
Further, it is (c) the easiest to implement when the implementation is not highly abstracted. This works on the
assumption that interjecting a small substring into a URL string is easier than adding a key-value pair like “api-version:
1” into the header. Points (a) and (b) together suggest that resources dominate developers’ thought space about REST,
or at least that developers think of REST at a higher level than http itself. Point (c) may suggest that developers tend
to build RESTful requests at a lower level of abstraction than purpose-build RESTful toolkits facilitate. Or perhaps, since
URLs are maximally visible in web browsers, developer preference for API versioning in the URL reflects a workflow
that heavily involves throwing GETs around in consumer-oriented tools.
2. Respondents who have designed and respondents who have not designed APIs both rank these API versioning
approaches in the same order.
The gap between “version number in URL” and “custom request header” is greater among those who have designed
an API (168-131=37, a 22% drop) versus those who have not (28-24=4, a 14% drop). Maybe API management is easier
when different URLs are maintained for different API versions because the demarcation between old-version and new-
version requests is extremely obvious.
If this is the case, then this might suggest some suboptimal absence of higher-level API management tools that
would make API version management less cognitively burdensome. However, the small n (11) for the “have not
designed an API” segment of respondents to this question is small enough that this account must remain a guess
pending further research.
Hypotheses
We also developed this survey in order to test specific hypotheses about the thought-world of practicing software professionals
who work on API design and management. These hypotheses were generated from broader theories about software
engineering, maintenance, and management and heavily informed by our own experiences developing software.
Reasoning: People who like static types like the shape of things to be nailed down — they would rather find formal errors at
compile-time or the equivalent (i.e., some kind of static analysis) than run-time. They understand complex systems partly by
understanding the definition of the interfaces between the parts of the system, even before the system runs dynamically.
Some approaches to data interchange formats prefer to enforce schemas in the messages themselves (e.g., Protobuf). Others
prefer to reduce messages to (nestable) key-value maps (e.g., EDN). Both approaches have optimal use cases. But sometimes
a given use case does not clearly demand one approach over the other. In such cases, with all other things being equal, is it
generally a good idea for a message schema to be enforced at the level of the data interchange format?
Observations:
While respondents who prefer static typing at the language level were only slightly more likely than those who prefer
dynamic typing to say, “often it’s a good idea” or “usually it’s a good idea” to enforce message schemas at the level of
the data interchange format (44.3% vs. 40.7%). However, dynamic typers were more likely (25.9% vs. 17.3%) to say “it’s
usually a bad idea” to enforce message schemas at the data interchange level. Neither of these signals is very clear on
its own given the relatively small, combined n=79, but together we think they mildly confirm our original hypothesis.
2. Somewhat less expected, static typers were more likely (23.1% vs. 18.5%) to have “no opinion” on the enforcement of
message schemas.
Our current guess is that this agnosticism — despite general preference in favor of message schemas — is the result
of a clash of mental habits, which prefer predefined structure, with actual professional experience with APIs. (The
purposes of APIs often change subtly and unpredictably, especially in large, kludgy enterprise codebases.)
Figure 2
35
30
25
Prefer Statically Typed Languages
20
Prefer Dynamically Typed Languages
15
10
0
Usually it's Often it's No opinion Often it's Usually it's
a bad idea a bad idea a good idea a good idea
Sub-hypothesis: Java developers prefer message schemas more than non-Java developers.
Reasoning: We wanted to test the same hypothesis regarding mental habits of static typers versus dynamic typers in the
context of APIs on two popular languages with different approaches to type systems. Originally, we wanted to test Java versus
JavaScript developers specifically, but too few JavaScript developers responded (n=3).
No single language provided enough respondents to this question for a significant comparison, so we lumped all non-Java
respondents together and altered our hypothesis. Most, but not all, of the languages our respondents say is their “primary
programming language at work” are less strongly typed than Java.
1. Our hypothesis was confirmed stronger along the somewhat specific Java versus non-Java axis than along the generic
statically versus dynamically type languages axis. 52.1% (n=25) of Java developers responded that “often it’s a good idea”
or “usually it’s a good idea” to enforce message schemas at the level of the data interchange format versus 43.3% (n=17) of
non-Java developers.
HYPOTHESIS TWO
Hypothesis: API creators are more likely to be agnostic or negative about message schema enforcement.
Reasoning: For an API designer or manager, settling on and maintaining message schemas requires additional, sometimes
thankless labor that, under the right circumstances, can outweigh the benefits of schema enforcement. API consumers
who do not also design APIs do not need to maintain this overhead, so there is less pressure on the consumer group against
message schema enforcement.
Observation:
1. The results contradicted our hypothesis. Respondents who have designed an API were more likely to consider message
schema enforcement “often a good idea” or “usually a good idea” (46.2%, n=36) than those who have not (22.3%, n=4).
Further, the non-API-designers were more likely to respond, “usually a bad idea” (27.8%, n=5) than the API designers
(16.7%, n=13). Again, those who have not designed an API were more likely to have “no opinion” about message schema
enforcement (38.9%, n=7) than those who have designed an API (23.1%, n=18).
In retrospect, an obvious explanation presents itself: If you’re calling an unfamiliar API, you’re reasonably likely to
get the message format wrong at first, especially if the API is poorly documented, as many are. And if how you
erred seems insignificant or irrelevant to you, then an enforced schema that rejects your message seems like an
unnecessary hurdle rather than a tool to implement clean design.
HYPOTHESIS THREE
Hypothesis: Java developers are more likely than non-Java developers to have performed API management (i.e., higher-level)
tasks.
Reasoning: The JVM’s powerful “WORA” capability means that Java is more likely than other languages to be used in
heterogeneous environments. In heterogeneous environments, more system boundaries are likely to arise; and where more
boundaries arise, API design and management require more deliberate care. So Java developers are more likely than non-Java
developers to have to spend time worrying about higher-level API management tasks.
To test this hypothesis, we asked: Which of the following primary aspects of API management have you contributed to?
For each answer option shown in Table 7, respondents were allowed to check “contributed ideas,” “implemented,” or both.
Table 7
API creation API discovery API proxy API publication and deployment
1. We think the results somewhat confirmed our hypothesis, but the distribution over specific API management tasks
tells more a more dappled story.Of these API management-related tasks, we selected a subset as “higher-level.” Java
developers were more likely to have contributed ideas to or implemented most of these, as shown in Table 8 below:
Table 8
2. The long, two-dimensional array of responses to this question, plus the additional dimensions offered by segmentation
versus other questions, made analysis of these results at a reasonable intersection size somewhat tricky. We plan to
expand our analysis in future articles.
Future Research
Our survey responses include a great deal of information not discussed in this article. Additional data include:
• Distinctions between primary and secondary (e.g., community support, monetization, issue management) aspects of API
management.
• Discrepancies between how approaches to method parameterization (considered as a specific, low-level, extremely
common aspect of API design) differ in theory and in practice.
• The relative importance of semantic correctness versus contract stability in public and private APIs.
• Free-response evaluations of particular APIs and what makes them good or bad.
Further analyses will be conducted over the coming months and results published on DZone.com. Several of our research areas
would benefit from follow-up analyses at future dates and/or in additional detail. These include:
• Segmentation by further subtype of API (beyond “REST versus any”) and level of abstraction “from the metal.”
API security is at the forefront of cybersecurity. Emerging trends and technologies like cloud-native applications, serverless,
microservices, single-page applications, and mobile and IoT devices have led to the proliferation of APIs. Application
components are no longer internal objects communicating with each other on a single machine within a single process — they
are APIs talking to each other over a network.
This significantly increases the attack surface. Moreover, by discovering and attacking back-end APIs, attackers can often
bypass the front-end controls and directly access sensitive data and critical internal components. This has led to the
proliferation of API attacks. Every week, there are new API vulnerabilities reported in the news. OWASP now has a separate list
of top 10 vulnerabilities specifically for APIs. And Gartner estimates that by 2022, APIs are going to become the number one
attack vector.
Traditional web application firewalls (WAF) with their manually configured deny and allow rules are not able to determine
which API call is legitimate and which one is an attack. For them, all calls are just GETs and POSTs with some JSON being
exchanged.
Anomaly detection (AI, ML) solutions, which rely on large volumes of 100% legitimate traffic, are prone to false positives and
false negatives; cannot deterministically explain why a specific call is “suspicious”; and frankly just cannot be expected to
magically turn any insecure API into a secure one — no matter how poorly designed and implemented.
To solve this problem, companies increasingly turn to the Positive Security model. They define the expected API behavior,
ensure that the definition is strict and detailed enough to be meaningful, test the implementation to conform to the definition,
and then enforce that definition during API use. Any calls outside of what the API expects and any responses outside of what
the API is supposed to return get automatically rejected.
Unlike traditional applications, APIs actually have a way to define their expected inputs and outputs in a standard, machine-
readable model. Specifically, for the most popular type of APIs today — REST APIs — this contract format is OpenAPI. It
originated as the Swagger standard created for documentation purposes and later got adopted by the OpenAPI Initiative
Let’s look at the specific parts of the OpenAPI specification and their role in security.
Note: We will be using the YAML format and OpenAPI version 3 for the examples here, but JSON is equally fine as the format
and one can find similar ways of specifying API behavior in version 2, also known as Swagger.
Paths
API paths are the most basic part of an API definition. Together with the server URL and base path, they document which URLs
API clients should invoke:
paths:
/activation:
...
/books:
...
/books/{id}:
...
Paths are mandatory in OpenAPI contracts and rightly so. Fully documenting all APIs and API paths exposed by your servers
prevents attackers from launching path traversal attacks or finding shadow endpoints: staging, non-production, and legacy, as
described in OWASP API9:2019 — Improper assets management.
Operations
Operations are the HTTP verbs — get , post , put , patch , delete , head , options , and trace — that a path can support.
paths:
/ping:
get:
It is extremely important to document the operations that each path supports and reject anything else.
For example, there are multiple tools that generate quick APIs on top of databases. These can be very convenient for
developers creating front-end user interfaces and thus wanting to get a REST API to write and retrieve back-end data.
This convenience can come back to bite later down the line when an attacker discovers that instead of a GET operation on a
particular path (for example /accounts ), they can send a PUT or even a DELETE , thus actually changing your back-end data on
a path that you intended to be used for read-only.
Another, more subtle example of a vulnerability that originated with operations not getting enforced happened to GitHub in
2019. GitHub’s authentication endpoint was supposed to only expose GET and POST operations. Unfortunately, unbeknownst
to GitHub developers, the Rails framework that they were using also exposed a HEAD operation for each GET . GitHub’s code
was expecting only a GET or a POST and thus had a simple if/else statement, so sending it an unexpected third option led to
unexpected code behavior and an authentication bypass.
Parameters
API operations can have parameters such as:
• Part of the path (e.g., /book/2951 — see example in the paths section above)
• HTTP header
• Cookie
Parameters are not mandatory, and it is not mandatory to describe their format and limits in such detail as we did in the
example above, but it is a very good idea to do so. Locking down strings to their exact pattern — with a strict regular expression
— can save you from potential API8:2019 — Injection attacks. And even without injection, you never know how your back-end
code will react when being sent something outside of the expected range (this happened to the license key API of the Steam
marketplace, causing it to leak thousands of game license keys).
Tl;dr: Document all your parameters and provide as much detail as possible.
Payloads
Both requests and responses may contain data in the body. REST APIs typically use JSON as the format to exchange data.
While not mandatory, it is very much recommended that you strictly describe the schema of such requests and responses (just
like we discussed with parameters above):
/book:
post:
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
isbn:
type: string
pattern: "ISBN\x20(?=.{13}$)\d{1,5}([- ])\d{1,7}\1\d{1,6}\1(\d|X)$"
maxLength:18
quantity:
type: integer
minimum:1
maximum:10
required:
- isbn
- quantity
additionalProperties:false
Note that you should also explicitly specify the type of payload as object and set the additionalProperties value to false .
These prevent additional properties from being inserted into the call.
These extra steps serve as protection against API6:2019 — Mass assignment attacks when a back-end implementation blindly
saves to the database any properties it gets and inadvertently overwrites sensitive fields. This kind of API vulnerability recently
happened to a popular container registry system, Harbor, allowing attackers to make themselves admins by simply including
"has_admin_role":true in the API call to change user profile details.
components:
securitySchemes:
OAuth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://example.com/oauth/authorize
tokenUrl: https://example.com/oauth/token
scopes:
read: Grants read access
write: Grants write access
admin: Grants access to admin operations
And then apply it at any level (the whole API or just a specific operation):
paths:
/user:
post:
security:
- OAuth2: [admin]
As you can also see in the examples above, scopes are natively supported by the standard.
Starting with version 3.1, OpenAPI will also natively support mutual certificate (mTLS) authentication. And there are third-party
extensions that provide further authentication and authorization policies, for example, JWT, which we will discuss briefly below.
Needless to say, authentication and authorization are extremely important to API security. So many APIs are getting hacked
because:
• They were meant to be “internal,” and developers never expected attackers to find a way to get to the network and invoke
them (see recent Mercedes-Benz API hack).
• Authentication was poorly designed and didn’t follow industry best practices (see API2:2019 — Broken authentication,
API1:2019 — Broken object level authorization, API5:2019 — Broken function level authorization).
Transport
In this day and age, you should always encrypt your traffic and use HTTPS rather than HTTP. In OpenAPI version 3, this is
specified by the mandatory protocol prefix in the base API URL:
servers:
- url: https://api.example.com/v1
Use of HTTP opens you up to man-in-the-middle attacks in which your traffic gets intercepted and an attacker pretends to be
your legitimate API consumer. See the recent ASUS and Dell attacks for examples of such flaws.
Developers can use specialized OpenAPI tools or OpenAPI plugins for VS Code, IntelliJ, Eclipse. Additionally, CI/CD pipelines
can include static and dynamic API testing based on OpenAPI contracts. API firewalls and API gateways can enforce Positive
Security based on the contracts, both on external (North-South) and internal (East-West) levels, as demonstrated in Figure 3:
Conclusion
Leveraging the advice from this article, you will be well covered for 95%+ of possible attacks. But realize that OpenAPI is still an
evolving standard and its coverage of API security is also evolving. For example, we already mentioned that up until version 3.1,
mTLS authentication was not something you could describe using OpenAPI, and there are still other aspects not covered out of
the box, like JSON Web Token requirements, control of response headers, rate limiting, and so on.
Luckily, OpenAPI allows you to extend it using your own custom objects and properties. This is something that you can do
yourself or by using custom extensions from the API security or API management vendor of your choice. With API attacks on
the rise, the most effective way to ensure you’re protected is by using a Positive Security model with well-defined, tested, and
enforced contracts throughout the API lifecycle.
It is easy to get lost in the hype and excitement of our technological decisions — which database to use, which dependency
injection framework works best, and which programming language is superior — and lose focus on our goal: Create an
application that most effectively solves a customer’s problem. While languages and tools are an important facet of software
design, they are not the only aspects we must consider.
In the end, our application is only practical if a client can easily access it through the interfaces we define. This requires effective
API design. In this article, we will look at five of the most important principles of effective API design: independence, simplicity,
consistency, error handling, and versioning.
Figure 1
To design our APIs, we must consider what clients will find useful. Some of these facets are specific to a particular domain —
such as using familiar terms — but others are universal.
There are countless other principles that go into effective API design, but these five represent the foundation for creating APIs
that clients enjoy using. To make our APIs useful, we first have to reach the widest audience possible.
Instead, we should always select the most language-agnostic option possible. In the current software environment, that means
favoring choices like REST APIs (preferably using JSON request and response bodies), Advanced Message Queuing Protocol
(AMQP), or even Protocol Buffers (protobuf). Each of these options has implementations in many of the popular languages,
including Java, Python, and Ruby. By abstracting the programming language from the API design, we allow our client to select
which programming language best suits their needs. This flexibility means that more customers can adopt and utilize our APIs.
SIMPLICITY
Simplicity has two major benefits: One for us and one for our clients. The benefit to us is that a simple API usually means less
work on our part — less code, less tests, less room for errors, less development time, and less repetition. The benefit for our
clients is that the code that consumes our API can be simpler — and likely smaller. Similar to our code, the code required to
consume our APIs grows in proportion to complexity of our APIs (not to mention the additional tests and stubs for the client).
To ensure our API is as simple as possible, we should follow a few basic rules:
1. Go with the simpler of two designs unless there is a very compelling reason not to.
2. Use primitives, such as strings and numbers, as values whenever possible and only introduce new data structures when
necessary.
3. Only include information that is needed (i.e., follow the YAGNI principle) — future proofing results in more code to
maintain and a larger API to consume.
CONSISTENCY
As clients use our APIs — especially those that use it frequently — they will begin to pick up on our conventions and come to
expect them throughout the entire API. For example, if we have REST status resource with a key and display name, we can
represent it in numerous ways, including as a nested object:
{
"status": {
"key": "STARTED",
"displayName": "Started"
}
}
{
"statusKey": "STARTED",
"statusDisplayName": "Started"
}
The best option will depend on the context and the nature of the API itself, but whichever we choose, we should stick with it
and use it consistently. Staying consistent reaps some important benefits:
1. Clients know that the common representation means that the resource has the same meaning everywhere it is used.
3. Clients can quickly understand the resource anywhere it appears because they have seen it before.
There are times when we have to break convention and use a different representation, but we should limit those cases to when
we have a strong, compelling reason.
Generally, a useful approach is to categorize an error and then provide details about that specific error. For REST APIs, that
means using HTTP status codes and providing the details of the error in the response body. For message-based APIs, that
means having some error code and some supplemental data — in the header or in the message body — to distinguish which
specific error occurred.
While the error category may seem sufficient, there can be multiple reasons for one type of error. For example, if we return a
401 Unauthorized response from a REST API, the client may not know if the error is due to an incorrect username, incorrect
password, or incorrect session ID. These details are important if we expect our client to handle errors in our API. Therefore, we
must provide pertinent and detailed information about the error (without sacrificing simplicity).
VERSIONING
One of more overlooked aspects of effective API design is versioning. For most projects, it is difficult to see where our API will
be six months, a year, or even five years from now, but it is important to prepare for the future. Eventually, our APIs will evolve
and we will add new features and remove unneeded ones, but we cannot break existing clients. If a client expects a resource
to be available or a message to have a specific format, it would be poor API design to change those existing expectations
(especially without deprecating them first and giving the client time to adapt).
Instead, we need to version our APIs. For REST APIs, we can include some version string (such as v1 ) in the URL:
/api/v1/foo/bar
This allows clients to continue to call /api/v1 , even when version 2 releases, ensuring that the APIs that the customer
depends on remain stable. For message-based APIs, this may mean including a version header that distinguishes one version
of a message from another.
Figure 2
Regardless of the mechanism we choose, it is important to plan for the future and consider the stability of our clients. This
simple addition will go a long way in keeping customers for a long time and reducing their anxiety each time we release a new
version of our APIs.
Conclusion
There are countless, small details that go into making APIs that effectively solve our customer’s problems. This alone can bog
us down in pursuit of a perfect API design. Instead, we should focus on the most important tenets of effective API design —
namely language independence, simplicity, consistency, error handling, and versioning. While not comprehensive, these alone
can dramatically improve our API designs and make our APIs a pleasure to use.
Integration Zone
As software connects the world in more and more complex ways, integration
makes it all possible by facilitating communication among applications.
Learn more about this necessity for modern software development.