<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://apidesignmatters.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://apidesignmatters.org/" rel="alternate" type="text/html" /><updated>2026-04-27T19:40:17+00:00</updated><id>https://apidesignmatters.org/feed.xml</id><title type="html">API Design Matters</title><subtitle>Where I explore API Design and Developer Experience matters large and small, topics around building and running API programs... that is, why API Design Matters. Authored by &lt;a href=&apos;https://davidbiesack.github.io&apos;&gt;David Biesack&lt;/a&gt;.</subtitle><entry><title type="html">Meet Hyrum and Postel</title><link href="https://apidesignmatters.org/2025/11/16/meet-hyrum-and-Postel.html" rel="alternate" type="text/html" title="Meet Hyrum and Postel" /><published>2025-11-16T18:00:00+00:00</published><updated>2025-11-16T18:00:00+00:00</updated><id>https://apidesignmatters.org/2025/11/16/meet-hyrum-and-Postel</id><content type="html" xml:base="https://apidesignmatters.org/2025/11/16/meet-hyrum-and-Postel.html"><![CDATA[<blockquote>
  <p>See how two famous laws interplay with API Design</p>
</blockquote>

<p>Note: Below is an article I originally wrote for Nordic APIs, published as <a href="https://nordicapis.com/meet-hyrum-and-postel/">Meet Hyrum and Postel</a> on December 9, 2020. – djb, Nov 16, 2025</p>

<h2 id="how-do-hyrums-law-and-postels-law-affect-api-designs">How do Hyrum’s Law and Postel’s Law affect API designs?</h2>

<p>Luckily for us humans, and especially that narrow subclass of humans who
build APIs, API design is a field that has not been automated or
botified… yet. Sure, one can point at a database schema and generate
what one can label an “Application Programming Interface.” But it is an
API only in a literal sense — and certainly not in a RESTful one. It
does not provide any of the benefits of designing an API abstraction
layer, such as decoupling your API from the back end. (See Nordic APIs’
<a href="https://nordicapis.com/how-to-build-and-enforce-great-api-governance/">How To Build And Enforce Great API Governance</a>.)</p>

<p>One of the reasons API design is more an art than a science is that
human intelligence is still required to weigh the competing forces that
arise. There are numerous API design cookbooks available, such as
<a href="https://www.oreilly.com/library/view/restful-web-services/9780596809140/">REST API cookbook</a>,
<a href="https://www.manning.com/books/the-design-of-web-apis">The Design of Web APIs</a>
(new
<a href="https://www.manning.com/books/the-design-of-web-apis-second-edition">second edition</a>).
<a href="https://www.manning.com/books/the-design-of-web-apis-second-edition">RESTful Web APIs</a>,
and
<a href="https://pragprog.com/titles/maapis/design-and-build-great-web-apis/">Design and Build Great Web APIs</a>.
These resources offer several
categories and layers of design guidelines that are easy for humans to
understand and apply… less so for an artificial intelligence. The art of
API design lies in weighing and making decisions around those tradeoffs.</p>

<p>Consider two human-centric software design principles which are so
impactful they are better characterized as laws:</p>

<h3 id="john-postels-law">[John] Postel’s Law</h3>

<blockquote>
  <p>TCP implementations should follow a general principle of robustness:
be conservative in what you do, be liberal in what you accept from
others.</p>
</blockquote>

<p>Postel’s Law is so darn useful that it has been generalized away from the narrow realm of TCP implementations as the Robustness Principle:</p>

<blockquote>
  <p>Be conservative in what you send, be liberal in what you accept.</p>
</blockquote>

<p><a href="https://lawsofux.com/postels-law/">Postel’s Law</a> focuses on making
service implementations more robust by allowing for interfaces and
messages to evolve over time. A nice consequence of Postel’s Law is that
it can make APIs easier to use, which we’ll see in a moment.</p>

<h3 id="hyrum-wrights-law">Hyrum [Wright]’s Law</h3>

<blockquote>
  <p>With a sufficient number of users of an API, it does not matter what
you promise in the contract: all observable behaviors of your system
will be depended on by somebody.</p>
</blockquote>

<p>While Postel’s Law
is one of those guardrails that help you design
robust APIs, <a href="https://www.hyrumslaw.com/">Hyrum’s Law</a>, coined by
<a href="https://twitter.com/hyrumwright">Hyrum Wright</a>, is one of those
1,000-foot cliff drop-offs along that narrow, winding, gravel mountain
road. You know, the one without the guardrail. Hyrum’s Law is so
treacherous; it even has an
<a href="https://xkcd.com/1172/">XKCD manifestation</a>.</p>

<p>The problem that our human brains can solve but the robot overlords
can’t (yet) is how to weigh Postel against Hyrum. You probably want
something a little more concrete (unless you’ve already driven over that
cliff, in which case you want something a little more silk-like \ux1fa82;).</p>

<p>Let’s look at some examples.</p>

<h2 id="examples-of-postels-law-in-action">Examples of Postel’s Law in Action</h2>

<p>Example 1: Imagine you have been tasked to build an API for authors to
submit content for publication on Nordic APIs’ site. One API operation
in your “Submissions API” accepts the author’s contact phone number.
With Postel’s Law in mind, you design the API to accept multiple
formats, such as <code class="language-plaintext highlighter-rouge">"(910) 555-1234"</code> or <code class="language-plaintext highlighter-rouge">"910.555.1234"</code> or <code class="language-plaintext highlighter-rouge">"9105551234"</code>. You
also design the API to always return E.164 formatted phone numbers such
as <code class="language-plaintext highlighter-rouge">"+19105551234"</code>. This interpretation of “Be conservative in what you
send, be liberal in what you accept” yields an API that is easier for
clients to use:</p>

<p>Clients can pass phone numbers in multiple formats according to user
input preferences; each client does not have to normalize phone numbers.
API consumers do not have to worry about parsing/supporting various
phone number formats returned in the API’s responses, only one
well-defined format.</p>

<p>Example 2: The Submissions API operation to search submissions has a
query parameter, defined by the
<a href="https://spec.openapis.org/oas/v3.0.2">OpenAPI Specification</a> (OAS) notation:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">parameters</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">published</span>
    <span class="na">in</span><span class="pi">:</span> <span class="s">query</span>
    <span class="na">type</span><span class="pi">:</span> <span class="s">boolean</span>
</code></pre></div></div>

<p>The OAS relies on <a href="https://json-schema.org/">JSON Schema</a> (see
<a href="https://nordicapis.com/7-api-standards-bodies-to-get-involved-with/">7 API Standards Bodies To Get Involved With</a>)
to define the types of properties, parameters, and request bodies. So,
clearly, one can pass <code class="language-plaintext highlighter-rouge">...?published=true</code> or <code class="language-plaintext highlighter-rouge">...?published=false</code>.
However, some client languages don’t use <code class="language-plaintext highlighter-rouge">true</code> and <code class="language-plaintext highlighter-rouge">false</code> tokens for
Boolean values. Python, for example, uses <code class="language-plaintext highlighter-rouge">True</code> and <code class="language-plaintext highlighter-rouge">False</code> instead.</p>

<p>Should one apply Postel’s Law and be liberal in what the API accepts
here, as with the phone numbers? It may be tempting to code the API to
accept <code class="language-plaintext highlighter-rouge">?published=True</code>, <code class="language-plaintext highlighter-rouge">?published=TRUE</code>, <code class="language-plaintext highlighter-rouge">?published=t</code>, or even
<code class="language-plaintext highlighter-rouge">?published=yes</code> and <code class="language-plaintext highlighter-rouge">?published=1</code>. All are possible representations of a “true” value in
various client programming languages. Your implementation framework may
even have a nice utility that can convert all kinds of values into
Boolean values. However, this example and the next show the risks of
adding too much flexibility in input validation.</p>

<p>Example 3: Your API has an operation that accepts a request body schema
with a property, publicationDate. Thus, a valid JSON request would
specify the date as follows:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="err">...</span><span class="p">,</span><span class="w"> </span><span class="nl">"publicationDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2020-12-09"</span><span class="p">,</span><span class="w"> </span><span class="err">...</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<div style="float: right">
One can use more elaborate OAS/JSON Schema constructs to be more liberal
in what the API allows, such as JSON Schema `oneOf` or `anyOf`, or using
`pattern:` instead of `format:`... However, such alternatives obfuscate
APIs, and that's the enemy of clarity and ease of use. Also, not all
client languages and SDKs fully support schemas defiend with
`oneOf`/`anyOf` composition structures.
</div>

<p>Let’s say you are on a Postel’s Law roll and code the implementation to
accept other date formats, such as <code class="language-plaintext highlighter-rouge">"2020/12/09"</code> or <code class="language-plaintext highlighter-rouge">"Dec 09, 2020"</code> for
the date December 9, 2020, to make the API easier to use (ignoring the
fact that <code class="language-plaintext highlighter-rouge">"12/09/2020"</code> is ambiguous). Knowing it is critical to validate
all user input in a pubic API, you find a nice open-source library that
parses dates. But a year later, the team migrates the API implementation
to a new language runtime and, as mart of the migration, chooses to
adopt a <em>new</em> library that also accepts these
formats. Such backend changes should not affect API consumers.
Unbeknownst to you, some clients have been passing dates in
<code class="language-plaintext highlighter-rouge">"09-Dec-2020"</code> format, which the old library supported.
The new framework and library don’t handle this,
nor does it support all the “<em>truthy</em>” values you previously allowed for
the <code class="language-plaintext highlighter-rouge">?published=</code> query parameter. Hyrum’s Law has struck!</p>

<h2 id="api-evolution">API Evolution</h2>

<p>The original intent of Postel’s Law was to account for evolution of the
interface.
(See also Nordic APIs’
<a href="https://nordicapis.com/whats-the-difference-between-versioning-and-revisioning-apis/">What’s The Difference Between Versioning and Revisioning APIs?</a>.)
Examples of evolution in the API space include adding new properties to
a JSON schema. This is a core principle of “good” REST APIs: the service
and clients should be free to evolve (in a compatible manner)
independently of each other. For example, the first release of the
publishing API may allow passing only the title and publication date
properties:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Meet Hyrum and Postel"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"publicationDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2020-12-09"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>A new release of the service may add a new <code class="language-plaintext highlighter-rouge">revision</code> property, so requests may look like:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Meet Hyrum and Postel"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"publicationDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2020-12-09"</span><span class="w"> </span><span class="p">}</span><span class="w">
  </span><span class="nl">"revision"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2020-10-28"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>A robust service would allow this request (even in the first release!)
by ignoring (and perhaps logging) properties that it does not recognize,
rather than treating them as an error. Clients who consume such
responses should also be lenient in what they receive. A client built
for the first release of an API should not fail if it connects to the
newer release of the API that includes new properties.</p>

<p>One consequence of API design that Postel’s Law tells us:</p>

<p><img src="/assets/img/no-robustness-for-you.png" alt="The Soup Nazi says &quot;No Rubustness For You!&quot;" /></p>

<blockquote>
  <p>When defining JSON Schemas for our APIs, avoid using
<code class="language-plaintext highlighter-rouge">additionalProperties: false</code>. Doing so slams the door in John Postel’s
face!</p>
</blockquote>

<p>Hyrum’s Law states that all observable behaviors of your system will be
depended on by somebody. This includes behaviors that are not explicitly
accounted for in the API design or documentation, such as the
“09-Dec-2020” date format above. If one considers an API definition to
be a software contract, then Hyrum’s Law means consumers have found (and
depend on) loopholes in that contract. Industry veterans are all
familiar with a customer who has come to rely on buggy behavior, which
they quickly learn about only after releasing a bug patch!</p>

<h2 id="hyrums-law-and-api-evolution">Hyrum’s Law and API Evolution</h2>

<p>APIs must evolve over time. Hyrum’s Law tells us that such change will
be painful. Imagine you did not provide an OpenAPI definition with your
first Submission API releases, but you chose to add it after several
requests from consumers. You describe the publicationDate string
property and its need to represent a date value:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">publicationDate</span><span class="pi">:</span>
  <span class="na">description</span><span class="pi">:</span> <span class="s">The intended publication date of the submission.</span>
  <span class="na">type</span><span class="pi">:</span> <span class="s">string</span>
  <span class="na">format</span><span class="pi">:</span> <span class="s">date</span>
  <span class="na">example</span><span class="pi">:</span> <span class="s2">"</span><span class="s">2020-12-09"</span>
</code></pre></div></div>

<p>Hyrum’s Law also means pain here. An API design that adheres strictly to
the OpenAPI Specification and JSON Schema validation does not always
allow for the “be liberal in what you accept” clause of Postel’s Law.</p>

<p>JSON Schema tells us that a string with the date format must follow the
RFC 3339 “MMMM-DD-YY” format. API frameworks and libraries based on OAS
and JSON Schema may not allow input that does not pass strict JSON
Schema validation.</p>

<p>In effect, this design choice imposes a stricter constraint on the API.
Other formats that users have come to depend on are not allowed. To
maintain compatibility, you are forced to abandon the use of format:
date for the property to maintain your kinship with Postel’s Law. (With
luck, you find out before you publish the OAS API definition.) But to
guard against Hyrum’s Law, you need to specify all the allowed date
formats.</p>

<p>Another example of Hyrum’s Law wreaking havoc would be a client that passes:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"NordicAPIs"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"publicationDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2020-12-09"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"revision"</span><span class="p">:</span><span class="w"> </span><span class="mi">25</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>to the above publishing example. Perhaps because they are reusing a
response from another API that includes a <code class="language-plaintext highlighter-rouge">revision</code>, and they simply
don’t remove it before calling your Submissions API. This behavior was
allowed in the first release, and perhaps the client even comes to
depend on this behavior. However, once the service adds a revision
property with <code class="language-plaintext highlighter-rouge">type: string</code> (or any non-numeric type), that client
request will cause an error in the Sumissions API. Something as simple
as adding a new property can break existing consumers!</p>

<p>Unfortunately, there are many such ways that API evolution can have such
ill effects: adding a value to an enum list or changing the <code class="language-plaintext highlighter-rouge">maxLength</code>
of a string from 80 to 100 may break a consumer. Even changing the HTTP
response code for an erroneous call from 400 to a more specific 422 will
change an “observable behavior.”</p>

<p>I highly recommend Gareth Jones talk, Your API Spec Isn’t Worth the
Paper It’s Written
On](https://nordicapis.com/sessions/your-api-spec-isnt-worth-the-paper-its-written-on/),
presented at Nordic API Austin Summit 2019. Gareth points out many ways
that even small changes in APIs or their implementations can break
clients.</p>

<h2 id="balancing-postel-and-hyrum-in-practice">Balancing Postel and Hyrum in Practice</h2>

<p>The main impacts of Postel’s and Hyrum’s laws arise: To prevent
unintentional dependencies on unspecified data and behavior, the API
definition would need to do the following:</p>

<ol>
  <li>Enumerate all the variations on how developers will use it, such as
  listing all allowed formats of all input and all possible API call
  sequences. The goal is to turn the API software contract into an
  “iron-clad contract” and remove all loopholes.</li>
  <li>Disallow any input that
  deviates from the new, strict API definition — even “harmless”
  ones. This must start with the first release by explicitly failing
  operations and data outside the API contract. Thus, no client can come
  to depend on those behaviors. Clearly, with any non-trivial API, it is
  impossible to do either! Even listing only common variations can add
  significant bloat to the API definition. Unfortunately, larger, more
  verbose API definitions are harder to use compared to concise API
  definitions. They also add significant cost to the implementation,
  including developing exhaustive, comprehensive regression tests.
  Avoiding the cliff of Hyrum’s law is at odds with Postel’s Law of being
  liberal in what you accept. Trying to follow both means giving up easy
  to understand, concise APIs, or it locks you into a backend that cannot
  evolve.</li>
</ol>

<p>The ultimate artful engineering solution is to be aware of both laws and
weigh them in each API design decision. One tactic is to set reasonable
expectations with your consumers about API evolution and change. Don’t
be an automaton when it comes to API design. Instead, use your
experience and intelligence to design APIs that respect the boundaries
laid down by Hyrum and Postel and which can evolve as your API
consumers’ needs change.</p>

<hr />

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><category term="the-language-of-api-design" /><summary type="html"><![CDATA[See how two famous laws interplay with API Design]]></summary></entry><entry><title type="html">The Reality of API programs</title><link href="https://apidesignmatters.org/2025/11/16/the-reality-of-api-programs.html" rel="alternate" type="text/html" title="The Reality of API programs" /><published>2025-11-16T18:00:00+00:00</published><updated>2025-11-16T18:00:00+00:00</updated><id>https://apidesignmatters.org/2025/11/16/the-reality-of-api-programs</id><content type="html" xml:base="https://apidesignmatters.org/2025/11/16/the-reality-of-api-programs.html"><![CDATA[<p><a href="https://www.linkedin.com/in/shaneopenapi">Shane O’Conner</a>
(Founding Team @ Scalar ) has started a  Q&amp;A series on LinkedIn called
<em>Behind The API</em>. Shane graciously asked me to participate, and also
allowed me to re-publish the content here. Below is Shane’s initial
announcement of the Q&amp;A, followed by the full content.</p>

<h2 id="introduction">Introduction</h2>

<p>Below is Shane’s first
<a href="https://www.linkedin.com/feed/update/urn:li:activity:7393950763816742912/">LinkedIn announcement on Nov 11, 2025</a>,
sharing
the <a href="https://www.linkedin.com/feed/update/urn:li:activity:7393950763816742912/"><em>Behind The API featuring David Biesack</em></a> article:</p>

<blockquote>
  <p>I’ve been thinking a lot about what “mature API strategy” actually means as we build Scalar.
So I did what any sane person would do: tracked down someone with
“Chief API Officer” in their title and asked him everything.</p>
</blockquote>

<blockquote>
  <p><a href="https://www.linkedin.com/in/davidbiesack/">David Biesack</a> spent some time walking me through the reality of API programs - not just the highlights, but the actual messy, cultural, people-first work.</p>

  <p>A few things that come up;</p>

  <p>The “API-first” paradox: APIs can’t come first. The business problem does. But once you solve that, APIs become the unified way you deliver your entire business value. That mindset shift changes everything.</p>

  <p>Governance = velocity: I’ve always known this, but hearing David explain how standards like OAuth2 and OpenID Connect are precisely what enable speed (not constrain it) reframed the whole governance conversation for me.</p>

  <p>The people problem: API maturity isn’t a tech problem. It’s culture. It’s convincing people that “API as a Product” means something fundamentally different than “we have APIs.”</p>

  <p>If you’re working in APIs, developer tools, or platform strategy—I think you’ll find something useful here.</p>

  <p>Enjoy!</p>

  <p>* if you’d like to partake in my interview series, please let me know. Would love to chat with as many of you as possible.</p>

  <p><a href="https://www.linkedin.com/search/results/all/?keywords=%23behindtheapi&amp;origin=HASH_TAG_FROM_FEED">#BehindTheAPI</a></p>
</blockquote>

<p><img src="/assets/img/behind-the-api-with-david-biesack.png" alt="alt text" />
<br /><em>(Image by Shane O’Conner, used with permision)</em></p>

<p>The remainder of this API Design Matters article is a full reprint of
Shane’s full
<a href="https://www.linkedin.com/pulse/behind-api-david-biesack-shane-o-connor-uyjme/?trackingId=G6o0aPqkR0qaGJRTYgL6gA%3D%3D">Behind The API</a> article, courtesy of Shane (Thanks, Shane!):</p>

<h2 id="behind-the-api-with-david-biesack">Behind the API with David Biesack</h2>

<p>An interview with David Biesack, who is Chief API Officer at Apiture (now part of CSI).</p>

<p>* all views expressed are his own and are not of his employer</p>

<p>Shane: Most people don’t wake up dreaming of being a ‘Chief API Officer.’ Walk me through how this role came to be at Apiture - was it reactive to chaos or proactive vision?</p>

<p>David: This was a proactive move that I suggested to Apiture executives as the API program matured and began to realize its potential and impact. “API” was in the founding DNA of the company, so it was not a hard sell that APIs merited guidance and governance and quality controls—and ultimately responsibility. We could establish the role, or it we could partition it out and dilute it amongst other roles, to the risk and detriment of all. So yes, proactive against chaos.</p>

<p>Shane: You lead Apiture’s ‘API First’ initiative. For folks who think that just means ‘we have APIs’- what does TRUE API-first actually look like in practice? What are the non-negotiables?</p>

<p>David: APIs exist within a business context, so APIs can’t come first — the problems and needs of the user and the business capabilities come first. APIs are just part of a technical solution to the business problems, so APIs come after fully understanding the business domain and its problems. They are the vehicle for accessing the core capabilities, so they must be shaped based on how users want to consume those capabilities. If the API came first, it would not align with the desired outcomes. So, the non-negotiable is accepting that APIs are part of a larger ecosystem. People who work on APIs must rely on others—the domain experts, the customers, product managers and business analysts and strategists—to tell them what needs to be solved before taking any “how” first steps with building an API
Secondly, a true API First mindset means the API solution is the primary tool in the business’ toolbelt for gaining access to the domain. Rather than implementing five competing access methods (and differing authorization management, etc) to your business capabilities, focus on APIs as the first and foremost way of exposing those features to all consumers, internal and external. This unifying theme brings tremendous power, more secure solutions, and faster business agility.”</p>

<p>Shane: What’s the hardest part about instilling an API-first mindset in an organization? Is it technical, cultural, or something else entirely?</p>

<p>David: It is definitely culture — one can’t instill a mindset with technology (I’m not gonna let anyone put a chip in my brain). Many people talk about “API as a Product”, and I think grasping that idea is the largest hurdle: One of the hardest things to understand is that providing a unified way for others to access your business’ data and processes requires a newer, deeper way of thinking what your product is. It forces people to think what is the true value of your business, and realizing that it does not have to be packaged up in some older, rigid, legacy, monetized widget, but that by enabling your capabilities through APIs, you can really understand the value your company provides, then make it available to more partners and markets.
For many, holding onto a UX-first mindset (and the business analysis tools that lock them into that mindset) is what holds them back. I get it — comfort, momentum, familiarity are hard things to let go. But when they shift to an API-first mindset, it clicks and it becomes very freeing and powerful for all parties, and this leads to accelerated success.”</p>

<p>Shane: Let’s talk API governance - it’s one of those things everyone nods about but few do well. How do you think about the balance between enabling developer velocity and maintaining standards?</p>

<p>David: This one is relatively easy to position, because standards are precisely what enable productivity and deliver velocity. Imagine how slow you would be if you also had to take time to invent, implement, and harden a new authorization protocol instead of relying on standards such as OpenID Connect and OAuth 2? Reality Check: no existing libraries, frameworks, tools, agents or infrastructure would integrate with your non-standard API. Who would consume your API if it were not built upon the standards that all developers know and expect
API Governance is all about managing risk—reducing risk and enabling velocity by following standards, so teams can focus on getting their unique capabilities right, rather than re-implementing the API “chrome” of HTTP or JSON or OAuth2 or encryption or inventing a new protocol that no one else understands.
The other dimension of your question is balancing developer creativity vs. following standards. I spoke about this at my talk at the Nordic APIs Austin API Summit in 2024.</p>

<p>Shane: You talk about ‘APIs as a Product’ - what does that mindset shift mean in practical terms? How does it change how you build, document, and support APIs?</p>

<p>David: I hinted at this above… There is a spectrum of engagement in APIs as a Product. The most trivial (and least useful) is the “widget” approach to commoditizing and commercializing digital products, as done with any product. The other extreme is full buy-in throughout the organization to “API all the things”, to rephrase your main business value as digital capabilities that are available via APIs and which allow innovation and growth by inviting other organizations to partner with you. This is a monumental shift, because it requires a significant investment in doing it right — getting security right, getting consistency and evolution right, aligning teams on a strategic vision, addressing Developer Experience. For the business, seeing APIs as part of the innovation chain, as part of what brings your business’ value to customers, shifts it from being an expense sink to a growth product.</p>

<p>Shane: Developer Experience is core to your role. What are the most common DX sins you see API teams commit? And what separates a ‘good enough’ API from a genuinely great one?</p>

<p>David: I think the most common mistake is for engineers to not think like their API consumers. This applies to so many aspects, from using internal jargon, to making unstated assumptions about intimate internal knowledge about how things work, to missing the core abstractions and concepts that consumers think about… or simply not answering (in the API design, or in the accompanying documentation) the important questions that developers needs to know about your API.
My goal is to make APIs a joy to work with. If you have ever worked with a library that “thought” the way you did and which made it a breeze to use, vs. a highly opinionated competing library that incurred mental load that was all friction and confusion, then you know joy vs. agony.
“Good enough” is an API that allows solving the obvious problems, whereas a Great API and corresponding developer experience are truly expressive, adaptable, intuitive, flexible, simple, composable, and comprehensible, yet highly usable. They allow solving the 20% obvious use cases as well as the 80% harder use cases. Of course, the risk is making the API too general, too complex, too abstract, so it does everything poorly but does nothing well. Never trade simplicity and directness for overly abstracted “elegance”. Ever try to program an actual Turing Machine? Sure, it can perform any computation, but at what cost to Developer Experience? DX means delivering the right abstractions based on the API consumer’s conceptual model, not an API coupled to some elegant platform design that they don’t care about.”</p>

<p>Shane: When you think about your external developer partners using Apiture’s open banking APIs, what metrics or signals tell you the developer experience is working?</p>

<p>David: We have the great fortune of working with a world-class Support team and an equally stellar Customer Success team, so we get great (and fast) feedback from partners through them. Our company mantra has always been to “Treat every customer like they were your only customer”, so that leads directly into seeking and accepting great feedback. We hear it when someone can’t achieve their goals, and also when they do succeed</p>

<p>Shane: What’s your philosophy on API versioning and evolution when you have that many partners depending on your APIs? How do you ship new capabilities without breaking things?</p>

<p>David: Joshua Bloch wrote, “Public APIs, like diamonds, are forever.” I once gave a talk on API evolution and backwards compatibility at SAS, where I took a SAS program from the 1976 SAS Manual and ran it on the most recent version of SAS — and it worked, unchanged, 40+ year later. That’s my goal with APIs— design for evolution by building in enough extensibility to allow for the system to change. We’ve done a great job of this, by understanding and anticipating how a system can or will change, and guiding partners along the way. We’re lucky enough to be able to build and validate our APIs alongside our front-end mobile and web and system applications, to get early enough feedback. But just as I mentioned the API First myth above, we also push back heavily on the product team to get firm commitments about what can change in the future. For example, cardinality is always a critical aspect of API design, so whenever we get a requirement for one of this, or two of that, we always push back and design things with arrays to allow future evolution, or use arrays of objects rather than arrays of strings, to allow the data to evolve in multiple dimensions.</p>

<p>Shane: CSI just acquired Apiture, and the press release specifically called out your ‘API-first platform’ and ‘API-driven flexibility’ as key value drivers. That’s not typical M&amp;A language. What do you think that signals about where API strategy fits in the broader fintech landscape?</p>

<p>David: I’m heartened to hear this, certainly. I hope this bodes well for the broader industry. There is certainly a lot of activity and change in the industry, but APIs are here to stay, especially with the growth of AI agents. By being thoughtful and by recognizing the growth enabled by partnerships built on APIs, others will also position APIs as an crucial dimension of their portfolio. And investment firms etc. will be looking at API enablement and robust API governance and developer experience as hallmarks of mature, valuable companies.</p>

<p>Shane: Who are some other API leaders or companies doing interesting work in this space that you admire or learn from?</p>

<p>David: Top of mind is Matthew Reinbold. I appreciate his thoughtful analysis and consistent reminder that most of our industry problems (especially those around API Governance) are people problems, not technology problems. We also learn from the past, and his work on software forensics is so valuable and intriguing</p>

<p>I’ll attend a keynote or talk by Mike Amundsen any chance I get.</p>

<p>I also admire Kin Lane , of course, as he has established a long record of telling stories about API success and for building and inspiring our community around the people behind the APIs.”</p>

<p>Shane: Last one - if someone’s reading this and thinking about how to mature their own API program, what’s your advice on where to start?</p>

<p>David: There is no reason to jump into this alone. I feel lucky to be involved with such a great community of passionate people who want to help each other. When you can, attend conferences and make yourself known. Don’t be shy, because everyone is helpful and wants to see their peers succeed. Participate to the extent you can — even sign up to present at an API conference</p>

<p>One of my favorite quotes, attributable to Richard Feynman:
“If you want to master something, teach it!”.</p>

<p>I hope you enjoyed the article. Thank you again Shane for this and other
<a href="https://www.linkedin.com/search/results/all/?keywords=%23behindtheapi&amp;origin=HASH_TAG_FROM_FEED">#BehindTheAPI</a>
content. I hope all my readers will check it out - there’s
lots of great content there — please read!</p>

<hr />

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Shane O’Conner (Founding Team @ Scalar ) has started a Q&amp;A series on LinkedIn called Behind The API. Shane graciously asked me to participate, and also allowed me to re-publish the content here. Below is Shane’s initial announcement of the Q&amp;A, followed by the full content.]]></summary></entry><entry><title type="html">Provenance</title><link href="https://apidesignmatters.org/2025/06/15/provenance.html" rel="alternate" type="text/html" title="Provenance" /><published>2025-06-15T18:00:00+00:00</published><updated>2025-06-15T18:00:00+00:00</updated><id>https://apidesignmatters.org/2025/06/15/provenance</id><content type="html" xml:base="https://apidesignmatters.org/2025/06/15/provenance.html"><![CDATA[<blockquote>
  <p>Origins of API Design Matters</p>
</blockquote>

<p>I started API Design Matters in early 2023 (if you’ve been reading since
then, <strong><em>Thank You!</em></strong>), but the idea goes back much further.</p>

<p>Back in the mid 90’s (yeah, I’ve been around a while…) I was deep into
that new “Java thang”. In June 2025, Emmanuel Paraskakis shared slides from
a 2007 talk Joshua Bloch had given, titled
<a href="https://www.linkedin.com/feed/update/urn:li:activity:7334632906079776768/">How to Design Good APIs, and Why it Matters</a>. I had seen a version of this talk in my Java years at a
conference, and I had the pleasure of working with Java API design
experts like Josh Bloch and Doug Lea as they built out the Collection
framework (lists, maps, etc) for Java 2 in the early days. The title of that talk lodged
itself in the back of my brain, almost as much as the content of the
talk, and both were a large part of why I created <em>API Design Matters</em>…
and why I named it as I did.</p>

<p><img src="/assets/img/Provenance.png" alt="alt text" /></p>

<p>Josh and Doug and others were gracious and accepted a lot of input from
the younger me, and answered my questions about the emerging design of
Java’s Collection framework. Those conversations are lost to time, but I
do remember their impact. A specific example I recall from the early Java
Collection API design discussions centered on the collection interfaces’
<code class="language-plaintext highlighter-rouge">isEmpty()</code> query function, which returns <code class="language-plaintext highlighter-rouge">true</code> if the collection was
empty (had no items), <code class="language-plaintext highlighter-rouge">false</code> if not. I asked about the need for such a function, since
the collections already had a <code class="language-plaintext highlighter-rouge">length()</code> function. It seemed unnecessary
to add a <code class="language-plaintext highlighter-rouge">collection.isEmpty()</code> method because a client could trivially
use <code class="language-plaintext highlighter-rouge">(collection.length() == 0</code>). However, Josh kindly pointed out that,
with so many different/possible collection implementations, the <code class="language-plaintext highlighter-rouge">length()</code>
function may be expensive to compute. For example, for a linked list,
computing <code class="language-plaintext highlighter-rouge">linkedList.length()</code> is <code class="language-plaintext highlighter-rouge">O(n)</code> (where <em>n</em> is the number of items in the list),
not <code class="language-plaintext highlighter-rouge">O(1)</code>, whereas the implementation of <code class="language-plaintext highlighter-rouge">linkedList.isEmpty()</code>
function for a linked list is trivially <code class="language-plaintext highlighter-rouge">O(1)</code>.
While API composability is nice, it may come at the cost of performance.</p>

<p>Many of the practices and pragmas Josh shared then, as well in his InfoQ
article,
<a href="https://www.infoq.com/articles/API-Design-Joshua-Bloch/">“Bumper-Sticker API Design”</a>,
stuck with me because they also apply to Web API design.</p>

<p>The one principle I have shared the most:</p>

<blockquote>
  <p>Public APIs, like diamonds, are forever.”</p>

  <p>— Joshua Bloch</p>
</blockquote>

<p>When I worked at SAS, I shared an example of this principle several
times when discussing API design. As late as 2017, I would show examples
of small SAS programs from the 1976 SAS manual, and the programs
continued to work unaltered in the SAS System of 2017. Backwards
compatibility is as critical to the longevity of an API as it is to a
programming language/platform.</p>

<p>Josh also wrote:</p>

<blockquote>
  <p>If there is a fundamental theorem of API design, this is it … Every
facet of an API should be as small as possible, but no smaller. You
can always add things later, but you can’t take them away. Minimizing
conceptual weight is more important than class- or method-count.</p>
</blockquote>

<p>Obviously, design forces often oppose on another. The collection
interface footprint would be smaller without an <code class="language-plaintext highlighter-rouge">isEmpty()</code> function, but
the negative impact of omitting it is offset by the benefit of including
it.</p>

<p>Another important aspect of <em>API Design Matters</em> provenance that I wish
to share is that none of the text in <em>API Design Matters</em> was generated
by AI. (I did try AI for one image and I doubt I’ll do that again
because the result was so awful). But I have never used an AI to draft,
write, or rewrite my posts—It’s all me. It always will be.</p>

<p>I wish to acknowledge and thank Josh Bloch and Doug Lea and others who taught me so much.</p>

<p>Who has inspired your work with APIs? Let me know in the comments.</p>
<hr />

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Origins of API Design Matters]]></summary></entry><entry><title type="html">API Design Antipattern: Leaky Abstractions</title><link href="https://apidesignmatters.org/2025/06/03/api-design-antipattern-leaky-abstractions.html" rel="alternate" type="text/html" title="API Design Antipattern: Leaky Abstractions" /><published>2025-06-03T18:00:00+00:00</published><updated>2025-06-03T18:00:00+00:00</updated><id>https://apidesignmatters.org/2025/06/03/api-design-antipattern-leaky-abstractions</id><content type="html" xml:base="https://apidesignmatters.org/2025/06/03/api-design-antipattern-leaky-abstractions.html"><![CDATA[<blockquote>
  <p>Pro tip: Do not let internal implementation constraints leak into your API</p>
</blockquote>

<p>In this edition of <em>API Design Matters</em>, I will discuss an API design
practice that I recommend avoiding — leaking internal implementation
details into the API design. This does not fit the original definition
of an <em>antipattern</em><a id="footnote-1-ref"></a><a href="#footnote-1"><sup>1</sup></a>
but I’m going to use that term anyway and call <em>Leaky
Abstractions</em> an <em>API Design Antipattern</em>.</p>

<p><img src="/assets/img/API-Design-Anitipattern-Leaky-Abstractions.png" alt="alt text" /></p>

<blockquote>
  <p>Welcome to the next article in <a href="/api-design-patterns"><em>API Design Patterns</em></a>
series.</p>
</blockquote>

<p>Exposing internal implementation details in an API design has negative consequences:</p>

<ol>
  <li>If the API design is too coupled to the underlying system, changes to
that internal system likely will require changes to the API, which in
turn can disrupt the API’s clients and consumers.</li>
  <li>Such detail often reflects cultural, historical, technical and other
influences that pertain to the engineering team, requirements, system
and other constraints for a different scenario or problem set than
the API. As such, the internal implementation decisions may not
address the needs of the API. For example, databases are often designed
to optimize for certain access patterns of the system or application
they were originally built to support. Such patterns may be very
different for an API that is designed to use that data at a later
time.</li>
  <li>Internal system design often uses jargon or concepts that are
unrelated to the conceptual model that your API consumers have of
your system. This impedes adoption of your API.</li>
</ol>

<p>Thus, one should avoid letting the internal system design leak into the API in order to create and maintain an API abstraction that fits the API consumer’s needs. Don’t sacrifice API usability just to facilitate expediency in the API implementation.</p>

<p>(Corollary: avoid generating an API directly from a database schema.)</p>

<p>Here is a more concrete example. I recently saw the following construct
in a third party API (I renamed the schema to keep the vendor anonymous,
but I did not change the enum names.)</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
components:
  schemas:
    CommunicationMethod:
      title: Communication Method
      enum:
        - FAXI
        - EDIC
        - URID
        - EMAL
        - POST
        - SMSM
      type: string
</code></pre></div></div>

<p>Unfortunately, the schema that defines these enum values does not define
what these values mean… this is understandable, since OpenAPI and JSON
Schema do not provide a specific notation for describing what each
enumeration in an enum list means. Still, a better developer experience
calls for a description that tells the reader what each of these values
means.</p>

<p>In this case, the descriptions of these values appear <em>elsewhere</em> in the
OpenAPI source file, in the description of a property that is
constrained by the schema. If this schema is needed elsewhere, it is
likely the API author would either not describe the values at all or,
more likely, follow the existing code pattern and duplicate this verbose
description. The result would be fragile — if the API needed a new value
in the list, this would require updating multiple descriptions in the
API definition. This violates the <strong>Don’t Repeat Yourself (DRY)
Principle</strong>, which I’ve discussed before:</p>
<blockquote>
  <p><a href="/2023/04/09/dont-repeat-yourself-when-designing-apis">Don’t Repeat Yourself When Designing APIs</a>)</p>
</blockquote>

<p>However, this <strong>WET</strong> (“Write Everything Twice”) design is not the real
API design antipattern I want to discuss. Instead, it is the <strong>names</strong> of
these enumerated strings that strike me as a leaky abstraction. Here is
the definition of the property which uses this schema:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="na">properties</span><span class="pi">:</span>
        <span class="na">method</span><span class="pi">:</span>
          <span class="na">$ref</span><span class="pi">:</span> <span class="s1">'</span><span class="s">#/components/schemas/CommunicationMethod'</span>
          <span class="na">description</span><span class="pi">:</span> <span class="pi">&gt;-</span>
            <span class="s">The method used to deliver the the status to the originator.</span>
            <span class="s">- `EMAL` - Email</span>
            <span class="s">- `URID` - URI (HTTP URL or similar)</span>
            <span class="s">- `POST` - Postal services</span>
            <span class="s">- `SMSM` - Short Message Service (SMS)</span>
            <span class="s">- `FAXI` - FAX</span>
            <span class="s">- `EDIC` - Electronic Data Interchange</span>
</code></pre></div></div>

<p>Unfortunately, this API appears to leak some internal implementation
constraints — perhaps this format is required by a separate pre-existing
back end service, or some internal communication protocol, or perhaps
even a database table where only 4 characters are allowed and EMAIL
would not fit. However, there is no need to let such internal
constraints affect the API design by constraining these enum strings to
four characters with reduced readability and diminished self
description.</p>

<p>The purpose of an API is to provide an abstraction of the underlying
service. That abstraction should be expressed in terms the API consumer
can use and understand, not just what is convenient for the implementor.
The goals of the API designer—and implementor—should be to do the hard
work to make the API easier to learn and use.</p>

<blockquote>
  <p>The goals of the API designer—and implementor—should be to do the hard
work to make the API easier to learn and use.</p>
</blockquote>

<p>The above example highlights several issues which decrease the API
usability. For example:</p>

<p>I believe <code class="language-plaintext highlighter-rouge">EMAIL</code> would be much better than <code class="language-plaintext highlighter-rouge">EMAL</code>. Why decrease
readability and increase cognitive load by removing just one letter? The
abbreviated spelling reduces one’s ability to discuss (talk about) the
API - i.e. one cannot simply mention EMAIL in a conversation and have it
be easily understood - one might even have to spell it out E-M-A-L to
avoid miscommunication.</p>

<p>Why add an <code class="language-plaintext highlighter-rouge">I</code> to <code class="language-plaintext highlighter-rouge">"FAX"</code>, or add <code class="language-plaintext highlighter-rouge">C</code> to <code class="language-plaintext highlighter-rouge">"EDI"</code> (Electronic Data Interchange) or
add an <code class="language-plaintext highlighter-rouge">M</code> to <code class="language-plaintext highlighter-rouge">"SMS"</code> Short Message Service (SMS) or add a <code class="language-plaintext highlighter-rouge">D</code> to <code class="language-plaintext highlighter-rouge">"URI"</code> — just
to make them all 4 character strings?
The terms FAX, EDI, SMS and URI
are well-known, recognizable names; adding extra characters to them only
obfuscates them, especially when the given definitions do not explain
why those extra characters are there:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">SMSM</code> - Short Message Service (SMS)</li>
  <li><code class="language-plaintext highlighter-rouge">FAXI</code> - FAX</li>
  <li><code class="language-plaintext highlighter-rouge">EDIC</code> - Electronic Data Interchange</li>
  <li><code class="language-plaintext highlighter-rouge">URID</code> - URI (HTTP URL or similar)</li>
</ul>

<p>I don’t know the origin of these names, but I suspect they came directly
from implementation code. However, this semantic gap between the names
and what they represent only <em>increases API friction</em>. There is no
justification given here for why these enum values are named as they are
(perhaps because there is no good rationale). The API design only makes
consumers pause and ask “Why?”. When this happens, the API design detracts
from the API’s purpose and becomes a pointless distraction.</p>

<p>Your API design should anticipate and answer the domain questions your
consumers may have; it should not raise additional questions in their
minds; nor should reading or using the API be frustrating.
In other words:</p>

<blockquote>
  <p>APIs should help you solve your problems. APIs should not be your
problem.</p>

  <p>-<a href="/2025/04/22/the-api-team-mantra">The API Team Mantra</a>:</p>
</blockquote>

<p>A useful tip is to <em>always look at your API design from the perspective
of someone who has never seen your system before and does not have the
same institutional knowledge that your API team has</em>.</p>

<hr />

<p><a id="footnote-1"></a><a href="#footnote-1-ref"><sup>1</sup></a>
Martin Fowler defines antipattern as “something that seems like a good idea when you begin, but leads you into trouble. Since then the term has often been used just to indicate any bad idea, but I think the original focus is more useful.”
I’m using the latter interpretation of the term.</p>

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><category term="api-design-patterns" /><summary type="html"><![CDATA[Pro tip: Do not let internal implementation constraints leak into your API]]></summary></entry><entry><title type="html">The API Team Mantra</title><link href="https://apidesignmatters.org/2025/04/22/the-api-team-mantra.html" rel="alternate" type="text/html" title="The API Team Mantra" /><published>2025-04-22T18:00:00+00:00</published><updated>2025-04-22T18:00:00+00:00</updated><id>https://apidesignmatters.org/2025/04/22/the-api-team-mantra</id><content type="html" xml:base="https://apidesignmatters.org/2025/04/22/the-api-team-mantra.html"><![CDATA[<blockquote>
  <p>200 is Not OK</p>
</blockquote>

<p>In April 2025, I
<a href="https://www.linkedin.com/posts/davidbiesack_the-mantra-of-a-good-api-program-manager-activity-7315537628420845569-t49X?utm_source=share&amp;utm_medium=member_desktop&amp;rcm=ACoAAAfzL5sBDSFE339Qa5vhQeVWS39Vc_HFFkU">posted on LinkedIn</a>:</p>

<blockquote>
  <p>The mantra of a good API Program Manager/Product Manager/Developer Advocate:</p>

  <p>APIs should help you solve your problems. APIs should not be your problem.</p>

  <p>— David Biesack</p>
</blockquote>

<p>Today, I want to break this down and discuss <em>API Success</em>.</p>

<p><img src="/assets/img/API-team-mantra.png" alt="alt text" /></p>

<blockquote>
  <p>Welcome to the next article in <em>The Language of API Design</em> series.
Rather than jumping into the middle of this series, I encourage new
visitors start by reading
<a href="/the-language-of-api-design">The Language of API Design</a>
and scanning previous posts in the series.</p>
</blockquote>

<p>As I’ve stated multiple times in podcasts where I’ve been a guest, the most important
measure for API success is if it is solves real problems — if developers can use your API
to build their applications. This means the API must be fit for purpose. I won’t be
successful sending a text message to someone if I try to use the Amazon Web Services S3
cloud storage API, and I will find the Tenth Level of Hell if I try to upload a PDF of a
Platinum Checking Account Terms and Conditions document, March 2025 revision, using the
Twillio API.</p>

<p>Of course, to obtain this highest level of success, someone has to be able to find (i.e.
discover) your API. This normally means being able to find it in an API registry (alas,
<a href="https://apievangelist.com/2022/10/15/programmableweb-is-shutting-down/">ProgrammableWeb.com is no more</a>),
or find it through a search service (Google, Bing, Ask Jeeves!, pick your poison), as long
as the API is on a web site that can be indexed by search services. (Pro tip - don’t put
your API documentation behind a paywall or require registering and logging in to see the
API documentation.) You may even try the AI chatbot of your choice to find the API that
solves your problem, but for that to work, the AI engine needs to be able to see the API
doc too… that’s not likely if the API doc is not easily available.</p>

<p>Either way, success in finding the right API requires that 1) the API be discoverable, and
that 2) the API documentation clearly describes what the API does using the terms the
potential consumer understands. I’ve seen way too many APIs described with woefully
inadequate documentation. This often stems from technical people documenting the API “from
the inside out” - i.e. describing how the system behind the API was designed (at one point
in time…), or using internal code names or marketing terms, rather than documenting the
API from the perspective of a consumer who, at least initially, knows next to nothing
about your API.</p>

<p>This problem often extends deeply into the API documentation. There are few things worse
than wasting bits and bytes (and your readers’ time) by providing a circular description
of a field or operation that has an obscure or non-obvious purpose, described with
undefined, obsolete, or misleading terms that raise more questions than answers:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="na">paths</span><span class="pi">:</span>
    <span class="na">/lincoln/v14/indications/</span><span class="pi">:</span>
      <span class="na">post</span><span class="pi">:</span>
         <span class="na">summary</span><span class="pi">:</span>
           <span class="s">Create a new laminar indication in the layers V12 API.</span>
</code></pre></div></div>

<p>Don’t. Do. This.</p>

<p>(Yes, this is an excerpt from a vendor’s production API.)</p>

<p>A successful API clearly articulates its purpose, and the API design and documentation is
built upon a foundation of a good conceptual model of the API’s domain. Such APIs arise
when the team applies an API design process [ADDR recommended] rather than simply
generating an API from a (soon to be obsolete) database schema or other structure which
has been optimized for completely different use case than a clean API. (For my thoughts on
using Generative AI to design APIs, see my
<a href="/2024/04/11/the-art-of-api-design">The Art of API Design</a> talk at
Nordic APIs Austin API Summit, 2024)</p>

<p>A successful API designed via a solid process is more likely to provide the needed
services.</p>

<p>Other problems you may encounter which inhibit API success are listed below. (Fret not,
I’ve included lots of guidance on how to avoid the problems.)</p>

<ol>
  <li>An API that uses proprietary authorization. I led a <em>Birds of a Feather</em> session at an API
conference a few years ago, and the largest hurdle that most of the participants expressed was
getting API authentication/authorization right. It’s not too hard to use OpenIDConnect /
OAuth2 correctly, especially if you use a good library that implements the protocol, but
if an API has proprietary auth, then auth becomes a problem for your API users, an thus,
your API becomes a problem for them.</li>
  <li>An API that shuns HTTP standards.</li>
  <li>The most common “hall of shame” for APIs (as I shared in <a href="/2023/03/25/my-favorite-api-memes">My Favorite API Memes</a>
) is not using correct 4XX and 5XX HTTP response codes and their semantics, but instead returning a 200 OK HTTP response code with <code class="language-plaintext highlighter-rouge">{ "error": true, ... }</code> or <code class="language-plaintext highlighter-rouge">{ "success": false, ... }</code></li>
  <li>A related problem is not using the correct 2xx response codes. If your POST creates a new resource, return 201, not 204. If your operation only has side effects but does not return any data, use a 204, not a 200.</li>
  <li>Other examples are violating the uniform interface constraint of RESTful APIs - i.e. misusing the HTTP methods <code class="language-plaintext highlighter-rouge">GET</code>, <code class="language-plaintext highlighter-rouge">PUT</code>, <code class="language-plaintext highlighter-rouge">POST</code>, <code class="language-plaintext highlighter-rouge">PATCH</code>, <code class="language-plaintext highlighter-rouge">DELETE</code>; or a <code class="language-plaintext highlighter-rouge">GET</code> operation not being idempotent and safe (I once saw an API which used a <code class="language-plaintext highlighter-rouge">GET</code> operation to shut down a server! <strong>Do. Not. Do. This.</strong> _Run, don’t walk, away from such APIs.`) There was a lot of thought put into the design of the HTTP protocol, and the protocol ecosystem (libraries, proxies, gateways, and other intermediaries, etc), works well only if the protocol is followed. Ignorance or hubris says “I know better….”.</li>
  <li>Not using the standard HTTP headers can be a problem. When a POST operation creates a new resource, return the new resource’s URL in the standard Location <a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-10.2.2">response header</a>. If a resource is not ready, the GET operation should return the standard <a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-retry-after">HTTP Retry-After response header</a>.</li>
  <li>Always use date-time values in <a href="https://datatracker.ietf.org/doc/html/rfc3339">RFC 3339</a> <code class="language-plaintext highlighter-rouge">date-time</code> format in UTC (“Zulu”) time done. Let clients map these to the user’s time zone or date/time format. The <a href="https://apiux.com/2013/03/20/5-laws-api-dates-and-times/">5 laws of API dates and times</a> by <a href="https://www.linkedin.com/in/jasonhnaustin/">Jason Harmon</a> is an oldie but a goodie…</li>
  <li>An API that tries to avoid or minimize good use of JSON Schema is a problem. If you are defining an API, you owe it to your consumers to use JSON Schema well. This includes well-named schemas and properties, but also appropriate use of JSON Schema constraints and annotations as declarations of what data is valid in a request, and what data to expect in responses.
  The simplest example of such a problem is using strings with <code class="language-plaintext highlighter-rouge">"Y"</code> or <code class="language-plaintext highlighter-rouge">"N"</code> (or other string values) instead of boolean values, but it also includes exposing data taken directly from packed/encoded raw database fields, such as CHAR(1) codes or integer codes instead of self-describing enum values (See <a href="https://www.amundsens-maxim.com/">Amundsen’s Maxim</a>). Here are a couple examples from a real-world API: <img src="/assets/img/wrong-use-of-boolean-values.png" alt="API documentation showing a property named `business` which is defined with enumerated values `&quot;Y&quot;` and `&quot;N&quot;` instead of using JSON Boolean types" />
  <br />
  <img src="/assets/img/non-mnemonic-codes-in-api-design.png" alt="API documentation showing a `code` property with a single character codes rather than mnemonic enumeration strings" /></li>
  <li>I don’t know about you, but I have no way to know how to use those single character
code in the matches property… and the <code class="language-plaintext highlighter-rouge">pattern: \w{1}</code> constraint is certainly
more obtuse than <code class="language-plaintext highlighter-rouge">minLength: 1, maxLength: 1</code>. <em>A good API team will anticipate and answer the questions developers will have about your API.</em> This is another reason to use the <a href="https://addrprocess.com/">ADDR Process</a> — and <em>not skip the Refine phase</em>, where you improve the API after feedback from real users.
    <blockquote>
      <p>Don’t be afraid to refine and revise your API - instead, plan for it!</p>

      <p>— David Biesack</p>
    </blockquote>
  </li>
  <li>Any design aspect which violates basic and widely adopted conventions or developer expectations for how APIs work is a problem. Just as a good User Experience (UX) should be intentionally designed, a good Developer Experience (DX) should be intentionally designed,, with the goal of enabling the desired feature as intuitively as possible, without surprises.</li>
  <li>An incomplete API is one example of violating these expectations. Normally, if your API supports creating a resource, it should also provide a way to update/patch that resource, fetch the most recent representation of that resource, and ultimately delete it. Omitting one or more leads to a frustratingly incomplete API that violates basic expectations.</li>
  <li>Inconsistency can be is another caustic API problem. A consistent API design is easier to
learn and use because it adheres to those expectations; an inconsistent design adds
frustration. (Recommended:
<a href="https://blog.postman.com/the-5-dimensions-of-api-consistency/">The 5 dimensions of API consistency</a>
by Arnaud Lauret)</li>
  <li>An API that is not designed for evolution will not evolve gracefully when it needs to
change… that’s a problem. An no, changing the API URL from <code class="language-plaintext highlighter-rouge">/v1/...</code> to <code class="language-plaintext highlighter-rouge">/v2/...</code> is
not graceful API evolution.</li>
  <li>An API that is not designed with error handling from the start will have problems when
consumers start using the API — developers make mistakes; apps have bugs, and not every
request is perfect. Oh, and hackers or bad actors will use invalid requests to launch
Denial of Service Attacks or worse. (Pro Tip: use <a href="/2023/03/26/your-api-has-problems.-deal-with-it"><code class="language-plaintext highlighter-rouge">application/problem+json</code></a>
 to describe the problems you detect)</li>
  <li>
    <p>A poor or fragmentary Developer Experience can add to the growing list of API problems:</p>

    <ol>
      <li>Onerous registration process</li>
      <li>Unclear license and terms of use</li>
      <li>Unclear or unpredictable rate plans</li>
      <li>Hard to navigate documentation; documentation that one can’t bookmark or reference or search… Oh, the plethora of potential API documentation problems!</li>
      <li>No easily downloaded OpenAPI documents, or OpenAPI documents based on OpenAPI 2.0 instead of 3.x, or “Swagger” documents (Again, see <a href="/2023/03/25/my-favorite-api-memes">those favorite API memes</a>
!)</li>
    </ol>
  </li>
</ol>

<p>API success is certainly more than a lack of problems. Identifying and removing problems
is a necessary but insufficient element of building a successful API or API program. “Zero
problems” is analogous to the definition of the HTTP 200 status code…. you go to all the
bother of assembling a API request, getting the authorization correct, pushing your API
call over the wire, capturing the response… and you end up with the less-than-satisfactory</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>200 OK
</code></pre></div></div>

<p>It’s almost a let down! “Meh, your API call was, well, just OK.”</p>

<p>Instead, I prefer: “200 is Not (just) OK. It’s Success! Hooray! Hooray!”</p>

<p><img src="/assets/img/200-Is-Not-OK.png" alt="banner graphic reading &quot;200 is not OK&quot; in graphic text" /></p>

<p>By reducing the common problems and pitfalls when designing and delivering APIs, you can help your consumers insucceed… If you do it really well and focus not only on removing problems and roadblocks to success, but focus on enabling innovative solutions, you APIs may even be a joy to work with. You have my permission to be more than just OK; you may use “200 Success! Happy Happy Joy Joy!” in your API documentation.</p>

<p><img src="/assets/img/200-Success,-Happy-Happy-Joy-Joy.png" alt="Blue block-lettered text on white background reading &quot;200: Success! Happy Happy Joy Joy!" /></p>

<hr />

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><category term="the-language-of-api-design" /><summary type="html"><![CDATA[200 is Not OK]]></summary></entry><entry><title type="html">From Here to There, from Where to Here</title><link href="https://apidesignmatters.org/2025/03/16/from-here-to-there-from-where-to-here.html" rel="alternate" type="text/html" title="From Here to There, from Where to Here" /><published>2025-03-16T18:00:00+00:00</published><updated>2025-03-16T18:00:00+00:00</updated><id>https://apidesignmatters.org/2025/03/16/from-here-to-there-from-where-to-here</id><content type="html" xml:base="https://apidesignmatters.org/2025/03/16/from-here-to-there-from-where-to-here.html"><![CDATA[<blockquote>
  <p>Patterns for Web API Query Parameters</p>
</blockquote>

<p>There are many different patterns for using query parameters in web
APIs. Today’s article in my API Design Patterns series in API Design
Matters is about query parameters in Web APIs. Let’s explore some of
these patterns…</p>

<p><img src="/assets/img/From-Here-to-There,-from-Where-to-Here.png" alt="alt text" /></p>

<blockquote>
  <p>Welcome to the next article in <em>The Language of API Design</em> series.
Rather than jumping into the middle of this series, I encourage new
visitors start by reading
<a href="/the-language-of-api-design">The Language of API Design</a>
and scanning previous posts in the series.</p>
</blockquote>

<h2 id="it-is-what-it-is">It is what it is</h2>

<p>In HTTP APIS, query parameters occur after the path and before optional anchor tags in a URL. The query parameters begin with the <code class="language-plaintext highlighter-rouge">?</code> special character, which is followed by a <code class="language-plaintext highlighter-rouge">&amp;</code>-delimited list of <em>name=value</em> pairs</p>

<p>It’s quite natural to interpret this <code class="language-plaintext highlighter-rouge">=</code> character to mean equality, i.e
<code class="language-plaintext highlighter-rouge">?x=6</code> means “where x equals 6”. However, I prefer to interpret this <code class="language-plaintext highlighter-rouge">=</code>
character as “is” , such as “where x is 6”</p>

<p>Thus, one can read or “interpret” a URL such as the following (ignore line breaks)</p>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">http://api.chainlinks.example.com/universes</code> <br />
<code class="language-plaintext highlighter-rouge">?author=au345bd84</code> <br />
<code class="language-plaintext highlighter-rouge">&amp;genre=fantasy</code></p>
</blockquote>

<p>as</p>

<blockquote>
  <p>universes where<br />
the author <em>is</em> (the author with id au345bd84)<br />
and genre <em>is</em> “fantasy”</p>
</blockquote>

<p>I find this style slightly more <a href="http://www.literateprogramming.com/">literate</a>
as well as more flexible than a rigid “equals” interpretation.</p>

<h2 id="filtering-list-operations">Filtering List Operations</h2>

<p>For consistency across APIs, I use query parameters to, as the name implies, parameterize the query. What does this mean? Most commonly, I use query parameters to serve as filters on List operations, as a means of subsetting the response list to a narrower set that satisfies the conditions defined in one or more query parameters.</p>

<p>In these cases, the interpretation of the query parameters is done with an implicit context of an element of the referenced collection.</p>

<p>In our <a href="/2023/03/07/chain-links-domain-model">Chain Links API</a>, one such collection is the <code class="language-plaintext highlighter-rouge">chainLinks</code> resource.</p>

<p>A chain link has several properties:</p>

<ul>
  <li>the author who created/write the chain link</li>
  <li>a set of characters who are mentioned in or are part of the chain link</li>
  <li>the universe in which the chain link occurs</li>
  <li>the date when the author create/wrote the chain link (<code class="language-plaintext highlighter-rouge">authoredOn</code>)</li>
</ul>

<p>Thus, we can use these property names as query parameter names to subset
the list response to those chain link instances whose property values
match the query parameters.</p>

<p>The next design decision is what query parameter <em>values</em> to use after the <code class="language-plaintext highlighter-rouge">=</code> sign. For <code class="language-plaintext highlighter-rouge">author</code> and <code class="language-plaintext highlighter-rouge">universe</code> query parameters, we want to allow the client to pass the author’s resource ID (author names are not unique) or perhaps the author’s URI. Similarly, it is most convenient for the client to pass the resource ID for for a universe resource.</p>

<p>As I wrote in
<a href="/2023/03/09/from-domain-model-to-OpenAPI">From Domain Model to OpenAPI</a>,
one can parameterize the request to return a list of chain links:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GET /chainLinks?character={someCharacterId}
GET /chainLinks?universe={someUniverseId}
GET /chainLinks?author={someAuthorId}
GET /chainLinks?authoredOn=[2023-01-01,2023-03-31]
</code></pre></div></div>

<p>I hope the first three are intuitive. A common pattern is to filter
resources on a <em>range</em> of values, such as a date range. In banking APIs
(such as filtering a list of transactions), it’s common to filter based
on a range of values. I like using range notation as shows with the date
range above; this works for numeric values as well, such as <code class="language-plaintext highlighter-rouge">GET
/banking/accounts/{accountId}/transactions?amount=(0,100.00]</code> to match
transactions whose amount is greater than 0 and less than or equal to
100.00.</p>

<p>I’ve seen lots of other query designs for ranges, such as</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>?amount=gt:0&amp;amount=le:100.00
?filter=and(gt(amount,0),le(amount:100.0)
?where=amount &gt; 0 and amount &lt;= 100
?$filter=amount gt 0 and amount le 100.00
</code></pre></div></div>

<p>The last one is based on OData. It and the ?where style before it are
more common in APIs which directly expose the underlying data schema.
However, this is more of an anti-pattern in modern web APIs, which are
more robust when they support (or even enforce) an abstraction layer
between the API consumer and the back-end system behind the API.
<a href="https://mamund.substack.com/">Mike Amundsen</a> put this eloquently when
he wrote</p>

<blockquote>
  <p><a href="https://www.amundsens-maxim.com/">Amundsen’s Maxim</a>
“Remember, when designing your Web API, your data model is not your
object model is not your resource model is not your message
model.” — Mike Amundsen</p>
</blockquote>

<p>(Mike shared this in 2016 on a social media microblogging site that I
choose to not quote here. However, you can read more about it at
<a href="https://mamund.substack.com/p/what-is-amundsens-maxim">What is Amundsen’s Maxim?</a>)</p>

<p>In other words, if you expose the current data schema of your (internal) database, you lock your API into that implementation, or you risk breaking clients if you wish to refactor the database. (Mike followed up the original message with a clarification: “we need to be able to design/implement each aspect (data, object, resource, representation) independently without breaking the others.”) Thus, I advise against adopting any query parameter patterns that expose the back-end implementation details of the API web service. I think this emphasizes the main purpose of following good API design and API design patterns: Expect change, and use API design to hide the API consumer from changes which should not impact them.</p>

<p>Getting back to our other patterns, I hope you can see why I think that
interpreting = in a URL’s query parameters as <em>“is”</em> works better than
<em>“equals”</em>, such as:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>?amount=gt:0&amp;amount=le:100.00
</code></pre></div></div>

<blockquote>
  <p>amount is greater than 0 and amount is less than 100.00</p>
</blockquote>

<p>Some of these obviously require URL encoding, namely:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>?amount=(0%2C100.00%5D       // ?amount=amount=(0,100.00]
?amount=gt%3A0&amp;le%3A100.00   // ?amount=gt:0&amp;amount=le:100.00
?amount=and(gt(amount%2C0)%2Cle(amount%3A100.0)
?where=amount%20%3E%200%20and%20amount%20%3C%3D%20100
?$filter=amount%20gt%200%20and%20amount%20le%20100.00
</code></pre></div></div>

<p>Unfortunately, none of these are very legible once they have been URL encoded.</p>

<p>I like the range notation (also known as interval notation) because it
has existed in mathematics since before I first studied math (decades
ago). It is concise and very flexible. The ( and ) characters denote
open ended intervals (the interval does not include the adjacent
endpoint) and the [ and ] characters denote closed-ended intervals (the
interval includes the adjacent endpoint):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>?amount=(20.0,100.0]  : amount &gt; 20.0 &amp;&amp; amount &lt;= 100.0
?amount=[20.0,100.0]  : amount &gt;= 20.0 &amp;&amp; amount &lt;= 100.0
?amount=(20.0,100.0)  : amount &gt; 20.0 &amp;&amp; amount &lt; 100.0
?amount=[20.0,100.0)  : amount &gt;= 20.0 &amp;&amp; amount &lt; 100.0
?amount=(20.00,)      : amount &gt; 20.0
?amount=[20.00,)      : amount &gt;= 20.00
?amount=(,100.0]      : amount &lt;= 100.00
?amount=(,100.0)      : amount &lt; 100.00
</code></pre></div></div>

<h2 id="this-or-that-here-or-there">This or That, Here or There</h2>

<p>One additional query parameter pattern I use comes in handy when you
wish to express a condition where a resource’s property is one of a
small list of values (usually string enumerations). I.e. to capture the
condition of testing if the state property of a chain link is one of
three values, draft, published, withdrawn, the desired natural language
query is something like</p>

<blockquote>
  <p>List chain links where the chain link’s state is either draft or
published or withdrawn</p>
</blockquote>

<p>As a query parameter, the
<a href="https://spec.openapis.org/oas/v3.1.1.html#style-values">OpenAPI Specification allows defining a query
using an pipe-delimited array</a>. This is convenient because the pipe
character, <code class="language-plaintext highlighter-rouge">|</code>, is used as a binary <em><strong>or</strong></em> operator in several programming
languages. Thus, this filter maps to query parameter notation</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>?state=draft|published|withdrawn
</code></pre></div></div>

<p>In OAS 3.x notation, one can define a parameter:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">parameters</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">state</span>
    <span class="na">in</span><span class="pi">:</span> <span class="s">query</span>
    <span class="na">explode</span><span class="pi">:</span> <span class="no">false</span>
    <span class="na">style</span><span class="pi">:</span> <span class="s">pipeDelimited</span>
    <span class="na">schema</span><span class="pi">:</span>
      <span class="na">type</span><span class="pi">:</span> <span class="s">array</span>
      <span class="na">minItems</span><span class="pi">:</span> <span class="m">1</span>
      <span class="na">maxItems</span><span class="pi">:</span> <span class="m">3</span>
      <span class="na">uniqueItems</span><span class="pi">:</span> <span class="no">true</span>
      <span class="na">items</span><span class="pi">:</span>
        <span class="na">$ref</span><span class="pi">:</span> <span class="s1">'</span><span class="s">#/components/schemas/chainLinkState'</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">chainLinkState</code> schema is defined with a JSON schema such as</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">components</span><span class="pi">:</span>
  <span class="na">schemas</span><span class="pi">:</span>
    <span class="na">chainLinkState</span><span class="pi">:</span>
      <span class="na">title</span><span class="pi">:</span> <span class="s">Chain Link State</span>
      <span class="na">description</span><span class="pi">:</span> <span class="s">The state that a chain link resource may be in.</span>
      <span class="na">type</span><span class="pi">:</span> <span class="s">string</span>
      <span class="na">enum</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="s">draft</span>
        <span class="pi">-</span> <span class="s">published</span>
        <span class="pi">-</span> <span class="s">withdrawn</span>
</code></pre></div></div>

<p>The schema for the query parameter further constrains the parameter, allowing an API service to validate the value and reject invalid queries such as</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>?state=                         # minItems constraint violated
?state=garbage                  # items enum constraint violated
?state=draft|draft|draft|draft  # maxItems / uniqueItems: true
                                # constraint violated
</code></pre></div></div>

<p>I prefer using named schemas for such cases compared to putting the enum
schema in line in the parameter definition, as this helps Software
Development Kit (SDK) code generation tools generate cleaner code.
Absent named schemas, code generation tools often construct new names
for data types based on the context or location, and I find the result
somewhat unsatisfactory.</p>

<h2 id="parameterizing-operations">Parameterizing Operations</h2>

<p>Query parameters can parameterize other operations, not just List operations. I try to avoid mixing request body data with parameterization. For example, when creating (POST) or updating a resource (PATCH or PUT), I put all the data necessary to create or update the resource in the request body. Query parameters may alter how the operation is performed, but the request body conveys what data to use.</p>

<p>For example, see how the <code class="language-plaintext highlighter-rouge">?dryRun=</code> query parameter alters the behavior
of a POST or other operation in
<a href="/2024/08/19/validating-api-requests">Validating API Requests</a>.
There, the value of the <code class="language-plaintext highlighter-rouge">?dryRun=</code> query parameter is not part of the
request body payload — it does not get stored in the resource. Instead,
this parameterizes the operation, requesting that the server stop short
of creating or updating the resource, so that the client can let the API
service perform full validation of the request.</p>

<h2 id="your-options">Your Options</h2>

<p>There are many conventions and patterns for Web API query parameters.
It’s less important which style you choose, but as with any pattern,
what is more important is that you use it consistently across your APIs.</p>

<hr />

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><category term="the-language-of-api-design" /><summary type="html"><![CDATA[Patterns for Web API Query Parameters]]></summary></entry><entry><title type="html">Wherefore HATEOAS</title><link href="https://apidesignmatters.org/2025/01/23/Wherefore-HATEOAS.html" rel="alternate" type="text/html" title="Wherefore HATEOAS" /><published>2025-01-23T18:00:00+00:00</published><updated>2025-01-23T18:00:00+00:00</updated><id>https://apidesignmatters.org/2025/01/23/Wherefore-HATEOAS</id><content type="html" xml:base="https://apidesignmatters.org/2025/01/23/Wherefore-HATEOAS.html"><![CDATA[<blockquote>
  <p>Hypermedia as the Engine of Application State</p>
</blockquote>

<p>It’s finally time for <em>API Design Matters</em> to tackle one of the more
complex API design patterns/practices: Hypermedia, or more aptly named,
<em>Hypermedia As The Engine Of Application State</em> (HATEOAS).</p>

<p>(Please note that what follows are <em>my personal observations and
perspectives</em> on Hypermedia APIs. I encourage <em>API Design Matters</em> readers
to explore other voices.)</p>

<p><img src="/assets/img/Wherefore-HATEOAS.png" alt="alt text" /></p>

<p><a href="https://ics.uci.edu/~fielding/pubs/dissertation/top.htm">Roy Fielding defined the REST API architectural style</a>
and
<a href="https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">has stated</a>
that an API is not a REST API if it is not hypermedia driven. So what does this mean?</p>

<p>( REST? RESTful? REST-like? REST-ish? See <a href="/2023/12/26/we-talk-api-one-day">We Talk “API” One Day</a> )</p>

<p>At the structural level, a Hypermedia API is one in which the
capabilities of the API—or more accurately, the capabilities of
the application that the API enables—are conveyed in the API’s
responses, typically through hypermedia <em>links</em> embedded in the data.
Much as a web page is more useful because it contains links to other
related web pages, an API response (that is, a representation of one of
the API’s resources) is enriched when it includes links to resources or
API actions related to that resource.</p>

<p>Hypermedia APIs allows both discoverability of the features of the
API/application as well as looser coupling between the client
application and the API services—both admirable goals. As a pattern,
Hypermedia is fine solution to the design force of decoupling a web
application front end from the back end that manages it. Key to this is
allowing business rules to be managed on the back end rather than
replicated in the front end. For example, by including or excluding
certain links in responses from the back end, the application can
control what the end user can do. More importantly, it allows the
application to evolve by adding new features, expressed through
hypermedia, without having to re-write or update the client.</p>

<p>However, just as there is no standard definition of a REST API, there is
no definitive standard for how such hypermedia links are conveyed.
Instead, there are myriad competing standards and formats, such as</p>

<ul>
  <li><a href="https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-00">Hypertext Application Language</a> (HAL)</li>
  <li><a href="https://github.com/kevinswiber/siren">Siren</a></li>
  <li><a href="https://restfuljson.org/">Restful JSON</a></li>
  <li><a href="https://mamund.com/media-types/collection/format/">Collection+JSON</a></li>
  <li><a href="https://www.w3.org/TR/json-ld11/">JSON-LD</a></li>
  <li><a href="https://jsonapi.org/">JSON:API</a></li>
  <li><a href="https://www.hydra-cg.com/spec/latest/core/">Hydra</a></li>
  <li>… and others.</li>
</ul>

<p>I won’t dive into the details of all of these (that would be a couple
chapters worth of book material, and not too helpful right now).
Instead, I want to discuss the pros and cons of embedding Hypermedia in
a web API.</p>

<p>One of the primary goals of encapsulating a back end service or process
with an API is to add a level of abstraction. The API is the embodiment
of an abstraction at a point in time. However, services evolve over
time - they may add more capabilities or features. This is typically
exposed with new versions of an API, or even entirely new APIs if the
new behavior does not fit well in the existing API.</p>

<p>However, another way to deliver new functionality within an API is more
dynamically, by returning new links in the payload of the existing API.</p>

<p>For example, in the
<a href="/2023/03/07/chain-links-domain-model">Chain Links sample API</a>
I have provided in this series, the <code class="language-plaintext highlighter-rouge">listUniverses</code> operation returns a
representation of a list of <code class="language-plaintext highlighter-rouge">universes</code> (i.e. an array of <code class="language-plaintext highlighter-rouge">universeItem</code>
objects, each of which has the unique <code class="language-plaintext highlighter-rouge">id</code> of a universe.) The <code class="language-plaintext highlighter-rouge">getUniverse</code>
API operation accepts a <code class="language-plaintext highlighter-rouge">universeId</code> path parameter and fetches the
representation of that universe. This requires the client (or a Software
Development Kit or SDK library) to construct URLs to use the API - i.e.
the <code class="language-plaintext highlighter-rouge">getUniverse(universeId: string)</code> operation will substitute the
<code class="language-plaintext highlighter-rouge">universeId</code> into into the API path <code class="language-plaintext highlighter-rouge">/universes/{universeId}</code> and prepend
the API server base URL from the OpenAPI <code class="language-plaintext highlighter-rouge">servers</code> object in order to
invoke the <code class="language-plaintext highlighter-rouge">getUniverse</code> operation, then parse the JSON response and bind
it to a <code class="language-plaintext highlighter-rouge">universe</code> data structure in the target language. In a hypermedia
API, the URL of each item would be included in the list of universe
items in the <code class="language-plaintext highlighter-rouge">listUniverses</code>’s <code class="language-plaintext highlighter-rouge">universes</code> response, so that the client is
more loosely coupled to the API. This allow the API service to evolve
over time, such as providing a more efficient URL for fetching
resources. Such changes are not possible if the client has a tight
coupling to (a specific version of) the API.</p>

<p>The other challenge with hypermedia links is conveying the semantics. At
the base level, a link is just that - a URL. But in an HTTP API, a URL
is only part of the operation: there is also the HTTP verb, the
authorization, the request and response bodies, HTTP request and
response headers, and if the client is going to present the link or
action in the client application (such as a button or menu item or
link), it requires a title or label or descriptive text. Unadorned
Hypermedia links may work well with <code class="language-plaintext highlighter-rouge">GET</code> operations, but less so with
<code class="language-plaintext highlighter-rouge">POST</code> operations.</p>

<p>A key element of that unwieldy name “HATEOAS”
(<em>_H__ypermedia __A__s __T__he __E__ngine __O__f __A__pplication
__S__tate)
is _<strong>Application</strong></em>. Hypermedia APIs work well when
they are part of a web application. Applications have state; they
combine user input and back end processing, and the API encapsulates
that application’s behavior and capabilities. In such cases, these
HATEOAS APIs can contain links that expose or enable the next possible
steps in the application, based on the current state of the application
and what the authenticated user can do, given that application state and
what roles and permissions that user has. For example, from a list of
application domain objects, there may be an “edit” link which allows the
user to edit that object. Lack of such a link means that the current
user, given the current application state, cannot edit the object. The
appeal of this decoupling is obvious - the client application does not
(and rightfully should not) contain such business rules, as these are
subject to change (perhaps at a cadence more frequent than API version
releases).</p>

<p>Supporting a Hypermedia API is of course most useful if the client
application is written in such a way that it can do something with those
dynamic links. This is no easy task… most application developers don’t
want to deal with that kind of complexity.</p>

<p>However, we are all familiar with one type of such dynamic application -
your favorite web browser. This ability to handle arbitrary links and
dynamic content is what allows the browser to host myriad client
applications, such as Gmail, Substack, LinkedIn, and so on… without
having any prior knowledge of those applications.</p>

<p>However, when an API is the front end of a very general and reusable web
service with a well defined functional boundary (such as sending Email
or SMS messages or making a credit card payment for an purchase), there
is not a single application that the API is attached to - it must work
with arbitrary applications. Such atomic and composable service APIs may
be stateless, and since they are not part of any one specific
application, they have less application state to convey, and hence
HATEOAS links are less impactful for conveying application state.
Related resource links are still useful, such as a link from a Chain
Link Character to the Universe in which that character lives.</p>

<p>I suggest reading Bruno Pedro’s article,
<a href="https://apichangelog.substack.com/p/why-arent-apis-using-code-on-demand">Why Aren’t APIs Using Code on Demand?</a>
in <a href="https://apichangelog.substack.com/">The API Changelog</a>. Bruno’s
article discusses one of the (optional) constraints of the REST
architecture style, namely <em>Code-on-Demand</em>. It is what makes an API
driven application (such as a single page application) powerful and
reactive, compared to older web application architectures which are
built around server-generated web pages. Code-on-Demand works for web
applications because such applications run within an application host (a
browser) which can execute that code.</p>

<p>Code-on-Demand is also necessary to fully interpret the links in a
Hypermedia API. For example, consider a resource in our Chain Links
application, a Universe. How does one add a new universe? Certainly the
API answer is trivial - by using the POST operation on the /universes
collection, passing a request body that satisfies the newUniverse
schema. In a hypermedia API, the universes collection resource may have
a hypermedia link with a link relation called createUniverse, but if a
client application does not know about this resource or which request
body schema is needed to create a universe, it can’t use that
link… just as a client coded to version 2.1 of an API has no
knowledge of a resource introduced in version 3.0 of the API.</p>

<p>However, Code-on-Demand will allow the application to fetch the code to
do new things, such as create a universe, edit a universe, update a
universe. Creating can be done via a link to a web page or form or
applet which prompts the user to fill in and submit the data necessary
to complete the request. That is, the link to create a new universe is
may be a link to a web page — part of the broader application that the
API encapsulates. It may contain UI form controls and JavaScript to
handle the dynamic aspects, and perhaps optional controls based on the
current application state, such as where to go next after completing the
current task, or where to return to if the user decides to cancel. In
such a way, the client is adaptable and not tied to a specific version
of the API - the application, the API, and the client can evolve
together.</p>

<p>The downside is that, as it’s name implies, Code-on-Demand requires
passing executable code from the back end to the front end. If the
client is a browser, it can dynamically load JavaScript as part of
rendering a web page. Other clients may not have this dynamic
capability. If the client is a secure back office headless application
written in some other language such as Go, it can’t use such
Code-on-Demand without adding a lot of complex client code execution
features. (Of course, security must also be considered any time an
application introduces a new code execution feature.) Also, I am not
aware of APIs which support languages other that JavaScript, though
using <a href="https://webassembly.org/">WebAssembly</a>
(see <a href="https://apichangelog.substack.com/p/why-arent-apis-using-code-on-demand">Why Aren’t APIs Using Code on Demand?</a> ) may be
the technology bridge.</p>

<p>Developing clients to consume and fully exploit Hypermedia APIs requires
not just handling Code-on-Demand; it requires a different mindset. That
is, one must consider the API to be a dynamic entity, not a static one,
with new features possible every time an API call is made. This is a
difficult thing to implement well or correctly, especially when many
applications are often written to do very specific things.</p>

<p>For example, the AI summary on the
<a href="https://developers.google.com/workspace/gmail/api/guides">Gmail API page</a>
states (as of Jan 19, 2025):</p>

<blockquote>
  <p>The API is not intended as a full email client replacement but is
ideal for web applications needing authorized access to user data.</p>
</blockquote>

<p>Most developers prefer using some sort of language Software Development
Kit when coding to an API. However, these SDKs are often tied to a
specific version of an API, with a specific URL layout and fixed set of
operations and parameters—this goes very much against the grain of
Hypermedia APIs which are meant to be dynamic and flexible, not strictly
rigid structures with statically defined URLs and statically defined
request and response body schemas. Such SDKs (often generated from an
OpenAPI definition) typically use rigid interface constructs, such as
representing path parameters (which the SDK will inject to API resource
URLs) as function parameters, with one function per API operation. But a
Hypermedia application is more dynamic - the URLs are all provided by
the API, so the client should never construct a URL. (For example, the
getUniverse function in an SDK for a static API may accept the
universeId parameter; for a Hypermedia based API, the getUniverse
function in an SDK may accept the universe’s URL as a parameter instead
(where that URL is obtained in a link within another API response.)</p>

<p>Let’s revisit an application like Gmail. How would you design this
application to automatically support dynamic features that were not in
your requirements when you first started?</p>

<p>For example, Gmail allows adding attachments to a mail message; that is
part of the mime message format. The user can select a file from their
local file system and the client encodes that in the email message body.
However, if the file is too large, Gmail now has the ability to upload
the file to Google Drive (and set the permissions on that file so the
recipient can access it) and instead of adding an attachment, Gmail will
insert a hyperlink to that file on Google Drive. Imagine trying to
design the client app to allow executing this type of dynamic behavior -
it is not trivial. But with Code-on-Demand, it is possible.</p>

<p>Yes, hypermedia APIs are a useful replacement for server generated web
page architecture, and decoupling a (browser) web application from back
end logic and business rules. HATEOAS seems a better fit when there is a
(server managed) web application, but harder to exploit when the API is
a general purpose component meant to be embedded in arbitrary
applications that the service knows nothing about.</p>

<hr />

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Hypermedia as the Engine of Application State]]></summary></entry><entry><title type="html">Leave a Calling Card</title><link href="https://apidesignmatters.org/2024/09/19/leave-a-calling-card.html" rel="alternate" type="text/html" title="Leave a Calling Card" /><published>2024-09-19T18:00:00+00:00</published><updated>2024-09-19T18:00:00+00:00</updated><id>https://apidesignmatters.org/2024/09/19/leave-a-calling-card</id><content type="html" xml:base="https://apidesignmatters.org/2024/09/19/leave-a-calling-card.html"><![CDATA[<blockquote>
  <p>Make API responses more self-descriptive with reference objects</p>
</blockquote>

<p>Here’s today’s quick tip to make your API really stand out: make the response payloads as cryptic as possible.</p>

<p>I’m kidding, of course. I suppose if your message models are super
cryptic, your API will stand out… but for the wrong reason. Today, I’ll
present a useful pattern for making API data less cryptic with the
equivalent of a “calling card” - API reference objects.</p>

<p><img src="/assets/img/Leave-a-Calling-Card.png" alt="alt text" /></p>

<blockquote>
  <p>Welcome to the next article in <em>The Language of API Design</em> series.
Rather than jumping into the middle of this series, I encourage new
visitors start by reading
<a href="/the-language-of-api-design">The Language of API Design</a>
and scanning previous posts in the series.</p>
</blockquote>

<p>Most api resources don’t exist in isolation - instead, they have relationships with other resources. in the api design matters sample domain, chain links, i’ve shown how to use restful json to capture these relationships. a chain link has an author, and in the json model of a chain link, there is a property</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="s2">"</span><span class="s">author_url"</span><span class="err">:</span> <span class="s2">"</span><span class="s">https://api.chainlinks.example.com/authors/a733fhab"</span>
</code></pre></div></div>

<p>which is the URL of the author resource. A chain link also resides in a universe that is conveyed with a property as well:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"</span><span class="s">universe_url"</span><span class="err">:</span> <span class="s2">"</span><span class="s">https://api.chainlinks.example.com/universes/ucc87e09"</span>
</code></pre></div></div>

<p>If not using <a href="https://restfuljson.org/">Restful JSON</a> or some other
hypermedia based format, these relationships may be modeled instead with
the lower level equivalent of foreign database keys, namely the resource
IDs of the related resources:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"</span><span class="s">authorId"</span><span class="err">:</span> <span class="s2">"</span><span class="s">a733fhab"</span>
<span class="s2">"</span><span class="s">universeId"</span><span class="err">:</span> <span class="s2">"</span><span class="s">ucc87e09"</span>
</code></pre></div></div>

<p>While these representations convey the necessary information, it’s not
very satisfying for human consumption and results in a poor developer
experience.</p>

<p>I prefer JSON representations which are less cryptic and more
self-descriptive. This is where small reference objects can be useful.</p>

<p>My use of the term “reference object” is only slightly related to a $ref
reference object as used in <a href="https://json-schema.org">JSON Schema</a>
and <a href="https://spec.openapis.org/oas/v3.1.2.html">OpenAPI Specification</a> (OAS). In
OAS, a <em>Reference Object</em> is a JSON object with a <code class="language-plaintext highlighter-rouge">$ref</code> keyword and a URI
of a referenced value defined elsewhere in the OAS API definition. (See
<a href="/2023/04/09/dont-repeat-yourself-when-designing-apis">Don’t Repeat Yourself When Designing APIs</a>
) For example, an API
operation’s response object may define the response’s schema with a
Reference Object to a schema component. The <code class="language-plaintext highlighter-rouge">getAuthor</code> operation’s 200 OK
response is defined with a <code class="language-plaintext highlighter-rouge">$ref</code> to the author schema:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      <span class="na">responses</span><span class="pi">:</span>
        <span class="s1">'</span><span class="s">200'</span><span class="err">:</span>
          <span class="na">description</span><span class="pi">:</span> <span class="s">OK. The operation succeeded.</span>
          <span class="na">content</span><span class="pi">:</span>
            <span class="na">application/json</span><span class="pi">:</span>
              <span class="na">schema</span><span class="pi">:</span>
                <span class="na">$ref</span><span class="pi">:</span> <span class="s1">'</span><span class="s">#/components/schemas/author'</span>
</code></pre></div></div>

<p>In OAS, a reference object contains a <code class="language-plaintext highlighter-rouge">$ref</code> value and may contain <code class="language-plaintext highlighter-rouge">summary</code> or <code class="language-plaintext highlighter-rouge">description</code> values. However, there is a kernel of usefulness here that can be used outside of defining an API with OpenAPI — we can use a construct inspired by OAS reference objects instead of terse and cryptic Restful JSON URLs or naked resource ID properties.</p>

<p><em>An API reference object is a (JSON) object that references another
resource.</em></p>

<p>Such API reference objects (or more simply a <em>reference object</em>) in API responses (or requests) can include other key identifying data about the referenced resource; these are optional and informative. The id or url of the resource are required to actually identify the referenced resource. This makes the overall JSON payload more self-descriptive and does not send the developer down ratholes trying to understand data they see when exploring and learning the API.</p>

<p>Instead of seeing a terse/cryptic representation of a chain from the
Chain Links API:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"36abf4ceb72389"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"author_url"</span><span class="p">:</span><span class="w">
     </span><span class="s2">"https://api.chainlinks.example.com/authors/a733fhab"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"universe_url"</span><span class="p">:</span><span class="w">
     </span><span class="s2">"https://api.chainlinks.example.com/universes/ucc87e09"</span><span class="w">
  </span><span class="err">...</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>we can use reference objects (a different reference object schema for each resource) that includes the resource ID of that resource, its URL, and other identifying data:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"36abf4ceb72389"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"author"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
     </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"D.T. Weintraub"</span><span class="p">,</span><span class="w">
     </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"a733fhab"</span><span class="p">,</span><span class="w">
     </span><span class="nl">"url"</span><span class="p">:</span><span class="w">
        </span><span class="s2">"https://api.chainlinks.example.com/authors/a733fhab"</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"universe"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
     </span><span class="nl">"name"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"Edgar Rice Burroughs' Mars"</span><span class="p">,</span><span class="w">
     </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ucc87e09"</span><span class="p">,</span><span class="w">
     </span><span class="nl">"url"</span><span class="p">:</span><span class="w">
        </span><span class="s2">"https://api.chainlinks.example.com/universes/ucc87e09"</span><span class="w">
  </span><span class="p">}</span><span class="w">
  </span><span class="err">...</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>While a bit more verbose, I find the extra data to be immensely useful
in understanding the overall data.</p>

<p>In my work with designing banking APIs, we use <em>account reference objects</em> when one resource has a relationship to a banking account. For example, a transfer from a source account to a target account can be represented (albeit cryptically) as</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"sourceAccountId"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"30623674-5a14-99eed7a86549"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"targetAccountId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"4f3775d0-94e5-39cb8fb6924d"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"amount"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"500.00"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>By itself, this is not very informative because the opaque resource IDs do not add much usable stand-alone information to the reader; all we have is the means to find out more information about those accounts, but that is indirect and cumbersome.</p>

<p>A much more descriptive representation uses account reference objects
which tell more about the accounts:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"sourceAccount"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"30623674-5a14-99eed7a86549"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"url"</span><span class="w"> </span><span class="p">:</span><span class="w">
      </span><span class="s2">"https://api.example.com/accounts/30623674-5a14-99eed7a86549"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"type"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"checking"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"maskedNumber"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"*7844"</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"targetAccount"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"4f3775d0-94e5-39cb8fb6924d"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"url"</span><span class="w"> </span><span class="p">:</span><span class="w">
      </span><span class="s2">"https://api.example.com/accounts/4f3775d0-94e5-39cb8fb6924d"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"type"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"savings"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"maskedNumber"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"*1363"</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"amount"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"500.00"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<h2 id="resources-can-contain-their-own-reference-objects">Resources can contain their own reference objects</h2>

<p>To make these reference objects even more useful, the API service can
build them for you instead of making the client construct them. For
example, the response from the <code class="language-plaintext highlighter-rouge">getUniverse</code> operation can contain a
<code class="language-plaintext highlighter-rouge">reference</code> or <code class="language-plaintext highlighter-rouge">ref</code> property which is the reference object that the
client can embed in other requests when citing a universe. The <code class="language-plaintext highlighter-rouge">*Item</code>
schema in the API’s list responses (see
<a href="/2023/03/16/what-am-i-getting-out-of-this">What Am I Getting Out of This?</a>)
can also include the reference object instead of just the <code class="language-plaintext highlighter-rouge">id</code> of the
item in the colletion.</p>
<hr />

<h2 id="avoiding-excessive-data-exposure">Avoiding Excessive Data Exposure</h2>

<p>Reference objects should be small and only contain necessary data, not
many or most of the properties of the referenced resource. For example,
by no means is the universe property of a chain link defined by the full
universe schema. This limited, small reference object helps avoid
Excessive Data Exposure (OWASP API Security 2023
“<a href="https://owasp.org/API-Security/editions/2023/en/0xa3-broken-object-property-level-authorization/">Broken Object Property Level Authorization</a>”
vulnerability. Using small reference objects helps keep payloads smaller
but still informative. Too many properties will just add noise,
defeating the Developer Experience benefits of using reference objects.
Choose key attributes of the resource to include in the reference
object, such as the name or type of the resource. Avoid sensitive data,
such as full account numbers, sensitive Personally Identifiable
Information (PII), etc. (Note: the author name shown in examples above
is not PII, but is the author’s public pen name.)</p>

<hr />

<p>I hope you see value in using reference objects over more cryptic and
opaque identifiers or URLs. Why not try them out in your next API
design? Please leave comments to share your experience.</p>

<hr />

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><category term="the-language-of-api-design" /><category term="api-design-patterns" /><summary type="html"><![CDATA[Make API responses more self-descriptive with reference objects]]></summary></entry><entry><title type="html">Validating API Requests</title><link href="https://apidesignmatters.org/2024/08/19/validating-api-requests.html" rel="alternate" type="text/html" title="Validating API Requests" /><published>2024-08-19T18:00:00+00:00</published><updated>2024-08-19T18:00:00+00:00</updated><id>https://apidesignmatters.org/2024/08/19/validating-api-requests</id><content type="html" xml:base="https://apidesignmatters.org/2024/08/19/validating-api-requests.html"><![CDATA[<blockquote>
  <p>Techniques for API Request Validation</p>
</blockquote>

<p>Next up in the <a href="/api-design-patterns">API Design Patterns</a> series on API Design Matters, I’d like to present some patterns for validating API requests.</p>

<p><img src="/assets/img/Validating-API-Requests.png" alt="alt text" /></p>

<blockquote>
  <p>Welcome to the next article in <em>The Language of API Design</em> series.
Rather than jumping into the middle of this series, I encourage new
visitors start by reading
<a href="/the-language-of-api-design">The Language of API Design</a>
and scanning previous posts in the series.</p>
</blockquote>

<p>As I discussed in
<a href="/2024/02/06/improve-the-security-of-your-apis-data">Improve the Security of Your API’s Data</a>:</p>

<blockquote>
  <p>An API that allows unconstrained values to be passed is an API that likely has security vulnerabilities</p>
</blockquote>

<p>That is, to keep an API secure, <em>it should not trust any data that it
receives</em>.
Applying strict JSON schema constraints and ensuring all API operations
are properly secured via authentication/authorization help with
maintaining the secure API posture.
But is there a flip side - can an API help client’s validate their
interactions with the API?</p>

<p>A promise of REST APIs is good decoupling of clients and services. This
is achieved in part by reducing business logic as much as possible in
the client application. For example, a client application may use a form
for collecting information used in a <code class="language-plaintext highlighter-rouge">POST</code> operation to create an API
resource, or to edit an existing resource before updating it with a <code class="language-plaintext highlighter-rouge">PUT</code>
or <code class="language-plaintext highlighter-rouge">PATCH</code> operations. The client then maps the form fields to the
properties of the operation’s request body. Clients can use front end
frameworks and libraries to perform lots of low-level validation in the
front end corresponding to JSON schema constraints. Examples include:</p>

<ul>
  <li>Forms which use required data fields for properties that are required in the JSON schema</li>
  <li>Using date pickers</li>
  <li>Checkboxes for selecting Boolean true or false values</li>
  <li>Drop down lists that allows selection from a list of fixed enum values</li>
  <li>Constrained numeric text entry</li>
  <li>Form fields that enforce a regular expression matching of input from a
<code class="language-plaintext highlighter-rouge">pattern</code> constraint</li>
</ul>

<p>However, this only covers “syntactic” or static field-level validation.
Often, an API will also have <em>business rules</em> that the client must
follow. Secure API services will enforce those business rules in the API
operations - for example:</p>

<ul>
  <li>Parse the options and (JSON) request body and return a 400 Bad Request if any of the request data is malformed (i.e. does not satisfy the constraints of the operation—such as required body or required parameters—or all the JSON Schemas associated with the operation’s parameters or request body)</li>
  <li>Verify that the caller passes valid Authorization to the API call, and return <strong>401 Unauthorized</strong> if not</li>
  <li>Verify that the caller is authorized to perform the API operation, and return a <strong>403 Forbidden</strong> error if not.</li>
  <li>Verify the state of the application and return <strong>409 Conflict</strong> if the operation would put the application into an inconsistent state</li>
  <li>Verify the semantics of the request body and return a <strong>422 Unprocessable Content</strong> error if the request is incomplete, inconsistent, or otherwise invalid</li>
</ul>

<p>However, such problem responses only occur “after the fact” - they are returned after the client has made an API call. Many of these checks cannot be made by the client at all—for example, the client cannot validate a OAuth2 access token.</p>

<p>Can the API help the client prevent errors by performing business logic
and other validation for the client, so that such business rules do not
have to be embedded in the client?</p>

<p>One pattern is to extend the API operations with a <em>dry run</em> feature. A
dry run is a variant of the API operation which performs all (and only)
the validation performed by the full operation, but does not execute the
associated behavior. As such, it will return the same
400/401/403/409/422 that the full operation would return, allowing the
client to highlight invalid form data or otherwise correct the problem.
The client can use dry run operations incrementally as the user fills out
a form, and disable the “Save” or “Next” or “Submit” or similar UI controls if
there are validation errors.</p>

<p>One way to implement a dry run is to create a separate “validation”
operation for each API operation. This has the significant disadvantage
of greatly increasing the footprint (size) of the API and adding a lot
of duplication.</p>

<p>Rather than duplicate operations to add sibling validation operations,
another approach is to add a</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>?dryRun=true
</code></pre></div></div>

<p>query parameter to the operations. When used, the operation can return <strong>204 No Content</strong> if the request contains no problems. The <code class="language-plaintext highlighter-rouge">dryRun</code> parameter acts as a “short circuit” in the API operation. The implementation performs the full validation it would normally do before executing the desired behavior, but then stops before actually executing anything other than the validation.</p>

<p>This pattern has a small impact on the API footprint compared to making
sibling (duplicate) validation operations. A smaller footprint makes the API easier
to read and understand. It is also a good use of the <a href="/2023/04/09/dont-repeat-yourself-when-designing-apis">DRY principal</a>
, since you do not have to duplicate the definition of all the operation
request parameters and request bodies, which opens up the chance for
them to become out of sync.
<em>You do not have to invent a new operation ID or create a new API path
for each operation.</em></p>

<p>For example, here is how to add a dryRun query parameter to the OpenAPI
definition, within the createCharacter operation to create a new
character in the Chain Links sample API:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">paths</span><span class="pi">:</span>
  <span class="s1">'</span><span class="s">/characters'</span><span class="err">:</span>
    <span class="na">post</span><span class="pi">:</span>
      <span class="na">title</span><span class="pi">:</span> <span class="s">Create a Character</span>
      <span class="na">description</span><span class="pi">:</span> <span class="pi">&gt;-</span>
        <span class="s">Create a new Character. Use ?dryRun=true to perform validation</span>
        <span class="s">of the data without actually creating a character.</span>
      <span class="na">operationId</span><span class="pi">:</span> <span class="s">createCharacter</span>
      <span class="na">parameters</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="na">$ref</span><span class="pi">:</span> <span class="s1">'</span><span class="s">$/components/parameters/dryRunQueryParam'</span>
          <span class="na">description</span><span class="pi">:</span> <span class="pi">&gt;-</span>
            <span class="s">If `true`, this operation only validates the request and</span>
            <span class="s">it's data but does not actually create a character.</span>
            <span class="s">The operation returns one of the defined 4XX errors</span>
            <span class="s">if there are any problems, or</span>
            <span class="s">returns 204 if there are no problems.</span>
      <span class="na">security</span><span class="pi">:</span>
        <span class="s">...</span>
      <span class="na">responses</span><span class="pi">:</span>
        <span class="s1">'</span><span class="s">204'</span><span class="err">:</span>
           <span class="na">description</span><span class="pi">:</span> <span class="pi">&gt;-</span>
             <span class="s">No Content. There are no validation errors</span>
             <span class="s">with the request data.</span>
        <span class="s1">'</span><span class="s">201'</span><span class="err">:</span>
           <span class="na">description</span><span class="pi">:</span> <span class="s">Created</span>
           <span class="s">...</span>
<span class="na">components</span><span class="pi">:</span>
  <span class="na">parameters</span><span class="pi">:</span>
    <span class="na">dryRunQueryParam</span><span class="pi">:</span>
      <span class="na">name</span><span class="pi">:</span> <span class="s">dryRun</span>
      <span class="na">in</span><span class="pi">:</span> <span class="s">query</span>
      <span class="na">schema</span><span class="pi">:</span>
        <span class="na">type</span><span class="pi">:</span> <span class="s">boolean</span>
        <span class="na">default</span><span class="pi">:</span> <span class="no">false</span>
      <span class="na">description</span><span class="pi">:</span> <span class="pi">&gt;-</span>
        <span class="s">If `true`, this operation only validates the request and</span>
        <span class="s">it's data but does not execute the remainder of the request.</span>
        <span class="s">The operation returns one of the defined 4XX errors</span>
        <span class="s">if there are any problems, or</span>
        <span class="s">returns 204 if there are no problems.</span>
</code></pre></div></div>

<p>It is hard to make a completely generic dryRun parameter component
because the description should be specific to each operation where it is
used. In this case, I’ve used a component parameter <code class="language-plaintext highlighter-rouge">dryRunQueryParam</code>,
but provided a context-specific description of the <code class="language-plaintext highlighter-rouge">dryRun</code> parameter
for the <code class="language-plaintext highlighter-rouge">createCharacter</code> operation.</p>

<p>There is another API pattern that addresses these problems in a completely different way. The definition of a true REST API — Level 3 in the Richardson Maturity Mode — is <em>Hypermedia as the Engine of API State</em>, or HATEOAS. An important component of HATEOAS is “code on demand”, whereby the API service <em>returns code to the client</em> which can implement application logic. This can include performing some business logic checks/validation without such business logic being hard-coded in the client. I’ll tackle HATEOAS in the future.</p>
<hr />

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><category term="the-language-of-api-design" /><category term="api-design-patterns" /><summary type="html"><![CDATA[Techniques for API Request Validation]]></summary></entry><entry><title type="html">API Naming Patterns</title><link href="https://apidesignmatters.org/2024/07/15/api-naming-patterns.html" rel="alternate" type="text/html" title="API Naming Patterns" /><published>2024-07-15T18:00:00+00:00</published><updated>2024-07-15T18:00:00+00:00</updated><id>https://apidesignmatters.org/2024/07/15/api-naming-patterns</id><content type="html" xml:base="https://apidesignmatters.org/2024/07/15/api-naming-patterns.html"><![CDATA[<blockquote>
  <p>Patterns for naming things in APIs</p>
</blockquote>

<p>While <a href="/2024/06/17/oh-crud">CRUD</a>
may be the most common pattern in RESTful APIs, how to name things sure seems to be the most talked about.</p>

<p>Next up in the <a href="/api-design-patterns">API Design Patterns</a> series on API Design Matters, I’d like to present
a common pattern for managing API resources.</p>

<p>Certainly, one can name API elements without following any
pattern…. that will likely yield unfavorable results. As I noted
in my
<a href="/2024/04/11/the-art-of-api-design">The Art of API Design</a>
presentation at the 2024 <em>Nordic APIs Austin API Summit</em>, you could get creative and start using musical notes or Greek letters to name things… but that will hinder the usability of the API. In other words, applying consistent naming patterns will increase the usability of your API… and that won’t hurt adoption.</p>

<blockquote>
  <p>Welcome to the next article in <em>The Language of API Design</em> series.
Rather than jumping into the middle of this series, I encourage new
visitors start by reading
<a href="/the-language-of-api-design">The Language of API Design</a>
and scanning previous posts in the series.</p>
</blockquote>

<p><img src="/assets/img/API-Naming-Patterns.png" alt="alt text" /></p>

<p>Matthew Reinbold posted in <a href="https://netapinotes.com/">Net API News</a> in September 2023 about
<a href="https://netapinotes.com/the-necessity-of-naming-in-apis/">The Necessity of Naming in APIs</a>:</p>

<blockquote>
  <p>“naming should convey the API producer’s mental model to many consumers with minimal fuss” — Matthew Reinbold</p>
</blockquote>

<blockquote>
  <p>“To lower the cognitive overhead required to integrate with your API,
you must consider naming design issues. It is the #1 thing that an API
producer can do to improve a design, always.” — Matthew Reinbold</p>
</blockquote>

<p>Matthew lists serval factors that contribute to the long-held (and
justifiable) belief that naming is hard, then recommends a book,
<a href="https://leanpub.com/naming-things?ref=netapinotes.com">Naming Things: The Hardest Problem in Software Engineering</a>
by Tom Benner.</p>

<p>So there is a lot of good advice on choosing domain names for your API.
I’m going to step back and suggest naming patterns in APIs to improve
the <em>developer experience</em>. Using consistent naming patterns (or using
any pattern consistently, when it is the right pattern) will help lessen
the cognitive load when others try to adopt your API. But consistent
naming will also help you in the design process—basically, a
naming pattern serves as a preemptive design decision that removes the
need to make lots of similar decisions in the rest of the API design
process.</p>

<p>For example, here is a list of the important (OpenAPI) API elements that require a name from the API designer:</p>

<ul>
  <li>Path elements
    <ul>
      <li>static path elements</li>
      <li>dynamic path elements - path parameters</li>
    </ul>
  </li>
  <li>Operation IDs</li>
  <li>Requests and Response Headers</li>
  <li>Query Parameters</li>
  <li>Schemas
    <ul>
      <li>schema names</li>
      <li>object property names</li>
      <li>string enumerations</li>
    </ul>
  </li>
  <li>Response objects</li>
  <li>Parameter objects</li>
  <li>Security Schemes</li>
  <li>Security scopes</li>
</ul>

<p>With each name, you have a some important name attributes to consider:</p>

<ul>
  <li>Style — do you use snake_case, <em>camelCase</em>, <em>PascalCase</em>,
<em>kebob-case</em> (something else?)</li>
  <li>Is the name <em>case sensitive</em> or <em>case insensitive</em>? Both OpenAPI and
HTTP sort of make this decision for you - most names in the OpenAPI
Specification are <em>case sensitive</em>. However, HTTP says that <em>header
names</em> are <em>case insensitive</em>. The convention adopted in many
revisions of the HTTP standards are to use <em>Title-Kebab-Case</em> for
headers, such as <code class="language-plaintext highlighter-rouge">Content-Type</code>, <code class="language-plaintext highlighter-rouge">Content-Length</code>, <code class="language-plaintext highlighter-rouge">Retry-After</code>, and
so on.</li>
</ul>

<p>Rather than defining a separate naming rule or pattern for each
category (I count 14 naming categories above), I have adopted a meta rule for API design: Unless otherwise
indicated, use <em>camelCase</em> style for all names, with the exception of
header names, which should follow the <em>Title-Kebab-Case</em> style described above.
(Every rule needs an exception, so that you can claim a small bit of
edginess or sense of rebelliousness.) I prefer using <em>camelCase</em> because
such names can be used as programming language identifiers in most
programming languages without transformation rules, and OpenAPI also
uses it throughout (for example <code class="language-plaintext highlighter-rouge">operationId</code>, <code class="language-plaintext highlighter-rouge">securitySchemes</code>,
<code class="language-plaintext highlighter-rouge">requestBodies</code>, etc. — perhaps for the same reason :-) )</p>

<p>This does not cover <em>all</em> naming situations. Heres a few more naming
patterns—beyond the purely syntactic style pattern— that I
have adopted:</p>

<h2 id="url-paths">URL Paths</h2>

<ul>
  <li>I use plural names for the domain resource (entity) collections, such
as (in our API Design Matters Chain Links sample application’s domain
example): <code class="language-plaintext highlighter-rouge">/chains</code>, <code class="language-plaintext highlighter-rouge">/chainLinks</code>, <code class="language-plaintext highlighter-rouge">/authors</code>, <code class="language-plaintext highlighter-rouge">/universes</code>, <code class="language-plaintext highlighter-rouge">/characters</code>,
etc. (Note how the compound-word resource term “chain link” becomes
<code class="language-plaintext highlighter-rouge">chainLink</code> via the <em>camelCase</em> style). Others prefer using kebab case for
path elements (i.e. `chain-links). This is perfectly valid, although it
deviates from the “one pattern to rule them all” that I prefer. This is
a matter of preference and style, so <em>choose one rule and use it
consistently throughout your API</em>.</li>
  <li>For path parameters which indicate the unique resource ID of an
instance within a collection, I use a <code class="language-plaintext highlighter-rouge">&lt;resourceName&gt;Id</code> naming pattern:
<code class="language-plaintext highlighter-rouge">/chains/{chainId}</code> , <code class="language-plaintext highlighter-rouge">/chainLinks/{chainLinkId}</code>, <code class="language-plaintext highlighter-rouge">/authors/{authorId}</code>,
<code class="language-plaintext highlighter-rouge">/universes/{universeId}</code>, <code class="language-plaintext highlighter-rouge">/characters/{characterId}</code>, and so on.</li>
</ul>

<h2 id="operation-ids">Operation IDs</h2>

<p>The <code class="language-plaintext highlighter-rouge">operationId</code> assigned define in each operation object is often used
in code generation as the name of a function or method to invoke the
operation. Thus, I start all <code class="language-plaintext highlighter-rouge">operationId</code> names with direct present-tense
imperative verbs, such as <code class="language-plaintext highlighter-rouge">listAuthors</code>, <code class="language-plaintext highlighter-rouge">createUniverse</code>, <code class="language-plaintext highlighter-rouge">getCharacter</code> etc. I use <code class="language-plaintext highlighter-rouge">list</code>
for operations that return lists or collections of API resources and <code class="language-plaintext highlighter-rouge">get</code> for
operations which return individual instances within collections or other
non-collection resources.</p>

<h2 id="model-schemas">Model Schemas</h2>

<p>The model schemas in APIs are the names of <em>things</em> and thus should use
<em>nouns</em> or <em>noun phrases</em>, such as author, <code class="language-plaintext highlighter-rouge">character</code>, <code class="language-plaintext highlighter-rouge">universe</code>,
<code class="language-plaintext highlighter-rouge">chain</code>, and <code class="language-plaintext highlighter-rouge">chainLink</code>.
For convenience thoughout <em>API Design Matters</em>, I’ll use a generic <em>camelCase</em>
placeholder <code class="language-plaintext highlighter-rouge">{resourceName}</code> for the name of an API resource when
talking about naming patterns, not about a specific API resource. The case
here is significant. For example, for the “chain link” domain resource
for the Chain Links API, <code class="language-plaintext highlighter-rouge">{resourceName}</code> is <code class="language-plaintext highlighter-rouge">chainLink</code> and <code class="language-plaintext highlighter-rouge">{ResourceName}</code>
is <code class="language-plaintext highlighter-rouge">ChainLink</code>.</p>

<p>Here are the API naming patterns for model schemas (used in request and
response bodies):</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">new{ResourceName}</code> is the name of the model schema used (via a <code class="language-plaintext highlighter-rouge">POST</code> operation) to create
a new instance in the <a href="/2023/08/27/getting-creative-with-openapi">create</a>
operation. Example: <code class="language-plaintext highlighter-rouge">newChainLink</code> is the request body to create a new
chain link.</li>
  <li><code class="language-plaintext highlighter-rouge">{resourceName}Patch</code> is the name of the model schema used for the for
a <code class="language-plaintext highlighter-rouge">PATCH</code> operation request body. Example: <code class="language-plaintext highlighter-rouge">chainLinkPatch</code> is the request body to patch
an existing chain link.</li>
  <li><code class="language-plaintext highlighter-rouge">{resourceName}Update</code> is the name of the model schema for the <code class="language-plaintext highlighter-rouge">PUT</code>
operation request body to replace a resource with a completely new representation.</li>
  <li><code class="language-plaintext highlighter-rouge">{resourceName}</code> is the name of the model schema normally returns from
a GET operation, or in the response from the create or patch or
replace  operation, such as <code class="language-plaintext highlighter-rouge">chainLink</code>.</li>
</ul>

<p>By applying these model schema naming patterns with the operation ID and path element patterns, larger aggregate patterns become evident.</p>

<p>To create a resource:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST .../{pluralResourceName}
operationId: create{ResourceName}
request body model schema: {newResourceName}
response body model schema: {resourceName}
</code></pre></div></div>

<p>For example:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST .../characters
operationId: createCharacter
request body model schema: newCharacter
response body model schema: character
</code></pre></div></div>

<h2 id="property-names">Property Names</h2>

<p>In general, the names of properties in an object model should use
the names from your domain model and ubiquitous language. However, there are a number
of commonly repeated property names which pop up, regardless of domain.
Having “reserved” property names as part of your API pattern language
can guide your consistent API design:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">id</code> — the unique identifier (string ID) for a resource, often
automaticalluy assigned by the API service in the <code class="language-plaintext highlighter-rouge">POST</code> operation that creates a resource. This <code class="language-plaintext highlighter-rouge">id</code> is used in the <code class="language-plaintext highlighter-rouge">.../{pluralResourceName}/{resourceName}Id</code> resource path to access the instance resource within the collection, such as <code class="language-plaintext highlighter-rouge">.../characters/{characterId}</code> or <code class="language-plaintext highlighter-rouge">.../authors/{authorId}</code></li>
  <li><code class="language-plaintext highlighter-rouge">createdAt</code> is an
<a href="https://datatracker.ietf.org/doc/html/rfc3339">RFC 3339</a> <code class="language-plaintext highlighter-rouge">date-time</code>
when a resource was created.</li>
  <li><code class="language-plaintext highlighter-rouge">updatedAt</code> is the <code class="language-plaintext highlighter-rouge">date-time</code> the resource was last updated with a
<code class="language-plaintext highlighter-rouge">PUT</code> or <code class="language-plaintext highlighter-rouge">PATCH</code> or other transformation operation. In general, I
suggest using <code class="language-plaintext highlighter-rouge">{event}At</code> for <code class="language-plaintext highlighter-rouge">date-time</code> properties and <code class="language-plaintext highlighter-rouge">{eventAt}On</code> for
<code class="language-plaintext highlighter-rouge">date</code> properties when the time of day is too precise and only the
date is needed.</li>
  <li>The property <code class="language-plaintext highlighter-rouge">name</code> is for resources which have names (often names
which people assign to them); <code class="language-plaintext highlighter-rouge">label</code> for resources which have
slightly longer word-phrase labels that are displayed in the user
interface; and <code class="language-plaintext highlighter-rouge">description</code> for resources which allow longer
sentence-length or paragraph descriptions).</li>
</ul>

<h2 id="meta-patterns">Meta Patterns</h2>

<h3 id="name-everything">Name Everything</h3>

<p>My preference is to provide names for <em>all</em> API elements, especially
schemas — avoid using anonymous nested schemas (i.e. if a property
<code class="language-plaintext highlighter-rouge">p</code> within an object schema <code class="language-plaintext highlighter-rouge">s</code> is defined by another object schema (or
array of objects), do not define the schema for <code class="language-plaintext highlighter-rouge">s</code> in line. Instead,
extract them to a <em>named schema</em>. This is important for code generation
(Software Development Kits or SDKs) for your API, as different vendors
choose different “automatic” naming strategies for any anonymous/unnamed
schemas, and this can diminish usability of the SDK and therefore the
API. Such auto-generated names can often be overly long and cumbersome
because they tend to be derived from the context.</p>

<p>This applies not only to schemas nested inside other object schemas or
array item schemas, but to response object schemas, request body
schemas, parameters, and subschemas used schema composition with <code class="language-plaintext highlighter-rouge">allOf</code>.</p>

<p>Naming the schemas also makes it much easier to reuse a schema later,
and helps prevent code duplication and “API drift” — For example,
if someone reading the API later sees the same object structure with the
same four properties defined two or  more times, natural question arise:</p>

<ol>
  <li>Are these the same structures?</li>
  <li>If not, why not?</li>
  <li>Is the similarity accidental?</li>
  <li>What is different about them?</li>
</ol>

<p>Naming such schemas helps has several benefits<a id="footnote-1-ref"></a><a href="#footnote-1"><sup>1</sup></a>
:</p>

<ul>
  <li>It reveals your intention</li>
  <li>It eliminates the need for such questions about your design</li>
  <li>It removes the need for copy and paste (and copy and paste errors – see <a href="/2023/04/09/dont-repeat-yourself-when-designing-apis">Don’t Repeat Yourself When Designing APIs</a>)</li>
  <li>It makes future maintenance and API evolution easier</li>
</ul>

<h3 id="use-widely-recognized-domain-names--your-ubiquitous-language">Use widely recognized domain names : your ubiquitous language</h3>

<p>If you have used the <a href="https://addrprocess.com/">ADDR process</a> or
domain-driven design and created a ubiquitous language—especially one
that is driven by external API consumers and feedback, that is a great
starting point for the names in your API. I encourage you to review your
API domain analysis and your API Domain’s
<a href="/2023/02/15/api-design-first-is-not-api-design-first">ubiquitous language</a>
and choose names from that common language, provided they are clear and
not based on jargon that is not really part of the domain.</p>

<h3 id="use-standard-names">Use Standard Names</h3>

<p>When there is an existing internet standard, use the names defined by that standard. This begins with the HTTP standard (for example, for header names such as <code class="language-plaintext highlighter-rouge">Content-Type</code>, <code class="language-plaintext highlighter-rouge">Accept</code>, <code class="language-plaintext highlighter-rouge">Accept-Language</code>, <code class="language-plaintext highlighter-rouge">Retry-After</code>), media type names such as <code class="language-plaintext highlighter-rouge">application/json</code>, <code class="language-plaintext highlighter-rouge">application/pdf</code>, <code class="language-plaintext highlighter-rouge">text/plain</code>, etc.</p>

<p>If you are using <code class="language-plaintext highlighter-rouge">application/problem+json</code> (<a href="https://www.rfc-editor.org/rfc/rfc9457.html">RFC 9457</a>) representation for API problems/errors, use the property names it defines (<code class="language-plaintext highlighter-rouge">type</code>, <code class="language-plaintext highlighter-rouge">status</code>, <code class="language-plaintext highlighter-rouge">title</code>, <code class="language-plaintext highlighter-rouge">detail</code>, <code class="language-plaintext highlighter-rouge">instance</code>). ( <a href="/2023/03/26/your-api-has-problems.-deal-with-it">Your API Has Problems. Deal With It.</a> )</p>

<p>Few things will irritate a developer more than an API which does not
follow existing standards.</p>

<h2 id="anti-patterns">Anti-Patterns</h2>

<h3 id="avoid-brand-names">Avoid Brand Names</h3>

<p>One thing that I’ve learned over more than 35 years working in corporate software development is to <em>avoid using brand names or marketing names</em> in API element names.</p>

<p>Brand and marketing names change over time—it is a fact of
software development. If you incorporate brand/marketing names into an
API, then the API becomes semi-obsolete when the name changes.</p>

<p>During my time working at one organization, I saw a single product renamed three separate times.</p>

<h3 id="always-avoid-redundancy-and-repetition">Always Avoid redundancy and repetition</h3>

<p>When naming properties inside a model schema, avoid repeating the model name in the model schema’s property names. For example, use <code class="language-plaintext highlighter-rouge">universe.id</code>, <code class="language-plaintext highlighter-rouge">character.name</code>, and <code class="language-plaintext highlighter-rouge">author.name</code>, not <code class="language-plaintext highlighter-rouge">universe.universeId</code>, <code class="language-plaintext highlighter-rouge">character.characterName</code> or <code class="language-plaintext highlighter-rouge">author.authorName</code>.</p>

<h2 id="avoid-jargon">Avoid Jargon</h2>

<p>Another anti-pattern is using jargon, especially if such jargon derives
from internal implementation choices such as code names, legacy systems,
or terms that have seeped in from other domains. If the term is not in
common use with a clear meaning understood by most domain practitioners
and/or your API consumers, that is a strong hint that the name requires more
thought. Better than writing documentation explaining why you chose a
name, it’s better off to completely remove the need to ask such
questions.</p>

<h2 id="summary">Summary</h2>

<p>I’ve presented a small catalog of reusable patterns for naming elements
of APIs. I hope they work for you, or at least inspire you to create
your own patterns to increase the consistency and predictability of your
APIs.</p>

<hr />

<p><a id="footnote-1"></a><a href="#footnote-1-ref"><sup>1</sup></a>
Naming things gives you power over them. Or so I’m told.</p>

<p><a href="https://github.com/apidesignmatters/apidesignmatters.github.io/discussions">Join the discussion</a></p>

<p><strong>Note</strong>: This article was originally published on the auhor’s <em>API Design Matters</em> Substack.</p>]]></content><author><name></name></author><category term="the-language-of-api-design" /><category term="api-design-patterns" /><summary type="html"><![CDATA[Patterns for naming things in APIs]]></summary></entry></feed>