<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://apihandyman.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://apihandyman.io/" rel="alternate" type="text/html" /><updated>2024-10-12T14:37:54+00:00</updated><id>https://apihandyman.io/feed.xml</id><title type="html">API Handyman</title><subtitle>Hi! I&apos;m Arnaud Lauret, the API Handyman and author of The Design of Web APIs. I like to share what I do, struggle with, learn, and teach while working in the API space.</subtitle><author><name>Arnaud Lauret</name></author><entry><title type="html">How to check the presence of an element with Spectral</title><link href="https://apihandyman.io/how-to-check-the-presence-of-an-element-with-spectral/" rel="alternate" type="text/html" title="How to check the presence of an element with Spectral" /><published>2022-11-23T00:00:00+00:00</published><updated>2022-11-23T00:00:00+00:00</updated><id>https://apihandyman.io/how-to-check-the-presence-of-an-element-with-spectral</id><content type="html" xml:base="https://apihandyman.io/how-to-check-the-presence-of-an-element-with-spectral/"><![CDATA[<p>When linting an OpenAPI document (or any other JSON or YAML document with Spectral), the hardest part is ensuring you’re not missing your target and so be sure that expected checks will be done. In this post, we’ll see how to be sure a Spectral rule will be triggered when checking the presence of an element.
<!--more--></p>

<p>In an OpenAPI document, the description of the API located in the info section is not mandatory. A document without that information is syntactically valid. But from an API documentation perspective, that can be an issue. So let’s create a rule that will enforce providing this information.</p>

<p><em>If you’re unfamiliar with what Spectral is and need guidance to install and run it, check my <a href="lint-apis-with-spectral">Lint APIs with Spectral post</a>.</em></p>

<h1 id="relying-only-on-given-will-not-work">Relying only on “given” will not work</h1>

<p>The following <code>info-description</code> rule is intended to check there’s a description of the API in an OpenAPI document. The <code>given</code> JSON path targets the <code>description</code> property in the <code>info</code> object, which is located at the document’s root (<code>$</code>). The rule’s <code>then</code> section uses the <code>truthy</code> function to check that <code>description</code> is present and not empty.</p>

<div class="card card-code text-white bg-dark border-dark">
  
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">miss-target.spectral.yaml</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="1"><code class="code-block">rules:
  info-description:
    given: $.info.description
    then:
      function: truthy</code></pre>
  </div>
</div>

<p>If we run the Spectral CLI on the following OpenAPI document, we expect to detect an <code>info-description</code> problem.</p>

<div class="card card-code text-white bg-dark border-dark">
  
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">no-description.openapi.yaml</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="1"><code class="code-block">openapi: &#39;3.0.0&#39;

info:
  title: An API without description
  version: &#39;1.0&#39;

paths: {}</code></pre>
  </div>
</div>

<p>Unfortunately, no problem has been detected!</p>

<div class="card card-code text-white bg-dark border-dark">
  
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">Spectral CLI</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-bash line-numbers code-copy" data-start="1"><code class="code-block">&gt; spectral lint -r miss-target.spectral.yaml no-description.openapi.yaml
No results with a severity of &#39;error&#39; found!</code></pre>
  </div>
</div>

<h1 id="when-does-a-rule-is-triggered">When does a rule is triggered?</h1>

<p>What happened? The checks (<code>then</code>) of a Spectral rule will be executed only if the <code>given</code> path returns a value, which is not the case here. There’s no description property in the info object of the OpenAPI document, the <code>$.info.description</code> JSON path returns nothing.  So, how can we check that <code>description</code> is present?</p>

<h1 id="using-field-will-work">Using “field” will work</h1>

<p>We need to target the present info object to check that description is present. And <code>then</code>, we’ll apply the <code>truthy</code> function of the <code>field</code> “description.”</p>

<div class="card card-code text-white bg-dark border-dark">
  
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">hit-target.spectral.yaml</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="1"><code class="code-block">rules:
  info-description:
    given: $.info
    then:
      field: description
      function: truthy</code></pre>
  </div>
</div>

<p>This time, the problem has been detected!</p>

<div class="card card-code text-white bg-dark border-dark">
  
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">Spectral CLI</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-bash line-numbers code-copy" data-start="1"><code class="code-block">&gt; spectral lint -r hit-target.spectral.yaml no-description.openapi.yaml

/some/path/no-description.openapi.yaml
 3:6  warning  info-description  &quot;info.description&quot; property must be truthy  info

✖ 1 problem (0 errors, 1 warning, 0 infos, 0 hints)</code></pre>
  </div>
</div>

<h1 id="but-check-parents-if-needed">But check parents if needed</h1>

<p>But is that enough? What if <code>info</code> is not present like in the following OpenAPI sample document? Same issue as at the beginning of this post. Our <code>info-description</code> rule will not be triggered so that no problem will be detected. I let you write an <code>info</code> rule to ensure the <code>info</code> object is present.</p>

<div class="card card-code text-white bg-dark border-dark">
  
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">no-info.openapi.yaml</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="1"><code class="code-block">openapi: &#39;3.0.0&#39;

paths: {}</code></pre>
  </div>
</div>

<p>But, in that specific OpenAPI use case, we don’t have to worry about <code>info</code> being absent. Indeed, the <code>info</code> object is mandatory in an OpenAPI document, so the document above is syntactically invalid. But you may have noticed that Spectral didn’t say anything about this when testing your <code>info</code> rule. It’s because we didn’t ask Spectral to do that OpenAPI syntax check. We’ll see how to do so in an upcoming post.</p>]]></content><author><name>Arnaud Lauret</name></author><category term="post" /><summary type="html"><![CDATA[When linting an OpenAPI document (or any other JSON or YAML document with Spectral), the hardest part is ensuring you’re not missing your target and so be sure that expected checks will be done. In this post, we’ll see how to be sure a Spectral rule will be triggered when checking the presence of an element.]]></summary></entry><entry><title type="html">The contributions and limitations of API contract linting in API governance</title><link href="https://apihandyman.io/the-contributions-and-limitations-of-api-contract-linting-in-api-governance/" rel="alternate" type="text/html" title="The contributions and limitations of API contract linting in API governance" /><published>2022-11-15T00:00:00+00:00</published><updated>2022-11-15T00:00:00+00:00</updated><id>https://apihandyman.io/the-contributions-and-limitations-of-api-contract-linting-in-api-governance</id><content type="html" xml:base="https://apihandyman.io/the-contributions-and-limitations-of-api-contract-linting-in-api-governance/"><![CDATA[<p>As API governance often rhymes with “policy enforcement,” API contract linting can be seen as the panacea of API governance: it can be used to ensure API contracts conform to pre-defined rules.
But both API linting and API governance are more than that.
Let’s discover the contributions and limitations of API contract linting in API governance. 
<!--more--></p>

<h1 id="api-linting-and-api-governance">API linting and API governance</h1>

<p>Linting an API contract consists in analyzing its interface to “detect bugs, stylistic errors, and suspicious constructs” (like the original <a href="https://en.wikipedia.org/wiki/Lint_(software)">linting</a>). That can be done, for instance, with a tool called <a href="/lint-apis-with-spectral/">Spectral</a> to analyze <a href="/what-is-the-openapi-specification/">OpenAPI</a> documents, which contain standard and machine-readable API definitions.</p>

<p>As explained in previous articles, API governance aims to maximize the value created by APIs in alignment with the organization’s goals and constraints. It does this by enabling and facilitating people to work together on the right APIs in the right way. How can a linter contribute or not to that vision?</p>

<h1 id="it-helps-create-apis-almost-right">It helps create APIs (almost) right</h1>

<p>A linter, like Spectral, can participate in creating APIs right, following the organization’s guidelines, but incompletely. </p>

<p>For instance, it’s simple to check in an OpenAPI document that:</p>
<ul>
  <li>All schema properties are camel-cased.</li>
  <li>Each operation returns a successful response.</li>
  <li>Each operation returns the usual errors like 401 and 500.</li>
  <li>Error responses use the standard Error schema.</li>
</ul>

<p>Such simple aspects will always be right once checked with Spectral (and fixed).</p>

<p>If we go a bit further, it is also possible to check that:</p>
<ul>
  <li>An operation returning a list proposes pagination and search filters.</li>
  <li>An operation with a “search customers” summary operation is designed with the correct “search” pattern.</li>
</ul>

<p>But this will have some limits. Most of the time, it will still be up to humans to choose the correct design pattern.
If the linter can detect it, it is at least possible to check it is fully used.</p>

<h1 id="it-cant-help-to-create-the-right-apis">It can’t help to create the right APIs</h1>

<p>If a linter, such as Spectral, can more or less tell if an API has the correct look and feel, it will probably never be able to tell:</p>
<ul>
  <li>If “name” is the right piece of data to request or return to achieve some business rules.</li>
  <li>If “search customers” is the proper operation to add to an existing API to fulfill some needs.</li>
  <li>If the “customer directory” API is the correct API to create to fulfill some local needs or to help the organization achieve its goals.</li>
</ul>

<p>An API contract linter will never replace an API review done by human beings to ensure the API created is the right one, aligned with the organization’s goals.</p>

<h1 id="its-a-policy-enforcer-a-guide-and-an-enabler">It’s a policy enforcer, a guide, and an enabler</h1>

<p>An API contract linter can be used as an enforcer (a person or group that compels observance of or compliance with a law, rule, or obligation) enforcing API governance policies.
Linting can be integrated into CI/CD processes to check and block the build and deployment of APIs having a contract considered invalid.
But you can use it in more clever and constructive ways.</p>

<p>It can guide API designers if it is integrated earlier into the API design process and tools.
It will help API designers make design decisions seamlessly without losing momentum.
Designers will learn and follow the rules as time passes without realizing it.</p>

<p>It’s an enabler. It facilitates API design reviewers’ tasks. No more hours, even days, lost painfully checking that all property names of all schemas are camel-cased.
They can even create more fine and custom rules to detect patterns that should be discussed during an API design review.</p>

<h1 id="not-the-panacea-but-still-quite-helpful">Not the panacea, but still quite helpful</h1>

<p>So, API contract linting will only take care of some parts of API governance, but what it can do is pretty interesting.
It helps to create APIs almost right, sharing a similar look and feel.
As a last resort, it can be the guardian before deployment, but before that, it can be a teacher, guiding API designers and facilitating the work of API design reviewers.</p>]]></content><author><name>Arnaud Lauret</name></author><category term="post" /><summary type="html"><![CDATA[As API governance often rhymes with “policy enforcement,” API contract linting can be seen as the panacea of API governance: it can be used to ensure API contracts conform to pre-defined rules. But both API linting and API governance are more than that. Let’s discover the contributions and limitations of API contract linting in API governance.]]></summary></entry><entry><title type="html">Prefixing or not prefixing property names?</title><link href="https://apihandyman.io/prefixing-or-not-prefixing-property-names/" rel="alternate" type="text/html" title="Prefixing or not prefixing property names?" /><published>2022-11-08T00:00:00+00:00</published><updated>2022-11-08T00:00:00+00:00</updated><id>https://apihandyman.io/prefixing-or-not-prefixing-property-names</id><content type="html" xml:base="https://apihandyman.io/prefixing-or-not-prefixing-property-names/"><![CDATA[<p>Adding a prefix to a name should be carefully weighed because it impacts the overall design of an API, some code, or a specification and its usability for humans and machines. The discussion related to <code>apiResponses</code>, <code>pathResponses</code>, and <code>responses</code> properties in the early design of OpenAPI v4 is a perfect example of that concern.
<!--more--></p>

<h1 id="the-context">The context</h1>
<p>Version 4 (aka. <a href="https://github.com/OAI/moonwalk">Moonwalk</a>) of the <a href="https://apihandyman.io/what-is-the-openapi-specification/">OpenAPI Specification</a> is in its early discussion stage. It breaks everything, and the direction taken is quite promising! This post takes its source in a <a href="https://github.com/OAI/moonwalk/discussions/34">discussion related to <code>apiResponses</code>, <code>pathResponses</code>, and <code>responses</code> properties</a>.</p>

<p>In OpenAPI 3 (and 2), operations’ responses can only be set at the operation level (in <code>responses</code>). Though reusable responses can be created (in <code>components.responses</code>), that still means you have to define, for instance, the <code>401</code> and <code>500</code> responses key and reference the predefined responses (with a <code>$ref = '#/components/responses/&lt;name&gt;'</code>) for each operation. That’s a bit annoying.</p>

<div class="card card-code text-white bg-dark border-dark">
  
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">Responses in OpenAPI 3.1</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="1"><code class="code-block">openapi: &quot;3.1.0&quot;
# ...
paths:
  /resources:
    get:
      responses:
        401:
          $ref: &quot;#/components/responses/Unauthorized&quot;

components:
  responses:
    Unauthorized:
      description: Missing or invalid access token
      # ...</code></pre>
  </div>
</div>

<p>In OpenAPI v4, the new design would allow defining responses at API (<code>apiResponses</code>), path (<code>pathResponses</code>), and operation (<code>responses</code>) levels. That way, the 401 and 500 responses could be set at the API level in <code>apiResponses</code> once and for all operations.</p>

<div class="image ">
    <figure class="figure">
        <img src="/images/prefixing-or-not-prefixing-property-names/moonwalk-responses.jpg" class="figure-img img-fluid" /><figcaption class="figure-caption">Responses in OpenAPI 4 Moonwalk</figcaption></figure>
</div>

<h1 id="the-issue-and-solutions">The issue and solutions</h1>

<p><a href="https://twitter.com/matthewtrask">Matthew Trask</a> was faster than me to start a discussion and point there was something wrong with <code>apiResponse</code>, <code>pathResponse</code>, and (just)<code>responses</code> naming. “Confusing” and “verbose” were his words; I would add “inconsistent.”</p>

<h2 id="no-prefix-at-any-level">No prefix at any level</h2>
<p>As the three <code>apiResponses</code>, <code>pathResponses</code>, and <code>responses</code> describe the same thing (responses) but at different levels (API, path, operation), I expect them to be all named <code>responses</code>. It’s the context/location that tells at which level they apply (parent property name or sibling properties giving a clue about the level).</p>

<p>I use that “avoiding prefix as much as possible” naming strategy because:</p>

<ul>
  <li>Having the same name used for a “thing” favors consistency, understanding, and usability. It’s human-friendly but also (dumb-)machine-friendly: “whatever the level, no need to think, just look for <code>response</code>” vs. “which level is this? then <code>{level}Response</code>”.</li>
  <li>Having shorter names enhance usability and readability.</li>
</ul>

<p>That is well and good, but what if we keep them named as they are?</p>

<h2 id="the-unexpected-consequences-of-adding-a-prefix">The unexpected consequences of adding a prefix</h2>
<p>Keeping a name such as <code>apiResponses</code> vs <code>response</code> implicitly defines a naming pattern that should be applied across all the specification: <code>&lt;location&gt;Thing</code> vs. <code>thing</code>.</p>

<p>So, if, for any reason, the <code>apiResponses</code>, <code>pathResponses</code> would be kept that way, for the sake of consistency, I would argue that:</p>

<ul>
  <li><code>responses</code> which is at the operation level should be renamed <code>operationResponses</code>.</li>
  <li>the <code>parameterSchemas</code> which appears at the path and operation levels should be respectively renames <code>pathParameterSchemas</code> and <code>operationParameterSchemas</code>.</li>
  <li>the <code>contentSchema</code> properties which appears on request and response should be renamed <code>requestContentSchema</code> and <code>responseContentSchema</code>.</li>
  <li>and so on …</li>
</ul>

<p>So adding such a prefix may have consequences across the whole design, it’s like when throwing 💩 in a fan.</p>

<h2 id="but-why-would-someone-do-such-a-terrible-mistake">But why would someone do such a “terrible” mistake?</h2>
<p>The OpenAPI Specification v4 is in the early stage, and the current naming is probably just a “typo,” or a consequence of “that looks clearer on the diagram.”  Maybe it’s just because in current version 3 the property at response level already exists and is (just)<code>responses</code>.</p>

<p>That can happen to anyone, that’s why requesting feedback, doing reviews (and defining guidelines) is important. That helps to fix simple mistakes that have lightly annoying to terrible consequences that you’ll have to live with for eons (well, until the next major version).</p>

<h1 id="api-design-skills-are-useful">API design skills are useful</h1>

<p>I love to see how what I’ve learned designing and reviewing hundreds if not thousands of API can be used in other disciplines like designing a format for instance. The concerns you have to take care of when designing APIs are not new and not only related to APIs. But API becoming first class citizen has put those concerns, such as consistency or user-experience, to the front. And now that’s a concern in everything I do.</p>]]></content><author><name>Arnaud Lauret</name></author><category term="post" /><summary type="html"><![CDATA[Adding a prefix to a name should be carefully weighed because it impacts the overall design of an API, some code, or a specification and its usability for humans and machines. The discussion related to apiResponses, pathResponses, and responses properties in the early design of OpenAPI v4 is a perfect example of that concern.]]></summary></entry><entry><title type="html">The 4 values of API governance</title><link href="https://apihandyman.io/the-4-values-of-api-governance/" rel="alternate" type="text/html" title="The 4 values of API governance" /><published>2022-10-25T00:00:00+00:00</published><updated>2022-10-25T00:00:00+00:00</updated><id>https://apihandyman.io/the-4-values-of-api-governance</id><content type="html" xml:base="https://apihandyman.io/the-4-values-of-api-governance/"><![CDATA[<p>API governance means policies, institutions, processes, and indicators. But without the alignment, enablement, collaboration, and guidance values in mind, API governance can quickly become a senseless, kafkaesque, and counter-productive API dictatorship, which will slowly but surely kill the organization, or its APIs at the least. 
<!--more--></p>

<p><em>This post’s banner is an illustration from the first page of the Encyclopédie (Encyclopedia or Reasoned Dictionary of Sciences, Arts and Crafts).</em></p>

<h1 id="api-governance-definition">API Governance definition</h1>
<p>I’m continuing my exploration of API governance definition. In my initial post, I attempted to <a href="/attempting-to-define-api-governance/">define API governance</a> and ended up with two definitions. The first helped identify the <a href="/the-4-components-of-api-governance/">components of API governance</a>. The second one helped me identify the values to keep in mind when establishing and conducting proper API governance:</p>

<blockquote>
  <p>API governance is enabling and facilitating people to work together on the right APIs, the right way to maximize the value created by APIs in alignment with the organization’s goals and constraints.</p>
</blockquote>

<p>I identify four values for API governance in the definition above:</p>
<ul>
  <li>Alignment: “right APIs … in alignment with the organization’s goals and constraints.”</li>
  <li>Enablement: “enabling and facilitating.”</li>
  <li>Collaboration: “work together.”</li>
  <li>Guidance: “the right way.”</li>
</ul>

<h1 id="alignment">Alignment</h1>

<p>API governance initiatives must never lose sight of their fundamental objective. And it’s not defining policies, processes, institutions, and indicators to make people respect the API law. The final aim of API governance is to “maximize the value created by APIs in alignment with the organization’s goals and constraints.”</p>

<p>So, every policy, process, indicator, or institution must be carefully weighed regarding how it will contribute to achieving the organization’s goals while complying with its constraints. </p>

<p>Most API design guidelines state, “all APIs must be designed consistently.” Why? Consistent APIs are more user-friendly, meaning integration between systems is faster and costs less money. For public APIs, people will be more willing to use and buy them, so more customers. </p>

<p>The deeper reasons behind each policy, process, indicator, or institution must always lead to the organization’s goals and constraints.  If that’s not the case, don’t bother to put them in place, they’ll only bother everyone, slow the organization and possibly cost money for nothing.</p>

<h1 id="enablement">Enablement</h1>

<p>API governance is not about being the API police blocking and controlling people, making them lose their time. It’s about “enabling and facilitating people to work .. on APIs”.</p>

<p>API governance must have minimal overhead and must not require efforts that would prevent people from creating APIs the right way or at all.</p>

<p>And more than that, an API governance initiative must put, or help to put, any possible thing in place to lower the barrier to API creation—for instance, documentation (of policies and processes), tools, or automation. But API governance can go beyond “just APIs,” helping to put in place an internal API evangelization program or API design training course, for example.</p>

<p>But it must never do in place of people; it must never take their API ownership. It must “teach them how to fish and not bring them fish every day”: favor the spirit of an “API Center of Enablement” that will teach people how to create APIs over an “API Center of Excellence” that could be the unique API factory.</p>

<p>The ultimate goal of any dedicated API governance initiative should even be to disappear: the “API-enabled” people and system being fully autonomous in the end.  </p>

<h1 id="collaboration">Collaboration</h1>

<p>You rarely work alone when you create APIs and even more when you put API governance in place. Different stakeholders with diverse perspectives will be involved. Even when each has the organization’s goals and constraints in mind when defining their policies, processes, and institutions, they may go against each other. If all API stakeholders don’t collaborate to ensure that, as a whole, everything fits together and is still aligned with the organization’s goals and constraints, be ready for dire consequences. </p>

<p>For instance, security policies should be carefully defined to avoid as much as possible to unnecessarily crippling user experience. I remember when it was forbidden to use the DELETE HTTP method to expose API documentation to the outside world or return a meaningful error explaining how to solve the problem caused by an API call.</p>

<p>Without collaboration between all stakeholders, there will be no effective API governance and no effective use of APIs.</p>

<h1 id="guidance">Guidance</h1>

<p>With API governance, policies have to be defined, among other things. It’s a certainty. But these rules and guidelines don’t have to be abstruse, with little explanation of how to apply or implement them. People will need some overall guidance to be sure they use those <em>hundreds</em>, if not more, of rules and guidelines. People will need clear explanations to fix issues when they violate those rules.</p>

<p>People applying policies need to understand them without effort. They will need “cross concerns recipes”: instead of just being an endless separated list of rules (design vs. security, for instance), guidelines can be a list of actionable recipes merging as many concerns as possible, like “how to design a search operation” or “how to upload a file.” Some rules can be automated and integrated into design tools or CI/CD, but their error message must be clear and informative, to help users to fix the issues.</p>

<p>If the user experience is a significant concern when creating API, it must also be the case when implementing API governance. Forget that, and be sure your rules will never be applied correctly if applied at all.</p>

<h1 id="dont-forget-the-fundamental-objectives">Don’t forget the fundamental objectives</h1>

<p>I think that’s a common flaw of every policy-based system to lose sight of why it is put in place. The people implementing them focus on putting policies in place, possibly institutions, processes, and indicators around them, because that’s the objective they have been given; that’s what governance is made of, after all.  But with these values in mind, it may be easier to implement the right governance in the right way.</p>]]></content><author><name>Arnaud Lauret</name></author><category term="post" /><summary type="html"><![CDATA[API governance means policies, institutions, processes, and indicators. But without the alignment, enablement, collaboration, and guidance values in mind, API governance can quickly become a senseless, kafkaesque, and counter-productive API dictatorship, which will slowly but surely kill the organization, or its APIs at the least. ]]></summary></entry><entry><title type="html">The 4 components of API governance</title><link href="https://apihandyman.io/the-4-components-of-api-governance/" rel="alternate" type="text/html" title="The 4 components of API governance" /><published>2022-10-18T00:00:00+00:00</published><updated>2022-10-18T00:00:00+00:00</updated><id>https://apihandyman.io/the-4-components-of-api-governance</id><content type="html" xml:base="https://apihandyman.io/the-4-components-of-api-governance/"><![CDATA[<p>After formally defining API governance relative to IT governance, corporate governance, and governance, let’s dive deeper and describe the four components of API governance: policies, institutions, processes, and indicators.
<!--more--></p>

<p><em>This post banner is a part of the “Figurative system of human knowledge”, the structure that the Encyclopédie (Encyclopedia or Reasoned Dictionary of Sciences, Arts and Crafts) organised knowledge into.</em></p>

<h1 id="api-governance-definition">API governance definition</h1>
<p>In a previous post titled <a href="/attempting-to-define-api-governance/">Attempting to define API governance</a>, I described API governance as follows:</p>

<blockquote>
  <p>API governance is establishing and overseeing decision-making, policies, practices, processes, and institutions to enable an organization’s people to collectively achieve its goals by efficiently taking advantage of private, partner, or public APIs. It aims to align APIs with business and IT strategies, to monitor and maximize the value created from them while identifying and addressing risks and ensuring compliance with regulations.</p>
</blockquote>

<p>According to that previous post and this definition, API governance relies on four main components:</p>
<ul>
  <li>Policies (how)</li>
  <li>Institutions (who)</li>
  <li>Processes (do)</li>
  <li>Indicators (monitor)</li>
</ul>

<h1 id="policies-how">Policies (how)</h1>
<p>API governance’s policies and common practices are repeatable and shared rules and guides which define <strong>how</strong> APIs and API-related work should be done from a wide range of perspectives. This is probably the most known part of API governance, thanks to API design guidelines. API governance is even, unfortunately, too often reduced to this aspect alone, but those policies and common practices are far more than that. </p>

<p>They can cover a wide range of topics impacting the creation and management of APIs across their whole lifecycle, from design (the famous API design guidelines) and security to business models and terms of service. Domain standards or regulations could dictate some of those policies and common practices. For instance, <a href="https://ec.europa.eu/info/law/payment-services-psd-2-directive-eu-2015-2366_en">PSD2</a> Open Banking APIs must follow EU regulators’ requirements and may apply a format such as the <a href="https://www.berlin-group.org/">Berling Group</a> one. And some policies and common practices must also cover API governance itself. For example, it’s essential to define guidelines explaining how to create API design guidelines or how to conduct an API design review.</p>

<h1 id="institutions-who">Institutions (who)</h1>

<blockquote>
  <p>Institution: an organization founded for religious, educational, professional, or social purposes</p>
</blockquote>

<p>The “institutions” mentioned in the API governance’s definition represent <strong>who</strong> works on APIs. These are the different sub-organizations (inside the organization putting API governance in place) that directly or indirectly work on APIs. It comprises two groups, the API governance organizational representation and the various API stakeholders.</p>

<p>The most known and visible group involved in API governance is the API governance organizational representation itself. It can be, for example, a dedicated API CoE (Center of Excellence or Enablement), an API guild (a group of API practitioners scattered across the organization), or both. </p>

<p>The second group, the API stakeholders, are all the sub-organizations (teams, services, business lines, board of directors, …) involved directly or indirectly in creating APIs. These stakeholders can be, for example:</p>
<ul>
  <li>API product teams (the ones actively developing and implementing APIs)</li>
  <li>Security teams (who need to ensure APIs are secure)</li>
  <li>API platform teams (who manage CI/CD pipelines and API gateways)</li>
  <li>Internal API evangelists (who will promote the use of APIs, maybe conduct training sessions)</li>
  <li>Legal teams (who can be involved in API’s terms of services).</li>
</ul>

<h1 id="processes-do">Processes (do)</h1>
<p>“Processes” is how (API-related) institutions (including API stakeholders and API governance representation) <strong>do</strong> APIs and API governance. It encompasses how they will collaborate, interact, apply policies, and react to indicators evolution. It also covers how the API governance representation operates and how the policies are created and modified.</p>

<p>Processes may involve various institutions and be purely human-based, automated, or both. They can also be interdependent. For instance, an API review process may involve business, development, and security teams and rely on human reviews and automated linting. People may check that the API will fulfill the proper business needs, that it is implementable, easy to understand and use, and does not unduly expose sensitive operations or data. And machines may verify that the design respects the organization’s look and feel and proposes authorized security modes. If a limit, an error, or a missing element is detected in design guidelines during the creation of an API, it will trigger the guidelines revision process. The 100% automated API production deployment process could only run if the API review process is OK. </p>

<h1 id="indicators-monitor">Indicators (monitor)</h1>
<p>API governance indicators are used to <strong>monitor</strong> the value created directly or indirectly by APIs and their alignment with the organization’s goals and constraints. As API governance participates in that and aims to impact it, it should also be monitored to evaluate its effectiveness.</p>

<p>Like policies, indicators may cover a wide range of perspectives, from pure API statistics, such as the number of APIs consumed by more than one consumer, to business indicators, such as the number of new customers acquired through APIs, and governance indicators, such as the length of the review process.</p>

<h1 id="it-looks-a-bit-scary-no">It looks a bit scary, no?</h1>
<p>So API governance is composed of policies, institutions, processes, and indicators. But described like this, it looks a bit scary, like API police or an API dictatorship. And that’s indeed a risk if governance is not conducted with the right spirit. That also looks like a massive sum of elements to put in place. Are they all needed with all features right from the start? Hopefully, no. Governance can be put in place step by step. </p>

<p>But these are other stories I’ll keep for later posts. In the meanwhile, don’t forget that more engaging second definition of API governance coming from my <a href="https://apihandyman.io/attempting-to-define-api-governance/">Attempting to define API governance</a> post:</p>

<blockquote>
  <p>API governance is enabling and facilitating people to work together on the right APIs, the right way to maximize the value created by APIs in alignment with the organization’s goals and constraints.</p>
</blockquote>]]></content><author><name>Arnaud Lauret</name></author><category term="post" /><summary type="html"><![CDATA[After formally defining API governance relative to IT governance, corporate governance, and governance, let’s dive deeper and describe the four components of API governance: policies, institutions, processes, and indicators.]]></summary></entry><entry><title type="html">OpenAPI does what Swagger don’t</title><link href="https://apihandyman.io/openapi-does-what-swagger-dont/" rel="alternate" type="text/html" title="OpenAPI does what Swagger don’t" /><published>2022-09-21T00:00:00+00:00</published><updated>2022-09-21T00:00:00+00:00</updated><id>https://apihandyman.io/openapi-does-what-swagger-dont</id><content type="html" xml:base="https://apihandyman.io/openapi-does-what-swagger-dont/"><![CDATA[<p>Let’s compare versions Swagger 2.0 and OpenAPI 3.0, and 3.1 to demonstrate the benefits of the new features introduced by 3.x versions to create more precise, better documented, more practical, and future-proof API contract descriptions.
<!--more--></p>

<h1 id="abstract">Abstract</h1>

<p>It hurts, but though OpenAPI 3 is five years old and has more features, many people still use its previous version: Swagger 2.0. It’s high time that this changes. Inspired by the ‘90s “Sega Does What Nintendon’t” advertising campaign, Arnaud Lauret will compare versions 2.0, 3.0, and 3.1 of the specification, demonstrating the benefits of the new features introduced by 3.x versions to create more precise, better documented, more practical, and future-proof API contract descriptions.</p>

<p>Why do so? Because having a better understanding of the capabilities of the new versions and thus knowing what they are missing will perhaps push users and creators to say goodbye and thank you to Swagger 2.0 and hello to OpenAPI 3.x. It may also help OpenAPI 3.x users discover features they were not aware of.</p>

<h1 id="video">Video</h1>

<div id="WePbF4_7RkY" class="third-party-content third-party-content-youtube">
    <div class="card third-party-content-warning">
        <img class="card-img" src="/images/thirdpartycontents/openapi-does-what-swagger-dont.jpg" alt="Card image" />
        <div class="card-img-overlay d-flex">
            <div class="my-auto mx-auto text-center">
                <p>This content is hosted on youtube.com.</p>
                <p>By showing this third party content you accept YouTube (Google)'s 
                    <a class="privacy-policy" href="https://policies.google.com/privacy" target="_blank">privacy policy</a>.
                </p>
                <form>
                    <a href="javascript:thirdPartyConsent('WePbF4_7RkY', 'youtube')" class="btn btn-primary" role="button">Show third party content</a>
                    <div class="form-check">
                        <input type="checkbox" class="form-check-input third-party-content-remember" />
                        <label class="form-check-label" for="exampleCheck1">Remember my choice</label>
                        <p>(can be changed in <a class="privacy-policy" href="/privacy/">privacy settings</a>)</p>
                      </div>
                </form>
            </div>
        </div>
    </div>
    <div class="iframe-container third-party-content-iframe third-party-content-iframe-disabled">
        <iframe class="iframe-responsive" data-src="https://www.youtube-nocookie.com/embed/WePbF4_7RkY?color=white&amp;theme=light" frameborder="0" allowfullscreen="">
        </iframe>
    </div>
</div>

<h1 id="slidedeck">Slidedeck</h1>

<p><a href="/slidedecks/openapi-does-what-swagger-dont/openapi-does-what-swagger-dont.pdf" download="openapi-does-what-swagger-dont.pdf" class="btn btn-primary" role="button">Download PDF</a>
<a href="/slidedecks/openapi-does-what-swagger-dont/openapi-does-what-swagger-dont.pdf" target="_blank" class="btn btn-primary" role="button">Open PDF</a></p>
<div class="iframe-container">
    <iframe class="iframe-responsive" src="/slidedecks/openapi-does-what-swagger-dont/index.html"></iframe>
</div>]]></content><author><name>Arnaud Lauret</name></author><category term="talk" /><summary type="html"><![CDATA[Let’s compare versions Swagger 2.0 and OpenAPI 3.0, and 3.1 to demonstrate the benefits of the new features introduced by 3.x versions to create more precise, better documented, more practical, and future-proof API contract descriptions.]]></summary></entry><entry><title type="html">Attempting to define API governance</title><link href="https://apihandyman.io/attempting-to-define-api-governance/" rel="alternate" type="text/html" title="Attempting to define API governance" /><published>2022-09-08T00:00:00+00:00</published><updated>2022-09-08T00:00:00+00:00</updated><id>https://apihandyman.io/attempting-to-define-api-governance</id><content type="html" xml:base="https://apihandyman.io/attempting-to-define-api-governance/"><![CDATA[<p>In the collective unconscious, API governance often rhymes with API police. Reducing API governance to the need for order caused by the chaos of an organization’s myriad APIs is too reductive, and it risks not looking at the problem at hand from the right angle. Why not define API governance relatively to IT governance, corporate governance, and governance to better understand what it is?
<!--more--></p>

<p><em>This post’s banner is a detail of the frontispiece of the “Encyclopédie ou Dictionnaire raisonné des sciences, des arts et des métiers” (Encyclopedia or Reasoned Dictionary of Sciences, Arts and Crafts) drawn by Charles-Nicolas Cochin and engraved by Bonaventure-Louis Prévost.</em></p>

<h1 id="the-origin-of-api-governance">The origin of API governance</h1>
<p>It’s not that easy to find a definition of API governance. My ideas on the topic were not entirely clear, so I decided to work on its definition relative to other governance. I think API governance should be seen as a direct descendant of IT governance which descends from corporate governance, which descends from governance.</p>

<p>Governance is managing and overseeing an organization’s control and the <em>system</em> for doing this. It is also the decision-making among the actors involved in a collective problem by which stable practices, social norms, customs, or institutions (an organization founded for religious, educational, professional, or social purposes) are established, reinforced, and reproduced.</p>

<p>Corporate governance is externally and indirectly guiding, controlling, and evaluating a company and the system for doing this. It provides the structure through which the company’s objectives, the means to achieve them, and how to monitor performance are defined. It implies balancing all organization’s stakeholders’ interests. Responsibility, accountability, ethical behavior, corporate strategy, compliance, and risk management are the main areas of governance. Other areas are, for example, environmental awareness or talent acquisition. It differs from management; the people exercising governance, the governing agents, don’t have direct control and are not part of what they govern.</p>

<p>Information Technology (IT) governance is a subset of corporate governance that focuses on taking advantage of IT efficiently to enable the organization to achieve its goals, to maximize the creation of value. It aims to align business and IT strategies while identifying and addressing risks, ensuring compliance with regulations, and monitoring performance.</p>

<h1 id="how-api-governance-relates-to-its-ascendants">How API governance relates to its ascendants</h1>
<p>Like any governance, API governance refers to the decision-making among the actors involved in a collective problem (creating APIs helping the organization achieve its goals), by which stable practices, processes, policies, or institutions (organizations created for educational or professional purposes) are established, reinforced, and reproduced. For example, defining security, API design or API cataloging policies, having an API design review process, or creating an API center of enablement are part of API governance. These elements aim to facilitate, guide, and standardize the creation of the right APIs in the right way to help the organization to achieve its goals (and bring order to the API chaos in the making).</p>

<p>Like Corporate governance, API governance is <em>externally and indirectly</em> guiding, controlling, and evaluating a company’s APIs and the system for doing this. API governance is not creating APIs (API product management) or managing APIs (API management). People will make and manage APIs taking advantage of the institutions and following the processes and rules defined by API governance. The resulting APIs are being evaluated with the indicators defined by API governance. Though often people directly involved in the creation of APIs participate in governance (it is even highly recommended to ensure realistic governance), API governance agents should act as if they don’t have direct control over APIs.</p>

<p>Like corporate governance or IT governance, API governance implies balancing <em>all</em> stakeholders’ interests and the company’s objectives. The primary API stakeholders are the API providers (all members of API product teams) and the present and future API consumers. But many of the organization’s stakeholders are interested in APIs, for example, the security teams, the infrastructure teams, the business line managers, and even the board members or regulators.</p>

<p>Like IT governance, API governance is about what should be done and how it should be done and is both driven by IT and business. It requires aligning both IT and business. It covers all aspects of APIs, from their business inception and business model definition to design, implementation, exposition, and cataloging to (API) talent management (API design skills, internal API evangelization). It covers all types of APIs, whatever their visibility, so it concerns all public, partner, and private APIs. It’s about everything that will help maximize all APIs’ value.</p>

<h1 id="attempting-to-define-api-governance">Attempting to define API governance</h1>
<p>Now that all that is said, how to define API governance?</p>

<h2 id="paraphrasing-other-governances-definitions">Paraphrasing other governances definitions</h2>
<p>As a descendant of governance, corporate governance, and IT governance, and paraphrasing their definitions, API governance could be defined as follow:</p>

<blockquote>
  <p>API governance is establishing and overseeing decision-making, policies, practices, processes, and institutions to enable an organization’s people to collectively achieve its goals by efficiently taking advantage of private, partner, or public APIs. It aims to align APIs with business and IT strategies, to monitor and maximize the value created from them while identifying and addressing risks and ensuring compliance with regulations.</p>
</blockquote>

<h2 id="trying-to-simplify-the-definition">Trying to simplify the definition</h2>
<p>Simplifying the previous definition leads to this:</p>

<blockquote>
  <p>API governance is enabling and facilitating people to work together on the right APIs, the right way to maximize the value created by APIs in alignment with the organization’s goals and constraints.</p>
</blockquote>

<h1 id="the-tree-that-hides-the-forest">The tree that hides the forest</h1>
<p>I’m pretty satisfied with those definitions, although they do not provide all the tiny details of API governance. I feel the global ideas they describe are relevant and cover the topic from a high-level perspective. I’ll keep the small details for other posts.</p>

<h1 id="sources">Sources</h1>
<ul>
  <li>Governance:  <a href="https://www.merriam-webster.com/dictionary/governance">Merriam-Webster dictionary</a>, <a href="https://dictionary.cambridge.org/dictionary/english/governance">Cambridge dictionary</a>,  <a href="https://en.wikipedia.org/wiki/Governance">Wikipedia</a>, <a href="https://en.wikipedia.org/wiki/Governance#cite_note-Hufty_2011-2">Huffy, 2011</a>; <a href="https://en.wikipedia.org/wiki/Governance#cite_note-13">Lijun, 1988</a></li>
  <li>Corporate Governance: <a href="https://en.wikipedia.org/wiki/Corporate_governance">Wikipedia</a>,  <a href="https://www.investopedia.com/terms/c/corporategovernance.asp">Investopedia</a>, <a href="http://www.grcglossary.org/terms/governance">GRC glossary</a></li>
  <li>IT Governance: <a href="https://en.wikipedia.org/wiki/Corporate_governance_of_information_technology">Wikipedia</a>, <a href="https://www.gartner.com/en/information-technology/glossary/it-governance">Gartner</a>, <a href="https://www.thoughtworks.com/insights/articles/lightweight-technology-governance">Thoughtworks</a></li>
  <li>API Governance:  <a href="https://apievangelist.com/2021/11/13/some-thoughts-on-api-governance/">Some thoughts on API Governance (API Evangelist, 2021)</a>, <a href="https://youtu.be/lakFsqIiiLU">What is API governance (Erik Wilde, 2020)</a>,  <a href="https://apihandyman.io/human-centered-api-governance/">Human Centered API Governance (Arnaud Lauret, 2021)</a></li>
</ul>]]></content><author><name>Arnaud Lauret</name></author><category term="post" /><summary type="html"><![CDATA[In the collective unconscious, API governance often rhymes with API police. Reducing API governance to the need for order caused by the chaos of an organization’s myriad APIs is too reductive, and it risks not looking at the problem at hand from the right angle. Why not define API governance relatively to IT governance, corporate governance, and governance to better understand what it is?]]></summary></entry><entry><title type="html">What is the info property in OpenAPI?</title><link href="https://apihandyman.io/what-is-the-info-property-in-openapi/" rel="alternate" type="text/html" title="What is the info property in OpenAPI?" /><published>2022-07-21T00:00:00+00:00</published><updated>2022-07-21T00:00:00+00:00</updated><id>https://apihandyman.io/what-is-the-info-property-in-openapi</id><content type="html" xml:base="https://apihandyman.io/what-is-the-info-property-in-openapi/"><![CDATA[<p>The info property of an OpenAPI document contains metadata that provides an overview of an API, but what does it represent exactly? How did it evolve across the OpenAPI Specification versions? And how to can it be used and misused? This is the second post in the OpenAPI Specification Reference series.
<!--more--></p>

<div class="card series-toc">
  <div class="card-header series-toc-title">
    <h5 id="series">OpenAPI Specification Reference Series</h5>
  </div>
  <div class="row series-toc_content">
    <div class="col-md-7 series-toc-summary">
      <div class="card-body">
        <p class="card-text">
<p>This series aims to provide complete cross-version reference documentation about the OpenAPI Specification aggregating different sources of information. For each analyzed element, you’ll find its definition, how it evolved across the different versions of the specification, how it is used and misused and where to find more information about it. This structure may evolve with future posts.</p>

<p>This series’ posts are not intended to be actionable tutorials, they may be of interest to people involved in the evolution of the specification or creating tools, and also advanced OpenAPI users. Most of this content will probably be incorporated in the next version of the <a href="https://apihandyman.io/toolbox/openapi-map/">OpenAPI Map</a> and be useful for more actionable series/posts about OpenAPI and Spectral.</p>
</p>
      </div>
    </div>
    <div class="col-md-5 series-toc-list border-left">
      
      <ul class="list-group list-group-flush">
        
          
          
          <li class="list-group-item"><a href="/what-is-the-openapi-property/">1 - What is the openapi property?</a></li>
          
        
          
          
          <li class="list-group-item active">2 - What is the info property in OpenAPI?</li>
          
        
        
      </ul>
    </div>
  </div>
</div>

<h1 id="definition">Definition</h1>

<p>What represents the <code>info</code> property, how it is structured, is it required, and where it is located.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">An OpenAPI 3.1 document with a complete info property (license url variant)</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/complete-license-url-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="2-14"><code class="code-block">openapi: 3.1.0
info:
  title: Dummy Bookshop
  summary: A fictitious API demonstrating the OpenAPI Specification's features
  version: '1.0'
  description: The **Dummy Bookshop API** is a _fictitious_ API aiming to demonstrate the [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification)'s features.
  termsOfService: https://www.dummy-book.shop/tos
  contact:
    name: Bookshop Support team
    url: https://www.dummy-book.shop/support
    email: support@dummy-book.shop
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
paths: {}
</code></pre>
  </div>
</div>

<h2 id="what-does-it-represent">What does it represent?</h2>

<p>The <code>info</code> property (lines 2 to 15 in the document above) contains metadata that provides an overview of an API, what can be done with it, who to contact about it, and its limitations and conditions of use. It contains:</p>

<ul>
  <li>The API’s version (<code>version</code> properties). The OpenAPI Specification doesn’t enforce any way of versioning an API, the version just needs to be set as a string.</li>
  <li>Various descriptions of the API, such as its name (<code>title</code> ) and a short and long description (<code>summary</code> and <code>description</code> ).</li>
  <li>Contact information (<code>contact</code> property) to get more details or support.</li>
  <li>Legal information pointing to documents outside of the OpenAPI document describing the API’s conditions of use and limitations (<code>termsOfService</code> and <code>license</code> properties).</li>
</ul>

<h2 id="how-is-it-structured">How is it structured?</h2>

<p>The <code>info</code> property is an Info object and relies on two other objects; the <code>contact</code> property is a Contact object, and the <code>license</code> one is a License object. Those three object are <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specificationExtensions">extensible</a>. All other properties are of type <code>string</code> (especially the <code>version</code>, see “<a href="#how-to-write-a-multiline-description-in-yaml">Missing quotes around the version of the API</a>”). Some may require a specific format (<code>url</code> or <code>email,</code> for example).</p>

<table>
<thead><tr>
<th>Property</th><th>Required</th><th>Type</th><th>Description</th>
</tr></thead>
<tr>
<td>title</td><td>✅</td><td><code>string</code></td><td>The name of the API.</td>
</tr><tr><td>summary</td><td></td><td><code>string</code></td><td>A short summary of the API.</td>
</tr><tr>
  <td>version</td>
  <td>✅</td>
  <td><code>string</code></td>
  <td>The version of the API (which is distinct from the <a href="#what-is-the-openapi-property">OpenAPI Specification version defined in the <code>openapi</code> property</a> or the <a href="#version-is-not-the-interfaces-contract-one">API implementation version</a>).</td>
</tr><tr><td>description</td>
  <td></td>
  <td><code>string</code></td>
  <td>A description of the API. Supports markdown (<a href="https://spec.commonmark.org/">Commonmark</a>) to propose rich text formatting (see "<a href="#using-rich-text-formatting-in-description">Using rich text formatting in description</a>").</td>
</tr><tr><td>termsOfService</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>A URL to the terms of service for the API.</td>
</tr>
<tr>
  <td>contact</td>
  <td></td>
  <td>Contact Object</td>
  <td>The contact information for the exposed API.</td>
</tr>
<tr>
  <td>contact.name</td>
  <td></td>
  <td><code>string</code></td>
  <td>The identifying name of the contact person/organization.</td>
</tr>
<tr>
  <td>contact.url</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>The URL pointing to the contact information.</td>
</tr>
<tr>
  <td>contact.email</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>email</code>)</td>
  <td>The email address of the contact person/organization.</td>
</tr>
<tr>
  <td>license</td>
  <td></td>
  <td>License Object</td>
  <td>The license that is applicable to the interface contract which is described in the OpenAPI document. See <a href="#what-is-a-license-for-an-api">What is a license for an API?</a>)</td>
</tr>
<tr>
  <td>license.name</td>
  <td>✅</td>
  <td><code>string</code></td>
  <td>The license name used for the API.</td>
</tr><tr><td>license.identifier</td>
  <td></td>
  <td><code>string</code></td>
  <td>An <a href="https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60">SPDX</a> license expression for the API. The <code>identifier</code> field is mutually exclusive of the <code>url</code> field.</td>
</tr><tr>
  <td>license.url</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>A URL to the license used for the API.The <code>url</code> field is mutually exclusive of the <code>identifier</code> field.</td>
</tr>
</table>

<h2 id="is-it-required">Is it required?</h2>

<p>The <code>info</code> property itself is required; an OpenAPI document will be considered invalid without it. It may be more or less complete; a minimal <code>info</code> property will contain the API’s name (<code>title</code>) and version (<code>version</code>).</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">A minimal Info object</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/minimal-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="2-4"><code class="code-block">openapi: 3.1.0
info:
  title: Dummy Bookshop
  version: '1.0'
paths: {}
</code></pre>
  </div>
</div>

<p>When a <code>license</code> property is present, the License object must include at least a license <code>name</code>, <code>identifier</code> and <code>url</code> are optional. According to specification and schema, when the <code>contact</code> property could be empty as all properties of the Contact object are optional. Obviously, a minimal instance must contain at least one of its <code>name</code>,<code>email</code> , or <code>url</code> properties.</p>

<div class="alert alert-warning">
<p>Note that there’s an inconsistency between the optional status of <code>identifier</code> and <code>url</code> described in the specification and the official JSON Schema which makes them required (see <a href="https://github.com/OAI/OpenAPI-Specification/issues/2975">Issue 2975</a>, <em>I’m waiting a confirmation before proposing a fix</em>).</p>

</div>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">Minimal License and Contact objects</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/minimal-contact-license-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="5"><code class="code-block">openapi: 3.1.0
info:
  title: Dummy Bookshop
  version: '1.0'
  contact:
    url: https://www.dummy-book.shop/support
  license:
    name: Apache 2.0
paths: {}
</code></pre>
  </div>
</div>

<p>The <code>identifier</code> and <code>url</code> of the License object (<code>license</code> property of the Info Object) are mutually exclusive. That means only one of them can be provided and so a License object can’t contain them both at the same time.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">A complete License object (identifier variant)</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/complete-license-identifier-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="13"><code class="code-block">    name: Apache 2.0
    identifier: Apache-2.0
</code></pre>
  </div>
</div>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">A complete License object (url variant)</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/complete-license-url-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="13"><code class="code-block">    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
</code></pre>
  </div>
</div>

<h2 id="where-is-it-located">Where is it located?</h2>

<p>The <code>info</code> property is a property of the <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#oasObject">OpenAPI object</a> and so is located at the OpenAPI document’s root. This property and the related Info, License and Contact objects appear only once in a document.</p>

<h1 id="changelog">Changelog</h1>

<p>How the <code>info</code> property and its components evolved across the different versions of the specification.</p>

<p>The Info object hasn’t much structurally changed between version 2.0 and 3.1. Some clarifications and more-or-less non-backward compatible modifications have been made to the content of some values and some optional data have been added.</p>

<h2 id="version-20-2014">Version 2.0 (2014)</h2>

<p>The <code>info</code> property structure in version 2.0 is almost the same as in the 3.x versions minus the additions made in 3.1. Two properties, <code>termsOfService</code> and <code>description</code> have some “specific” behaviors that must be noted.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">A Swagger 2.0 document with a complete info property</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/complete-version-20.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="5-6"><code class="code-block">swagger: '2.0'
info:
  title: Dummy Bookshop
  version: '1.0'
  description: The **Dummy Bookshop API** is a _fictitious_ API aiming to demonstrate the [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification)'s features.
  termsOfService: https://www.dummy-book.shop/tos
  contact:
    name: Bookshop Support team
    url: https://www.dummy-book.shop/support
    email: support@dummy-book.shop
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
paths: {}
</code></pre>
  </div>
</div>

<table>
<thead><tr>
<th>Property</th><th>Required</th><th>Type</th><th>Description</th>
</tr></thead>
<tr>
<td>title</td><td>✅</td><td><code>string</code></td><td>The name of the API.</td>
</tr><tr>
  <td>version</td>
  <td>✅</td>
  <td><code>string</code></td>
  <td>The version of the API (which is distinct from the <a href="#what-is-the-openapi-property">OpenAPI Specification version defined in the <code>swagger</code> property</a> or the <a href="#version-is-not-the-interfaces-contract-one">API implementation version</a>).</td>
</tr><tr class="table-primary">
<td>description</td>
  <td></td>
  <td><code>string</code></td>
  <td>A description of the API. Supports markdown (<a href="https://github.github.com/gfm/">GFM</a>) to propose rich text formatting (see "<a href="#using-rich-text-formatting-in-description">Using rich text formatting in description</a>").</td>
</tr><tr class="table-primary">
<td>termsOfService</td>
  <td></td>
  <td><code>string</code></td>
  <td>The Terms of Service for the API.</td>
</tr>
<tr>
  <td>contact</td>
  <td></td>
  <td>Contact Object</td>
  <td>The contact information for the exposed API.</td>
</tr>
<tr>
  <td>contact.name</td>
  <td></td>
  <td><code>string</code></td>
  <td>The identifying name of the contact person/organization.</td>
</tr>
<tr>
  <td>contact.url</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>The URL pointing to the contact information.</td>
</tr>
<tr>
  <td>contact.email</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>email</code>)</td>
  <td>The email address of the contact person/organization.</td>
</tr>
<tr>
  <td>license</td>
  <td></td>
  <td>License Object</td>
  <td>The license that is applicable to the interface contract which is described in the OpenAPI document. See <a href="#what-is-a-license-for-an-api">What is a license for an API?</a>)</td>
</tr>
<tr>
  <td>license.name</td>
  <td>✅</td>
  <td><code>string</code></td>
  <td>The license name used for the API.</td>
</tr><tr>
  <td>license.url</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>A URL to the license used for the API.</td>
</tr>
</table>

<h3 id="terms-of-service-is-implicitly-a-url">Terms of service is implicitly a URL</h3>

<p>Though the <code>termsOfService</code> property is a string without any specific format, most parsers and tools expect its value to be a URL like in 3.x versions.</p>

<h3 id="description-markdown-syntax-is-different-from-later-versions">Description markdown syntax is different from later versions</h3>

<p>The <code>description</code> property supports the <a href="https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#GitHub-flavored-markdown">GFM (Github Flavored Markdown)</a> syntax, which differs from the one used in 3.x versions (see “<a href="#which-markdown-syntax-to-support-in-description">Which Markdown syntax to support in description?</a>”).</p>

<h2 id="version-30-2017">Version 3.0 (2017)</h2>

<p>There is no structural modification in version 3.0. Still, the descriptions of two existing properties, <code>termsOfService</code> and <code>description</code>, have been modified, introducing more-or-less non-backward compatible changes.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">An OpenAPI 3.0 document with a complete info property</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/complete-version-30.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="5-6"><code class="code-block">openapi: 3.0.3
info:
  title: Dummy Bookshop
  version: '1.0'
  description: The **Dummy Bookshop API** is a _fictitious_ API aiming to demonstrate the [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification)'s features.
  termsOfService: https://www.dummy-book.shop/tos
  contact:
    name: Bookshop Support team
    url: https://www.dummy-book.shop/support
    email: support@dummy-book.shop
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
paths: {}
</code></pre>
  </div>
</div>

<table>
<thead><tr>
<th>Property</th><th>Required</th><th>Type</th><th>Description</th>
</tr></thead>
<tr>
<td>title</td><td>✅</td><td><code>string</code></td><td>The name of the API.</td>
</tr><tr>
  <td>version</td>
  <td>✅</td>
  <td><code>string</code></td>
  <td>The version of the API (which is distinct from the <a href="#what-is-the-openapi-property">OpenAPI Specification version defined in the <code>openapi</code> property</a> or the <a href="#version-is-not-the-interfaces-contract-one">API implementation version</a>).</td>
</tr><tr class="table-danger"><td>description</td>
  <td></td>
  <td><code>string</code></td>
  <td>A description of the API. Supports markdown (<a href="https://spec.commonmark.org/">Commonmark</a>) to propose rich text formatting (see "<a href="#using-rich-text-formatting-in-description">Using rich text formatting in description</a>").</td>
</tr><tr class="table-warning"><td>termsOfService</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>A URL to the terms of service for the API.</td>
</tr>
<tr>
  <td>contact</td>
  <td></td>
  <td>Contact Object</td>
  <td>The contact information for the exposed API.</td>
</tr>
<tr>
  <td>contact.name</td>
  <td></td>
  <td><code>string</code></td>
  <td>The identifying name of the contact person/organization.</td>
</tr>
<tr>
  <td>contact.url</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>The URL pointing to the contact information.</td>
</tr>
<tr>
  <td>contact.email</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>email</code>)</td>
  <td>The email address of the contact person/organization.</td>
</tr>
<tr>
  <td>license</td>
  <td></td>
  <td>License Object</td>
  <td>The license that is applicable to the interface contract which is described in the OpenAPI document. See <a href="#what-is-a-license-for-an-api">What is a license for an API?</a>)</td>
</tr>
<tr>
  <td>license.name</td>
  <td>✅</td>
  <td><code>string</code></td>
  <td>The license name used for the API.</td>
</tr><tr>
  <td>license.url</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>A URL to the license used for the API.</td>
</tr>
</table>

<h3 id="terms-of-service-is-explicitly-a-url">Terms of service is explicitly a URL</h3>

<p>The <code>termsOfService</code> property is now explicitly a URL (<a href="https://github.com/OAI/OpenAPI-Specification/pull/661">Issue #661</a>, <a href="https://github.com/OAI/OpenAPI-Specification/pull/255">Pull Request #255</a>). Out of context, it is an actual non-backward compatible change, but it is not, based on the typical property usage in version 2.0.</p>

<h3 id="description-now-uses-commonmark-markdown-syntax">Description now uses CommonMark markdown syntax</h3>

<p>The <code>description</code> property now supports markdown using the <a href="https://spec.commonmark.org/">CommonMark</a> syntax instead of GFM syntax (<a href="https://github.com/OAI/OpenAPI-Specification/pull/720">Pull Request #720</a>). This modification was introduced because the definition of GFM and its differences from the original Markdown format were unclear then. Conversely, the CommonMark specification was considered well documented, rigorously defined, and would facilitate tool creators’ work. It seems not to be the case anymore in 2022; see <a href="https://github.github.com/gfm/">GFM specification</a>, which was probably not available in 2017 and is equivalent to CommonMark specification quality. Question: At equivalent quality, could another argument in favor of such a change be to avoid using a “proprietary” format? CommonMark is a “non-proprietary” attempt to specify the Markdown syntax formally. That was a knowingly accepted non-backward compatible lossy change; markdown table support loss, among other less-used features, was considered acceptable because there was a work-around, using HTML tables, and <a href="https://talk.commonmark.org/t/tables-in-pure-markdown/81/186">CommonMark was supposed to evolve to support this feature</a> (<a href="https://github.com/OAI/OpenAPI-Specification/issues/1867">see issue #1867</a> and Markdown support section in Troubleshooting).</p>

<h3 id="tools-may-ignore-some-markdown-features-in-rich-text-for-security-reasons">Tools may ignore some markdown features in rich text for security reasons</h3>

<p>Regardless of which markdown syntax is used in <code>description</code>, or any other rich text value, version 3.0 adds some precisions about markdown parsing and security: <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#richText">tools may ignore certain markdown features for security concerns</a> (See <a href="https://github.com/OAI/OpenAPI-Specification/issues/1078">issue 1078</a>, <a href="https://github.com/OAI/OpenAPI-Specification/pull/1090">Pull Request #1090</a>, and <a href="#">Security issues with Markdown support in description</a> in Troubleshooting)</p>

<h2 id="version-31-2021">Version 3.1 (2021)</h2>

<p>In version 3.1, two optional properties were added; <code>summary</code> was added to the Info object and <code>identifier</code> was added to the License one. These are backward compatible modifications.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">An OpenAPI 3.1 document with a complete info property (license identifier variant)</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/complete-license-identifier-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="2-14"><code class="code-block">openapi: 3.1.0
info:
  title: Dummy Bookshop
  summary: A fictitious API demonstrating the OpenAPI Specification's features
  version: '1.0'
  description: The **Dummy Bookshop API** is a _fictitious_ API aiming to demonstrate the [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification)'s features.
  termsOfService: https://www.dummy-book.shop/tos
  contact:
    name: Bookshop Support team
    url: https://www.dummy-book.shop/support
    email: support@dummy-book.shop
  license:
    name: Apache 2.0
    identifier: Apache-2.0
paths: {}
</code></pre>
  </div>
</div>

<table>
<thead><tr>
<th>Property</th><th>Required</th><th>Type</th><th>Description</th>
</tr></thead>
<tr>
<td>title</td><td>✅</td><td><code>string</code></td><td>The name of the API.</td>
</tr><tr class="table-success"><td>summary</td><td></td><td><code>string</code></td><td>A short summary of the API.</td>
</tr><tr>
  <td>version</td>
  <td>✅</td>
  <td><code>string</code></td>
  <td>The version of the API (which is distinct from the <a href="#what-is-the-openapi-property">OpenAPI Specification version defined in the <code>openapi</code> property</a> or the <a href="#version-is-not-the-interfaces-contract-one">API implementation version</a>).</td>
</tr><tr><td>description</td>
  <td></td>
  <td><code>string</code></td>
  <td>A description of the API. Supports markdown (<a href="https://spec.commonmark.org/">Commonmark</a>) to propose rich text formatting (see "<a href="#using-rich-text-formatting-in-description">Using rich text formatting in description</a>").</td>
</tr><tr><td>termsOfService</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>A URL to the terms of service for the API.</td>
</tr>
<tr>
  <td>contact</td>
  <td></td>
  <td>Contact Object</td>
  <td>The contact information for the exposed API.</td>
</tr>
<tr>
  <td>contact.name</td>
  <td></td>
  <td><code>string</code></td>
  <td>The identifying name of the contact person/organization.</td>
</tr>
<tr>
  <td>contact.url</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>The URL pointing to the contact information.</td>
</tr>
<tr>
  <td>contact.email</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>email</code>)</td>
  <td>The email address of the contact person/organization.</td>
</tr>
<tr>
  <td>license</td>
  <td></td>
  <td>License Object</td>
  <td>The license that is applicable to the interface contract which is described in the OpenAPI document. See <a href="#what-is-a-license-for-an-api">What is a license for an API?</a>)</td>
</tr>
<tr>
  <td>license.name</td>
  <td>✅</td>
  <td><code>string</code></td>
  <td>The license name used for the API.</td>
</tr><tr class="table-success"><td>license.identifier</td>
  <td></td>
  <td><code>string</code></td>
  <td>An <a href="https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60">SPDX</a> license expression for the API. The <code>identifier</code> field is mutually exclusive of the <code>url</code> field.</td>
</tr><tr>
  <td>license.url</td>
  <td></td>
  <td><code>string</code>&nbsp;(<code>url</code>)</td>
  <td>A URL to the license used for the API.The <code>url</code> field is mutually exclusive of the <code>identifier</code> field.</td>
</tr>
</table>

<h3 id="apis-summary-added-to-info-object">API’s summary added to Info Object</h3>

<p>The <code>summary</code> property has been added to the Info object (<a href="https://github.com/OAI/OpenAPI-Specification/issues/832">Issue #832</a>, <a href="https://github.com/OAI/OpenAPI-Specification/pull/1779">Pull request #1779</a>). It’s a short description of the API which is similar to the summary found on a path or an operation. That simplifies documentation tools work which would take the first sentence or first nth characters as a summary in previous version (See <a href="#api-documentation">API documentation use case examples</a>). That can also help better set the boundaries of the API (see <a href="#api-design">API design use case examples</a>).</p>

<h3 id="spdx-identifier-added-to-license-object">SPDX identifier added to License Object</h3>

<p>The <code>identifier</code> property has been added to the License object (<a href="https://github.com/OAI/OpenAPI-Specification/issues/1599">Issue #1599</a>, <a href="https://github.com/OAI/OpenAPI-Specification/pull/2105">Pull Request #2105</a>). It is a <a href="https://spdx.dev/spdx-specification-21-web-version/#h.jxpfx0ykyb60">SPDX (Software Package Data eXchange) license expression</a> which  “provides a way for one to construct expressions that more accurately represent the licensing terms typically found in open source software source code.” The value can be an <a href="https://spdx.org/licenses/">official SPDX identifier</a> or a custom one.</p>

<p>This new <code>identifier</code> property is optional but mutually exclusive with the <code>url</code> one. No information were found in the specification, issues or pull requests explaining this mutual exclusive relationship.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">A complete License object (identifier variant)</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/complete-license-identifier-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="13"><code class="code-block">    name: Apache 2.0
    identifier: Apache-2.0
</code></pre>
  </div>
</div>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">A complete License object (url variant)</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/complete-license-url-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="13"><code class="code-block">    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
</code></pre>
  </div>
</div>

<h1 id="usage">Usage</h1>

<p>How the <code>info</code> property and its components can be used and misused.</p>

<h2 id="notes-about-certain-properties">Notes about certain properties</h2>

<h3 id="using-rich-text-formatting-in-description">Using rich text formatting in description</h3>

<p>The <code>description</code> property supports markdown to propose rich text formatting (see “<a href="#which-markdown-syntax-to-support-in-description">Which Markdown syntax to support in description?</a>”).</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">A rich text (markdown) description</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/complete-license-url-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-start="6"><code class="code-block">  description: The **Dummy Bookshop API** is a _fictitious_ API aiming to demonstrate the [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification)'s features.
</code></pre>
  </div>
</div>

<div class="image ">
    <figure class="figure">
        <img src="/images/what-is-the-info-property-in-openapi/rich-text-rendered.jpg" class="figure-img img-fluid" /></figure>
</div>

<h2 id="use-case-examples">Use case examples</h2>

<p>The <code>info</code> property can be used for API design, governance, documentation, and tools. Here are a few examples; some of them may deserve more complete articles.</p>

<h3 id="api-design">API design</h3>

<ul>
  <li>In the early stage of design, designers can take advantage of almost empty documents containing only an <code>info</code> property (empty <code>paths</code> or empty <code>components</code>) to describe the API in natural language briefly. Giving a name (<code>title</code>) and crafting a short description (<code>summary</code> ) of an API can be an excellent start to set boundaries. The longer markdown-compatible <code>description</code> can be used to list the use cases to fulfill.</li>
</ul>

<h3 id="api-governance">API governance</h3>

<ul>
  <li>The <code>version</code> property can be used in conjunction with a <a href="https://semver.org/">semantic version</a> (<code>2.1,</code> for example) to inform about the type of changes introduced. Note that the version can be anything that fits into a string. For example, it could be an ISO8601 date (<code>2022-07-19</code>).</li>
  <li>An organization can ensure that an API has an identified owner by enforcing providing the <code>contact</code> information.</li>
</ul>

<h3 id="api-documentation">API documentation</h3>

<ul>
  <li>An API catalog can take advantage of the <code>title</code> and <code>summary</code> properties of OpenAPI documents to generate a list of APIs.</li>
  <li>A UI showing an API’s detailed information can take advantage of the markdown sections (<code># level 1</code>  and <code>## level 2,</code> for example) present in <code>the description to build a menu and</code> various pages.</li>
  <li>The <code>description</code> can list the modifications a new version brings (in a <code># Changelog</code> section, for instance).</li>
  <li>The support form of an API on an API portal could take advantage of the <code>contact</code> property.</li>
  <li>The <code>description</code> can be used to fill the gap in the OpenAPI Specification and add (non-machine readable) information that can’t be put elsewhere in the document, though it may be preferable to use machine-readable extensions (See <a href="#description-vs-extension">Description vs extension</a>).</li>
</ul>

<h3 id="api-tools">API Tools</h3>

<ul>
  <li>Depending on the type of change indicated by a semantic <code>version</code> , the tool in charge of deploying an API on an API gateway may choose to update (minor change<code>1.7</code>  to <code>1.8</code>  for example) or recreate the API (major change, <code>1.8</code>  to <code>2.0</code>  for example), leaving the previous version unmodified.</li>
  <li>Monitoring and logging tools may use the API <code>title</code> as an identifier of the API (hoping there are governance controls ensuring it is unique).</li>
</ul>

<h2 id="troubleshooting">Troubleshooting</h2>

<p>The usual problems, concerns, and questions encountered when using the <code>info</code> property (Info, Contact, and License objects). Some of the elements evoked here may deserve more complete articles.</p>

<ul>
  <li><a href="#info-may-be-more-than-metadata">Info may be more than metadata</a></li>
  <li><a href="#version-is-not-the-interfaces-contract-one">Version is not the interface’s contract one</a></li>
  <li><a href="#missing-quotes-around-the-version-of-the-api">Missing quotes around the version of the API</a></li>
  <li><a href="#how-to-write-a-multiline-description-in-yaml">How to write a multiline description in YAML?</a></li>
  <li><a href="#description-as-a-substitute-or-copy-of-some-openapi-elements">Description as a substitute or copy of some OpenAPI elements</a></li>
  <li><a href="#description-vs-extension">Description vs extension</a></li>
  <li><a href="#which-markdown-syntax-to-support-in-description">Which Markdown syntax to support in description?</a></li>
  <li><a href="#security-issues-with-markdown-support-in-description">Security issues with Markdown support in description</a></li>
  <li><a href="#non-url-terms-of-service">Non URL terms of service</a></li>
  <li><a href="#what-is-a-license-for-an-api">What is a license for an API?</a></li>
  <li><a href="#is-it-possible-to-use-a-custom-license-identifier">Is it possible to use a custom license identifier?</a></li>
  <li><a href="#license-used-for-terms-of-service">License used for terms of service</a></li>
</ul>

<h3 id="info-may-be-more-than-metadata">Info may be more than metadata</h3>

<p>The <code>info</code> property is described as “metadata” and could be seen as not being part of the API contract. But this property may directly or indirectly describe behavior and provide information impacting the overall API’s contract. For instance, the document(s) linked in <code>termsOfService</code> could define rate limits or the <code>description</code> may describe some of the API’s behavior in human-readable fashion only.</p>

<h3 id="version-is-not-the-interfaces-contract-one">Version is not the interface’s contract one</h3>

<p>When generating an OpenAPI document from code, the <code>version</code> property may contain the implementation’s version or build number instead of the interface’s contract version. The framework or library used may need some configuration tuning to ensure that the correct expected value is put in this property.</p>

<h3 id="missing-quotes-around-the-version-of-the-api">Missing quotes around the version of the API</h3>

<p>Many APIs use a <code>major.minor</code> semantic versioning, so the <code>info.version</code> value could be <code>1.0</code> for instance. Not putting quotes around this value will cause an error because <code>info.version</code> is defined as a string and such value will be interpreted as a number by OpenAPI parsers either the document is in JSON or YAML.</p>

<h3 id="how-to-write-a-multiline-description-in-yaml">How to write a multiline description in YAML?</h3>

<p>A complex and long markdown <code>description</code> can be a burden to write on a single line. Hopefully YAML supports multiline string values. Right after <code>description: </code> add a <code>|</code> followed by a new line, this allows to write multiline string values. Read more about multiline strings in YAML <a href="https://yaml-multiline.info/">here</a>.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">A multiline description</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/what-is-the-info-property-in-openapi/description-markdown-multiline-version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="5-14"><code class="code-block">openapi: 3.1.0
info:
  title: Dummy Bookshop
  version: '1.0'
  description: |
    The **Dummy Bookshop API** is a _fictitious_ API aiming to demonstrate the [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification)'s features.

    # How to get an access token?

    Go to the [consumer settings page](https://www.dummy-book.shop/consumer-settings) and follow the instructions.

    # Concepts

    The Dummy Bookshop API deals with book, authors and many other book related topics.
paths: {}
</code></pre>
  </div>
</div>

<h3 id="description-as-a-substitute-or-copy-of-some-openapi-elements">Description as a substitute or copy of some OpenAPI elements</h3>

<p>An axis of OpenAPI documents analysis (that can be done during an API review process) is to ensure the <code>description</code> property doesn’t contain information that could have been described in a machine-readable way with other OpenAPI elements or information that has been already formally described elsewhere.</p>

<h3 id="description-vs-extension">Description vs extension</h3>

<p>The description property could be used to fill the gap in the OpenAPI Specification, but the information provided are mostly human-readable only (though it could be partially machine-interpreted taking advantage of rich text features like sections). It could be preferable to take advantage of <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#specificationExtensions">extensions (custom x- properties)</a>.</p>

<p><em>API Handyman note: A dedicated post about extensions in planned in this OpenAPI Reference series.</em></p>

<h3 id="which-markdown-syntax-to-support-in-description">Which Markdown syntax to support in description?</h3>

<p>The use of <a href="https://commonmark.org/">CommonMark</a> was introduced in 3.0 (<a href="https://github.com/OAI/OpenAPI-Specification/pull/720">Pull Request #720</a>) in replacement of GFM (Github Flavored Markdown) used in previous version, see <a href="#version-30-2017">version 3.0 changelog</a>.</p>

<p>According to what is said in the <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#rich-text-formatting">3.1 specification</a> and in the <a href="https://github.com/OAI/OpenAPI-Specification/issues/972">issue #972</a> discussion, tools should support CommonMark 0.27 and above (the latest version as of the moment of writing is 0.30).</p>

<p>The problem is that transitioning from GFM to CommonMark markdown syntax came with some loss, especially the (non-HTML) table support (see <a href="https://github.com/OAI/OpenAPI-Specification/issues/1867">Issue #1867</a>) and many people are used to <a href="https://github.github.com/gfm/#tables-extension-">table GFM syntax</a>. The <a href="https://talk.commonmark.org/t/tables-in-pure-markdown/81/186">discussion about supporting table in CommonMark exists</a> but is not yet settle even in 2022. In 2017, the table issue was known and it was decided that as CommonMark supported HTML and markdown table was possibly coming to CommonMark, it was OK to switch.</p>

<p>Hopefully, according to the <a href="https://talk.commonmark.org/t/tables-in-pure-markdown/81/186">CommonMark table discussion</a> it seems “there are plenty of CommonMark implementations out there that offer table extensions compatible with what GitHub uses.</p>

<p><em>API Handyman note: Based on those elements, I would (I’m not speaking in the name of OAI) recommend to support the most common markdown syntax(es), especially GFM tables, and not just pure CommonMark. That way it is possible to easily deal with all versions of OpenAPI from 2.0 to 3.1 and what most users will expect regarding markdown support.</em></p>

<h3 id="security-issues-with-markdown-support-in-description">Security issues with Markdown support in description</h3>

<p>This is not an OpenAPI specific topic, any tool/format relying on markdown is subject to security issues like <a href="https://www.akamai.com/blog/security/markdown-menace">local file inclusion</a> or <a href="https://michelf.ca/blog/2010/markdown-and-xss/">XSS</a>. Therefore, it is accepted and even up to the tools to ignore some normally supported markdown feature for security concerns (See <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#richText">Rich Text Formatting section</a>,  <a href="https://github.com/OAI/OpenAPI-Specification/issues/1078">issue 1078</a> and <a href="https://github.com/OAI/OpenAPI-Specification/pull/1090">Pull Request #1090</a>). But, as always with security measures, a balance has to be found with user experience (completely forbidding HTML support could be a problem for instance).</p>

<h3 id="non-url-terms-of-service">Non URL terms of service</h3>

<p>In version 2.0, it was not clearly stated that <code>termsOfService</code> was a URL, so some documents may contain a text value which is not a URL. Based on a search on the APIs.guru directory, it can be assumed it is quite rare, if not non-existing on public APIs, though the situation may be different on the millions on private APIs. Nevertheless, most tools parsing 2.0 documents will expect a URL and ignore other values, but maybe silently. This is not an issue anymore in 3.x documents as the specifications clearly states the expected format.</p>

<h3 id="what-is-a-license-for-an-api">What is a license for an API?</h3>

<p>According to <a href="https://github.com/OAI/OpenAPI-Specification/issues/726">issue #726</a>, the <code>license</code> property describes the license (like Apache 2.0 for instance) that is applicable to the interface contract itself which is described in the OpenAPI document. It tells if one can re-implement or re-license the API, it does not apply to the implementation.</p>

<p><em>API Handyman note, I’ll need to investigate that topic, as despite what is said above, I’m not sure about what means a license for an API and even if an API can be licensed. Also does it relate to copyright (as in the <a href="https://en.wikipedia.org/wiki/Google_LLC_v._Oracle_America_Inc.">Google vs Oracle API case</a>)?</em></p>

<h3 id="is-it-possible-to-use-a-custom-license-identifier">Is it possible to use a custom license identifier?</h3>

<p>It is possible to use custom license <code>identifier</code> in the License object? Yes and no. The property only expects a <a href="https://spdx.dev/spdx-specification-21-web-version/#h.jxpfx0ykyb60">SPDX expression</a> value and not an actual <a href="https://spdx.org/licenses/">official SPDX identifier</a> or a combination of those.</p>

<p>A pseudo-custom identifier which is a combination of existing ones can be used. The information available on the <a href="https://spdx.org/licenses/">official license list</a> will allow to parse it.</p>

<p>But if the <code>identifier</code> is a completely custom one (which is not based on existing license identifiers), impossible to understand using the official list, how people or machine reading the document are supposed to understand that code? I wouldn’t recommend to use such an identifier unless you’re sure that people and machine using the document know what to do with it, but how to be 100% sure? In that case, it would be more secure to use a <code>url</code> instead of an <code>identifier</code>.</p>

<p>Note that the SPDX documentation can be overwhelming. On <a href="https://github.com/OAI/OpenAPI-Specification/issues/1599">Issue #1599</a>, silverhook <a href="https://github.com/OAI/OpenAPI-Specification/issues/1599#issuecomment-510819281">shows an example of completely custom SPDX identifier</a>:</p>

<blockquote>
  <p>If a license is not listed on the SPDX License List, you can still use SPDX annotation to indicate a unique license by prepending LicenseRef- to the (unique) license name. E.g. LicenseRef-My_Very_Own_Look_But_Do_Not_Touch_License-2.0 is a valid SPDX license identifier.</p>
</blockquote>

<h3 id="license-used-for-terms-of-service">License used for terms of service</h3>

<p>Some OpenAPI document may use the license object to point to their terms of service (or terms and conditions). That is not correct according to the definition (and clarification) of what is the <code>license</code> property. See <a href="https://github.com/OAI/OpenAPI-Specification/issues/1672">issue #1672</a>.</p>

<h1 id="documentation">Documentation</h1>

<p>Where to find more information about the <code>info</code> property and its components.</p>

<h2 id="specification-and-schemas">Specification and schemas</h2>

<table>


    <thead>
    <tr>
      <th>Info object</th>
      <th class="text-center" colspan="3">Links</th>
    </tr>
    </thead>
    <tr>
      <td>Specification</td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#infoObject"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#infoObject"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#info-object"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a></td>
      
    </tr>
    <tr>
      <td>JSON schema</td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/aa91a19c43f8a12c02efa42d64794e396473f3b1/schemas/v3.1/schema.json#L80"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/aa91a19c43f8a12c02efa42d64794e396473f3b1/schemas/v3.0/schema.json#L66"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/aa91a19c43f8a12c02efa42d64794e396473f3b1/schemas/v2.0/schema.json#L87"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a></td>
      
    </tr>


    <thead>
    <tr>
      <th>Contact object</th>
      <th class="text-center" colspan="3">Links</th>
    </tr>
    </thead>
    <tr>
      <td>Specification</td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#contactObject"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#contactObject"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#contact-object"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a></td>
      
    </tr>
    <tr>
      <td>JSON schema</td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/aa91a19c43f8a12c02efa42d64794e396473f3b1/schemas/v3.1/schema.json#L114"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/aa91a19c43f8a12c02efa42d64794e396473f3b1/schemas/v3.0/schema.json#L99"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/aa91a19c43f8a12c02efa42d64794e396473f3b1/schemas/v2.0/schema.json#L125"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a></td>
      
    </tr>


    <thead>
    <tr>
      <th>License Object</th>
      <th class="text-center" colspan="3">Links</th>
    </tr>
    </thead>
    <tr>
      <td>Specification</td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#licenseObject"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#licenseObject"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#license-object"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a></td>
      
    </tr>
    <tr>
      <td>JSON schema</td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/aa91a19c43f8a12c02efa42d64794e396473f3b1/schemas/v3.1/schema.json#L133"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/aa91a19c43f8a12c02efa42d64794e396473f3b1/schemas/v3.0/schema.json#L120"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a></td>
      
      
      <td class="text-center"><a href="https://github.com/OAI/OpenAPI-Specification/blob/aa91a19c43f8a12c02efa42d64794e396473f3b1/schemas/v2.0/schema.json#L151"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a></td>
      
    </tr>

</table>

<h2 id="discussions">Discussions</h2>

<table class="table-documentation-links">

  <thead>
    <tr>
      <th colspan="3" scope="col">termsOfService should be a URL</th>
    </tr>
    </thead>
  <tr>
    <td>Components</td>
    <td>Versions</td>
    <td>Issues and pull requests</td>
  </tr>
  <tr>
    <td>
      <ul class="list-group">
      
        
        
        
        
          
            <li class="list-group-item border-0 p-1"><code>Info.termsOfService</code></li> 
          
        
      
      </ul>
    </td>
    <td>
      <ul class="list-group text-center">
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span>
        </li>
      
      </ul>
    </td>
    <td>
      <ul>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/pull/255">Make clear that termsOfService should be an URL</a></li>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/pull/661">Make clear that info/termsOfService should be an URL.</a></li>
      
      </ul>
    </td>
  </tr>

  <thead>
    <tr>
      <th colspan="3" scope="col">Rich text markdown descriptions</th>
    </tr>
    </thead>
  <tr>
    <td>Components</td>
    <td>Versions</td>
    <td>Issues and pull requests</td>
  </tr>
  <tr>
    <td>
      <ul class="list-group">
      
        
        
        
        
          
            <li class="list-group-item border-0 p-1"><code>Info.description</code></li> 
          
        
      
      </ul>
    </td>
    <td>
      <ul class="list-group text-center">
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span>
        </li>
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span>
        </li>
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span>
        </li>
      
      </ul>
    </td>
    <td>
      <ul>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/pull/720">Change markdown standard from GFM to CommonMark</a></li>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/issues/972">Suggest we reference a specific version of CommonMark</a></li>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/issues/1867">Provide guidance on Markdown table syntax</a></li>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/issues/1078">CommonMark allows HTML tags, should some be prohibited/ignored?</a></li>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/pull/1090">Permit tooling to limit commonmark usage</a></li>
      
      </ul>
    </td>
  </tr>

  <thead>
    <tr>
      <th colspan="3" scope="col">Adding summary to Info object</th>
    </tr>
    </thead>
  <tr>
    <td>Components</td>
    <td>Versions</td>
    <td>Issues and pull requests</td>
  </tr>
  <tr>
    <td>
      <ul class="list-group">
      
        
        
        
        
          
            <li class="list-group-item border-0 p-1"><code>Info.summary</code></li> 
          
        
      
      </ul>
    </td>
    <td>
      <ul class="list-group text-center">
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span>
        </li>
      
      </ul>
    </td>
    <td>
      <ul>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/issues/832">Summary field in Info Object</a></li>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/pull/1779">832 add info.summary</a></li>
      
      </ul>
    </td>
  </tr>

  <thead>
    <tr>
      <th colspan="3" scope="col">Adding a license identifier</th>
    </tr>
    </thead>
  <tr>
    <td>Components</td>
    <td>Versions</td>
    <td>Issues and pull requests</td>
  </tr>
  <tr>
    <td>
      <ul class="list-group">
      
        
        
        
        
          
            <li class="list-group-item border-0 p-1"><code>License.identifier</code></li> 
          
        
      
      </ul>
    </td>
    <td>
      <ul class="list-group text-center">
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span>
        </li>
      
      </ul>
    </td>
    <td>
      <ul>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/issues/1599">identifier field for License Objects</a></li>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/pull/2105">Add SPDX identifier field to license object, fixes</a></li>
      
      </ul>
    </td>
  </tr>

  <thead>
    <tr>
      <th colspan="3" scope="col">License and terms of service clarifications</th>
    </tr>
    </thead>
  <tr>
    <td>Components</td>
    <td>Versions</td>
    <td>Issues and pull requests</td>
  </tr>
  <tr>
    <td>
      <ul class="list-group">
      
        
        
        
        
          
            <li class="list-group-item border-0 p-1"><code>Info.termsOfService</code></li> 
          
        
      
        
        
        
        
          <li class="list-group-item border-0 p-1"><code>License</code></li>
        
      
      </ul>
    </td>
    <td>
      <ul class="list-group text-center">
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span>
        </li>
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span>
        </li>
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span>
        </li>
      
      </ul>
    </td>
    <td>
      <ul>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/issues/726">Clarification on the purpose of the API license?</a></li>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/issues/1672">Provide additional detail in the documentation regarding the differences in Licensing vs. Terms of Service</a></li>
      
      </ul>
    </td>
  </tr>

  <thead>
    <tr>
      <th colspan="3" scope="col">The url and identifier are optional in specification and required in schema</th>
    </tr>
    </thead>
  <tr>
    <td>Components</td>
    <td>Versions</td>
    <td>Issues and pull requests</td>
  </tr>
  <tr>
    <td>
      <ul class="list-group">
      
        
        
        
        
          
            <li class="list-group-item border-0 p-1"><code>License.url</code></li> 
          
            <li class="list-group-item border-0 p-1"><code>License.identifier</code></li> 
          
        
      
      </ul>
    </td>
    <td>
      <ul class="list-group text-center">
      
        <li class="list-group-item border-0 p-1">
          <span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span>
        </li>
      
      </ul>
    </td>
    <td>
      <ul>
      
        <li><a href="https://github.com/OAI/OpenAPI-Specification/issues/2975">The mutually-exclusive url and identifier properties of License object are optional in specification and required in schema</a></li>
      
      </ul>
    </td>
  </tr>

</table>

<h2 id="samples">Samples</h2>

<p>All examples shown in this post and some others are listed below, they can be found in my <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/">openapi-samples</a> Github repository.</p>

<table>

  <thead>
  <tr>
    <th>Complete Info Object</th>
    <th class="text-center" colspan="3">Links</th>
  </tr>
  </thead>
  
  <tr>
    <td>Complete Info, Contact and License (url property) Objects</td>
    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/complete-license-url-version-31.openapi.yaml"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a>
      </td>

    
      
      <td class="text-center">
      </td>

    
      
      <td class="text-center">
      </td>

    
  </tr>
  
  <tr>
    <td>Complete Info, Contact and License (identifier property) Objects</td>
    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/complete-license-url-version-31.openapi.yaml"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a>
      </td>

    
      
      <td class="text-center">
      </td>

    
      
      <td class="text-center">
      </td>

    
  </tr>
  
  <tr>
    <td>Complete Info, Contact and License Objects</td>
    
      
      <td class="text-center">
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/complete-version-30.openapi.yaml"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/complete-version-20.openapi.yaml"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a>
      </td>

    
  </tr>
  

  <thead>
  <tr>
    <th>Minimal Info Object</th>
    <th class="text-center" colspan="3">Links</th>
  </tr>
  </thead>
  
  <tr>
    <td>Minimal Info Object</td>
    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/minimal-version-31.openapi.yaml"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/minimal-version-30.openapi.yaml"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/minimal-version-20.openapi.yaml"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a>
      </td>

    
  </tr>
  
  <tr>
    <td>Minimal Info, Contact and License Objects</td>
    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/minimal-contact-license-version-31.openapi.yaml"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/minimal-contact-license-version-30.openapi.yaml"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/minimal-contact-license-version-20.openapi.yaml"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a>
      </td>

    
  </tr>
  

  <thead>
  <tr>
    <th>Info description and markdown</th>
    <th class="text-center" colspan="3">Links</th>
  </tr>
  </thead>
  
  <tr>
    <td>Text only description</td>
    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-text-one-line-version-31.openapi.yaml"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-text-one-line-version-30.openapi.yaml"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-text-one-line-version-20.openapi.yaml"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a>
      </td>

    
  </tr>
  
  <tr>
    <td>Multiline text only description</td>
    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-text-multiline-version-31.openapi.yaml"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-text-multiline-version-30.openapi.yaml"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-text-multiline-version-20.openapi.yaml"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a>
      </td>

    
  </tr>
  
  <tr>
    <td>One line markdown description</td>
    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-markdown-one-line-version-31.openapi.yaml"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-markdown-one-line-version-30.openapi.yaml"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-markdown-one-line-version-20.openapi.yaml"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a>
      </td>

    
  </tr>
  
  <tr>
    <td>Multiline markdown description</td>
    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-markdown-multiline-version-31.openapi.yaml"><span class="badge badge-pill badge-success" style="font-size:1rem;">3.1</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-markdown-multiline-version-30.openapi.yaml"><span class="badge badge-pill badge-warning" style="font-size:1rem;">3.0</span></a>
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/description-markdown-multiline-version-20.openapi.yaml"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a>
      </td>

    
  </tr>
  

  <thead>
  <tr>
    <th>Text or URL termsOfService</th>
    <th class="text-center" colspan="3">Links</th>
  </tr>
  </thead>
  
  <tr>
    <td>Text termsOfService</td>
    
      
      <td class="text-center">
      </td>

    
      
      <td class="text-center">
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/tos-text-version-20.openapi.yaml"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a>
      </td>

    
  </tr>
  
  <tr>
    <td>URL termsOfService</td>
    
      
      <td class="text-center">
      </td>

    
      
      <td class="text-center">
      </td>

    
      
      <td class="text-center">
      
      <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/info-property/tos-url-version-20.openapi.yaml"><span class="badge badge-pill badge-danger" style="font-size:1rem;">2.0</span></a>
      </td>

    
  </tr>
  

</table>]]></content><author><name>Arnaud Lauret</name></author><category term="post" /><summary type="html"><![CDATA[The info property of an OpenAPI document contains metadata that provides an overview of an API, but what does it represent exactly? How did it evolve across the OpenAPI Specification versions? And how to can it be used and misused? This is the second post in the OpenAPI Specification Reference series.]]></summary></entry><entry><title type="html">What is the openapi property?</title><link href="https://apihandyman.io/what-is-the-openapi-property/" rel="alternate" type="text/html" title="What is the openapi property?" /><published>2022-07-06T00:00:00+00:00</published><updated>2022-07-06T00:00:00+00:00</updated><id>https://apihandyman.io/what-is-the-openapi-property</id><content type="html" xml:base="https://apihandyman.io/what-is-the-openapi-property/"><![CDATA[<p>No OpenAPI document without the openapi property, but what does it represent? How did it evolve across the OpenAPI Specification versions? And how to take advantage of it? This is the first post in the OpenAPI Specification Reference series.
<!--more--></p>

<div class="card series-toc">
  <div class="card-header series-toc-title">
    <h5 id="series">OpenAPI Specification Reference Series</h5>
  </div>
  <div class="row series-toc_content">
    <div class="col-md-7 series-toc-summary">
      <div class="card-body">
        <p class="card-text">
<p>This series aims to provide complete cross-version reference documentation about the OpenAPI Specification aggregating different sources of information. For each analyzed element, you’ll find its definition, how it evolved across the different versions of the specification, how it is used and misused and where to find more information about it. This structure may evolve with future posts.</p>

<p>This series’ posts are not intended to be actionable tutorials, they may be of interest to people involved in the evolution of the specification or creating tools, and also advanced OpenAPI users. Most of this content will probably be incorporated in the next version of the <a href="https://apihandyman.io/toolbox/openapi-map/">OpenAPI Map</a> and be useful for more actionable series/posts about OpenAPI and Spectral.</p>
</p>
      </div>
    </div>
    <div class="col-md-5 series-toc-list border-left">
      
      <ul class="list-group list-group-flush">
        
          
          
          <li class="list-group-item active">1 - What is the openapi property?</li>
          
        
          
          
          <li class="list-group-item"><a href="/what-is-the-info-property-in-openapi/">2 - What is the info property in OpenAPI?</a></li>
          
        
        
      </ul>
    </div>
  </div>
</div>

<h1 id="definition">Definition</h1>

<p>What represents the <code>openapi</code> property, is it required, and where it is located.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">An OpenAPI 3.1 document</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/openapi-reference/openapi/version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="1"><code class="code-block">openapi: 3.1.0

info:
  title: Demo API
  version: "1.0"

paths: {}</code></pre>
  </div>
</div>

<p>The <code>openapi</code> property (line 1 in the document above) specifies the version of the OpenAPI Specification used in the document. It does not participate in the description of an API itself; it could be considered the only “OpenAPI metadata” in an OpenAPI document.</p>

<p>The version of the OpenAPI Specification takes advantage of <a href="https://semver.org/">semantic versioning</a> <code>major.minor.patch</code>, <code>3.1.0</code> , for instance. Therefore, the <code>openapi</code> property is a string (not a number).  Note that some minor non-backward compatible modifications could happen (see Changelog).</p>

<p>The <code>openapi</code> property is required; an OpenAPI document will be considered invalid without it.</p>

<p>The <code>openapi</code> property is defined in the <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#oasObject">OpenAPI object</a> and located at the document’s root. It appears only once in a document.</p>

<h1 id="changelog">Changelog</h1>

<p>How the <code>openapi</code> property evolved across the different versions of the specification.</p>

<h2 id="version-20">Version 2.0</h2>

<p>In version 2.0 and earlier, the specification’s version was stored in a <code>swagger</code> property (at the same location) because that was the name of the specification at that time (read <a href="https://apihandyman.io/what-is-the-openapi-specification/">What is the OpenAPI Specification?</a> to learn more about this).</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">A Swagger 2.0 document</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/openapi-reference/openapi/version-20.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="1"><code class="code-block">swagger: "2.0"

info:
  title: Demo API
  version: "1.0"

paths: {}</code></pre>
  </div>
</div>

<h2 id="version-30">Version 3.0</h2>

<p>The new “OpenAPI Specification” name was introduced in the 3.0 version, hence the modification of the property’s name specifying the version of the specification to <code>openapi</code>.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">An OpenAPI 3.0 document</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/openapi-reference/openapi/version-30.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="1"><code class="code-block">openapi: 3.0.3

info:
  title: Demo API
  version: "1.0"

paths: {}</code></pre>
  </div>
</div>

<h2 id="version-31">Version 3.1</h2>

<p>While version 3.1 did not bring any structural change regarding the openapi property; it modified the interpretation of its value. Strict semantic versioning was used in version 3.0: a modification of the minor version (3.0.0 to 3.1.0, for instance) must be backward compatible. Version 3.1 introduces a “loose semantic versioning” where non-backward compatible minor version changes (3.1.0 to 3.2.0, for example) may be introduced if the impact is considered sufficiently low compared to the benefits.</p>

<div class="card card-code text-white bg-dark border-dark">
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">An OpenAPI 3.1 document</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code file controls">
          <a role="button" class="btn border-0 rounded-0" aria-label="download file" target="_blank" href="/code/openapi-reference/openapi/version-31.openapi.yaml" data-toggle="tooltip" data-placement="top" title="Download"><img class="btn-icon" src="/images/commons/icons/download.svg" /></a>
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="1"><code class="code-block">openapi: 3.1.0

info:
  title: Demo API
  version: "1.0"

paths: {}</code></pre>
  </div>
</div>

<h1 id="usage">Usage</h1>

<p>How the <code>openapi</code> property can be used and misused.</p>

<h2 id="use-case-examples">Use case examples</h2>

<p>While the <code>openapi</code> property has no use inside a document, it is pretty helpful for the tools and processes that take advantage of the OpenAPI Specification. By the way, if you plan to create a format (for whatever VALID reasons), I would highly recommend putting the version inside documents.</p>

<h3 id="openapi-parsers">OpenAPI Parsers</h3>

<ul>
  <li>Check you’re reading an OpenAPI document: if the property is absent, the document may not be an OpenAPI one.</li>
  <li>Choose an adapted parser or JSON Schema based on the name of the property (swagger, openapi) and its value (2.0, 3.0.X, 3.1.X).</li>
</ul>

<h3 id="api-tools">API Tools</h3>

<ul>
  <li>Check the document is compatible with the tools you’re using (version 3.1 is not supported in all tools yet at the moment this is written).</li>
  <li>Check the tools you plan to use are compatible with your existing documents.</li>
  <li>Raise warnings or errors when linting documents to enforce moving from Swagger 2.0 to OpenAPI 3 to stop using outdated and with-less-features tools.</li>
</ul>

<h3 id="api-governance">API Governance</h3>

<ul>
  <li>Raise warnings or errors when linting documents to enforce moving from Swagger 2.0 to OpenAPI 3 to allow describing and documenting APIs more precisely.</li>
  <li>Apply linting rules only on specific version(s) of the specification</li>
</ul>

<h2 id="troubleshooting">Troubleshooting</h2>

<p>The usual problems encountered with the <code>openapi</code> property.</p>

<h3 id="not-the-version-of-the-api">Not the version of the API</h3>

<p>When starting to use the OpenAPI Specification, the property and its value can be confounded with the version of the API described in the document (which is specified in <code>info.version</code>). Hopefully, most of the time, parsers will raise an error, but not straightforward like “did you try to put the API’s version in the <code>openapi</code> property instead of <code>info.version</code>?</p>

<h3 id="almost-semantic-versioning">Almost semantic versioning</h3>

<p>Be cautious with version 3.1 (and above) when working on OpenAPI-based tools because it introduces a “loose semantic versioning” where a minor version change may not be backward compatible (see Changelog). Version 3.1 introduces a few <a href="https://www.openapis.org/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0">non-backward-compatible-but-with-limited-impact changes</a>, mainly around schema definitions.</p>

<h3 id="missing-quotes">Missing quotes</h3>

<p>This is a concern only in version 2.0. It is recommended put quotes around the value in YAML because 2.0 would be interpreted as a number instead of a string.</p>

<h1 id="documentation">Documentation</h1>

<p>Where to find more information about the <code>openapi</code> property.</p>

<h2 id="official-documentation">Official documentation</h2>

<ul>
  <li>Version 3.1
    <ul>
      <li><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#versions">OpenAPI Specification version description</a></li>
      <li><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#oasObject">openapi property definition in OpenAPI object</a></li>
    </ul>
  </li>
  <li>Version 3.0
    <ul>
      <li><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#versions">OpenAPI Specification version description</a></li>
      <li><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#oasObject">openapi property definition in OpenAPI object</a></li>
    </ul>
  </li>
  <li>Version 2.0
    <ul>
      <li><a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#swagger-object">swagger property definition in Swagger object</a></li>
    </ul>
  </li>
</ul>

<h2 id="api-handyman-resources">API Handyman resources</h2>

<ul>
  <li>All examples shown in this post can be found in my <a href="https://github.com/arno-di-loreto/openapi-samples/tree/main/reference/openapi-property">openapi-samples</a> Github repository.</li>
</ul>]]></content><author><name>Arnaud Lauret</name></author><category term="post" /><summary type="html"><![CDATA[No OpenAPI document without the openapi property, but what does it represent? How did it evolve across the OpenAPI Specification versions? And how to take advantage of it? This is the first post in the OpenAPI Specification Reference series.]]></summary></entry><entry><title type="html">Lint APIs with Spectral</title><link href="https://apihandyman.io/lint-apis-with-spectral/" rel="alternate" type="text/html" title="Lint APIs with Spectral" /><published>2022-06-15T00:00:00+00:00</published><updated>2022-06-15T00:00:00+00:00</updated><id>https://apihandyman.io/lint-apis-with-spectral</id><content type="html" xml:base="https://apihandyman.io/lint-apis-with-spectral/"><![CDATA[<p>Are you struggling to design consistent APIs? On the verge of losing sanity while checking every single property of every schema is camelCased? Never remembering the parameters to use for pagination? Spectral is the tool you need: it will lint JSON Schema, AsyncAPI, and OpenAPI documents and do those checks for you.
<!--more--></p>

<p><em>Banner by my partner in crime <a href="https://linktr.ee/mrlapindesign">Mister Lapin</a>.</em></p>

<h1 id="spectral-is-a-json-and-yaml-linter">Spectral is a JSON and YAML linter</h1>

<p><a href="https://github.com/stoplightio/spectral">Spectral</a> is an open-source JSON and YAML linter created by <a href="https://stoplight.io/">Stoplight</a>. Imagine ESLint or SonarQube but for JSON and YAML.</p>

<blockquote class="blockquote">
    <p class="mb-0">Lint, or a linter, is a static code analysis tool used to flag programming errors, bugs, stylistic errors and suspicious constructs.</p><footer class="blockquote-footer">
        <cite title="Source Title"><a href="https://en.wikipedia.org/wiki/Lint_(software)">Wikipedia</a></cite>
    </footer></blockquote>

<p>Spectral checks that a JSON or YAML document respects some out-of-the-box or user-defined rules. Linting JSON or YAML documents allows ensuring different documents, possibly created by different persons are consistent with each other; that they share a similar look and feel. It makes them easier to read, and easier to maintain. Beyond styling, linting can also help avoid the use of wrong patterns.</p>

<p>As Spectral works on any JSON or YAML document, it can be used on formats like Kubernetes configuration file, Postman collection, Github action, JSON Schema, AsyncAPI, or OpenAPI. For instance, using Spectral, you can check that in a Github action file, all jobs have <code>snake_case</code> names or that any job’s step using <a href="https://github.com/marketplace/actions/deploy-to-github-pages"><code>github-pages-deploy-action</code></a> defines a <code>commit-message</code>. Linting a Postman collection, you can check that every request comes with at least an example.</p>

<h1 id="how-spectral-works">How Spectral works</h1>

<p>Using Spectral requires defining a ruleset and then using Spectral CLI to lint (analyze) a document with it.</p>

<h2 id="creating-a-ruleset">Creating a ruleset</h2>

<p>A Spectral ruleset can be defined in a JSON or YAML document. The following code snippet shows the content of a YAML Spectral ruleset file named <code>rules.spectral.yaml</code>. It defines a <code>title-no-api</code> rule that checks the name of an API (defined in an OpenAPI document) does not contain the word “API”.</p>

<div class="card card-code text-white bg-dark border-dark">
  
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">rules.spectral.yaml</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="3,7,9" data-start="1"><code class="code-block">rules:
  # Rule&#39;s name
  title-no-api:
    # Rule&#39;s description
    description: The title must not contain the word API
    # JSON Path to target
    given: $.info.title
    # Control applied on the target&#39;s value
    then:
      function: pattern
      functionOptions:
        notMatch: /\b(api)\b/i</code></pre>
  </div>
</div>

<p>Each Spectral rule works like this one, hence “given some path then do some controls”:</p>

<ul>
  <li>The “target” of the rule is defined in <code>given</code> using a <a href="https://jsonpath-plus.github.io/JSONPath/docs/ts/">JSON Path</a> expression. The  <code>$.info.title</code> path targets the <code>title</code> property of the <code>info</code> object which is located at the root (<code>$</code> ) of the OpenAPI document, hence the name of the API.</li>
  <li>The control that is done to the value of all the elements matching the given JSON path is defined in <code>then</code> by providing a <code>function</code> name and some options (<code>functionOptions</code> ) if required by the function. The <code>pattern</code> function used here ensures that the title doesn’t match a regular expression.</li>
</ul>

<h2 id="linting-a-document">Linting a document</h2>

<p>To install Spectral, run the following command (check the <a href="https://github.com/stoplightio/spectral#-installation-and-Usage">documentation</a> for other installation methods):</p>

<div class="card card-code text-white bg-dark border-dark">
  <pre class="copy-hidden code-copy">npm install -g @stoplight/spectral-cli
</pre>
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">Installing Spectral CLI</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-bash line-numbers" data-start="1"><code class="code-block">apihandyman&gt; npm install -g @stoplight/spectral-cli</code></pre>
  </div>
</div>

<p>Linting a document named <code>openapi.yml</code> with the <code>rules.spectral.yaml</code> created previously is done has follow:</p>

<div class="card card-code text-white bg-dark border-dark">
  <pre class="copy-hidden code-copy">spectral lint openapi.yaml -r rules.spectral.yaml
</pre>
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">Linting a document</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-bash line-numbers" data-start="1"><code class="code-block">apihandyman&gt; spectral lint openapi.yaml -r rules.spectral.yaml

/path/to/documents/openapi.yaml

 4:10  warning  title-no-api  The name of the API must not contain the word API  info.title

✖ 1 problem (0 errors, 1 warning, 0 infos, 0 hints)</code></pre>
  </div>
</div>

<p>For each problem, you get:</p>

<ul>
  <li>The problem’s location (<code>4:10</code> )as line and character numbers</li>
  <li>The triggered rule’s severity (<code>warning</code>, the default level when the rule doesn’t define it)</li>
  <li>The triggered rule name ( <code>title-no-api</code> )</li>
  <li>The description of the problem</li>
  <li>The path that triggered the rule( <code>info.title</code> )</li>
</ul>

<p>And indeed, the document that has been linted, contains the word “API” on line 4 in <code>info.title</code>  as shown below:</p>

<div class="card card-code text-white bg-dark border-dark">
  
  <div class="card-header">
    <div class="row m-0">
      <div class="col align-self-center">
        <p class="m-0 title">openapi.yaml</p>
      </div>
      <div class="col col-auto pr-0">
        <div class="btn-group" role="group" aria-label="code snippet control">
          <a role="button" class="btn code-copy-btn border-0 rounded-0" aria-label="copy" data-toggle="tooltip" data-placement="top" title="Copy"><img class="btn-icon" src="/images/commons/icons/copy.svg" /></a>
          
        </div>
      </div>
    </div>
  </div>
  <div class="card-body">
    <pre class="language-yaml line-numbers code-copy" data-line="4" data-start="1"><code class="code-block">openapi: &quot;3.1.0&quot;

info:
  title: Demo API
  version: &quot;1.0&quot;

paths: {}</code></pre>
  </div>
</div>

<h1 id="spectral-is-an-api-linter">Spectral is an API linter</h1>

<p>Spectral comes with handy and ready-to-use rules and functions that will make JSON Schema, OpenAPI, and AsyncAPI documents easier. But even without them, Spectral is an awesome tool when working on APIs.</p>

<p>Spectral really speeds up designing APIs your organization’s way and reviewing them. Using Spectral, you won’t lose time ensuring that the name of an API does not contain the word “API,” that all of your JSON schema properties are in camelCase, that every operation returning a list proposes the right pagination parameters, or that every operation returns at least a 2XX response. It can also tell you’re using a non-evolvable data structure such as a list of string or non-user-friendly required query parameters. Triggered Spectral rules will tell you what is wrong and how to fix it.</p>

<p>That means API designers and API reviewers lose less time on designing APIs the right way, with the right look and feel, and spend more time on creating the right APIs. Spectral also makes APIs more user-friendly, participating in the building of a great developer experience (DX).</p>

<h1 id="with-great-powers-comes-great-responsabilities">With great powers comes great responsabilities</h1>

<p>Spectral is a powerful tool that can be of great help to design consistent, evolvable,  and user-friendly APIs easily, in the long run, and at scale. But that will happen only if you know how to fully take advantage of it.</p>

<p>Spectral is a powerful tool that comes with a few challenges such as mastering JSON Path, mastering the functions, creating your own functions only when needed, designing user-friendly rules, governing rules, or being sure your rules actually work.
Spectral is a powerful tool that can be used in some not obvious ways to take even more advantage of it: it can output JSON and it’s also a library.</p>

<p>Hopefully, these are topics that will be covered in upcoming posts.</p>]]></content><author><name>Arnaud Lauret</name></author><category term="post" /><summary type="html"><![CDATA[Are you struggling to design consistent APIs? On the verge of losing sanity while checking every single property of every schema is camelCased? Never remembering the parameters to use for pagination? Spectral is the tool you need: it will lint JSON Schema, AsyncAPI, and OpenAPI documents and do those checks for you.]]></summary></entry></feed>