<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bump.sh</title>
    <description>The latest articles on DEV Community by Bump.sh (@bump).</description>
    <link>https://dev.to/bump</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F3713%2F3f0a58a2-a70b-4bae-8eb9-b28a51d122f2.png</url>
      <title>DEV Community: Bump.sh</title>
      <link>https://dev.to/bump</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bump"/>
    <language>en</language>
    <item>
      <title>JSON Streaming in OpenAPI 3.2</title>
      <dc:creator>Bump.sh</dc:creator>
      <pubDate>Tue, 02 Sep 2025 14:04:35 +0000</pubDate>
      <link>https://dev.to/bump/json-streaming-in-openapi-32-5dcl</link>
      <guid>https://dev.to/bump/json-streaming-in-openapi-32-5dcl</guid>
      <description>&lt;p&gt;Streaming data allows API servers to send and receive data in real-time or in chunks, rather than waiting for the entire response to be ready. This is already how browsers handle HTML, images, and other media, and now it can be done for APIs working with JSON.&lt;/p&gt;

&lt;p&gt;This can improve responses with lots of data, or be used to send events from server to client in realtime without polling or adding the complexity of Webhooks or WebSockets. Streaming works by sending "chunks", which clients can then work with individually instead of waiting for the entire response to be ready.&lt;/p&gt;

&lt;p&gt;Streaming JSON in particular is increasingly useful as expectations around big data, data science, and AI continue to grow. JSON on its own does not stream very well, but a few standards and conventions have popped up to expand JSON into a streamable format, and OpenAPI v3.2 introduces keywords to describe data in these stream formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON Streaming
&lt;/h2&gt;

&lt;p&gt;Streaming JSON is a bit tricky because JSON is not designed to be streamed. A naive approach might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1985-04-12T23:20:50.52Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hi!"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would trip up most tooling (because the closing bracket is not present in the payload), but we can use something like &lt;a href="https://jsonlines.org/" rel="noopener noreferrer"&gt;JSON Lines&lt;/a&gt; (a.k.a JSONL) to send one JSON instance per line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1985-04-12T23:20:50.52Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hi!"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1985-04-12T23:20:51.37Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hows it hangin?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1985-04-12T23:20:53.29Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bye!"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This format allows each line to be a valid JSON object, making it easy to parse with standard native tooling and a &lt;code&gt;for&lt;/code&gt; loop. There are a bunch of other streaming formats you might want to work with in your API like &lt;a href="https://github.com/ndjson/ndjson-spec" rel="noopener noreferrer"&gt;Newline Delimited JSON&lt;/a&gt; (NDJSON), &lt;a href="https://www.rfc-editor.org/rfc/rfc7464.html" rel="noopener noreferrer"&gt;JSON Text Sequence&lt;/a&gt;, &lt;a href="https://datatracker.ietf.org/doc/html/rfc8142" rel="noopener noreferrer"&gt;GeoJSON Text Sequence&lt;/a&gt;. Thankfully they are all quite similar and working with them in OpenAPI is almost identical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Streaming with OpenAPI
&lt;/h2&gt;

&lt;p&gt;OpenAPI v3.0 &amp;amp; v3.1 were able to stream binary data, but struggled to support JSON streaming formats as there was no standard way to define the &lt;strong&gt;schema of individual events&lt;/strong&gt; in a stream. People would try to describe things as an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;application/jsonl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;array&lt;/span&gt;
      &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
        &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
            &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;date-time&lt;/span&gt;
          &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might see this sort of thing around, but it's not valid, and will confuse tooling. A stream cannot be described as a single array, and it is a sequence of multiple objects on new lines which is rather different. Some tools could spot the &lt;code&gt;application/jsonl&lt;/code&gt; content type and figure that out, but we don't need awkward hacks anymore because the OpenAPI team have solved the problem. &lt;/p&gt;

&lt;p&gt;OpenAPI v3.2 introduces two new keywords to describe streamed data and events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;itemSchema&lt;/code&gt; - define the structure of each item in a stream.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;itemEncoding&lt;/code&gt; - define how those items are encoded (or serialized), as text, JSON, binary, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  itemSchema
&lt;/h3&gt;

&lt;p&gt;Describing a stream with &lt;code&gt;itemSchema&lt;/code&gt; works just like &lt;code&gt;schema&lt;/code&gt; with one difference: it will be applied to each item in the stream, instead of the entire response.&lt;/p&gt;

&lt;p&gt;Consider an example like the &lt;a href="https://github.com/bump-sh-examples/train-travel-api/" rel="noopener noreferrer"&gt;train travel API&lt;/a&gt; running a stream of tickets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/jsonl; charset=utf-8
Transfer-Encoding: chunked
Date: Tue, 19 Aug 2025 18:36:10 GMT
Connection: keep-alive
Keep-Alive: timeout=5

{"train":"ICE 123","from":"Berlin","to":"Munich","price":79.9}
{"train":"TGV 456","from":"Paris","to":"Lyon","price":49.5}
{"train":"EC 789","from":"Zurich","to":"Milan","price":59}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To describe this stream of items, we can use the &lt;code&gt;itemSchema&lt;/code&gt; keyword:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;application/jsonl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;itemSchema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;train&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
        &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
        &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
        &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;number&lt;/span&gt;
          &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;float&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tooling now has two important switches it can use to figure out how to handle the response. The &lt;code&gt;itemSchema&lt;/code&gt; makes it clear the response is a stream, and the &lt;code&gt;application/jsonl&lt;/code&gt; content type lets tooling decide how to present that.&lt;/p&gt;

&lt;p&gt;For streaming formats that just handle streams of JSON, the &lt;code&gt;itemSchema&lt;/code&gt; is often sufficient to describe the structure of each item in the stream. For more complicated formats, additional encoding information may be needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  itemEncoding
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;itemEncoding&lt;/code&gt; keyword allows you to specify how each item in the stream should be encoded, with the same encoding object as the &lt;code&gt;encoding&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;itemEncoding&lt;/code&gt; is only possible for &lt;code&gt;multipart/*&lt;/code&gt; responses, so it is not very useful for an API that's streaming JSON, unless you were streaming a mixture of JSON and assets/images on a single response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;multipart/mixed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;itemSchema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;$comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A single data image from the device&lt;/span&gt;
    &lt;span class="na"&gt;itemEncoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contentType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;image/jpg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's ignore itemEncoding for now and focus on the major use case of streams for APIs: streaming data and events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Popular Streaming Formats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jsonlines.org/" rel="noopener noreferrer"&gt;JSON Lines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ndjson/ndjson-spec" rel="noopener noreferrer"&gt;NDJSON&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc7464" rel="noopener noreferrer"&gt;JSON Text Sequences&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events" rel="noopener noreferrer"&gt;Server-Sent Events (SSE)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They all work a little different, but they share the common goal of allowing data to be sent in a continuous stream rather than as a single, complete response.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON Lines &amp;amp; NDJSON
&lt;/h3&gt;

&lt;p&gt;Working with JSON Lines or NDJSON is basically identical in OpenAPI, and feels very much like working with plain JSON responses just with a different header and a bit of &lt;code&gt;itemSchema&lt;/code&gt; usage.&lt;/p&gt;

&lt;p&gt;If using JSONL use content type &lt;code&gt;application/jsonl&lt;/code&gt;, and if using NDJSON use content type &lt;code&gt;application/x-ndjson&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/logs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Stream of logs as JSON Lines&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;200'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;A stream of JSON-format log messages that can be read&lt;/span&gt;
            &lt;span class="s"&gt;for as long as the application is running, and is available&lt;/span&gt;
            &lt;span class="s"&gt;in any of the sequential JSON media types.&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;application/jsonl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;itemSchema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
                &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
                    &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;date-time&lt;/span&gt;
                  &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
                    &lt;span class="na"&gt;minimum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
                  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
              &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;JSONL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Log entries&lt;/span&gt;
                  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;JSONL examples are just a string where each line is a valid JSON object.&lt;/span&gt;
                  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                    &lt;span class="s"&gt;{"timestamp": "1985-04-12T23:20:50.52Z", "level": 1, "message": "Hi!"}&lt;/span&gt;
                    &lt;span class="s"&gt;{"timestamp": "1985-04-12T23:20:51.37Z", "level": 1, "message": "Hows it hangin?"}&lt;/span&gt;
                    &lt;span class="s"&gt;{"timestamp": "1985-04-12T23:20:53.29Z", "level": 1, "message": "Bye!"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example once again shows JSONL as a series of JSON objects with a newline character &lt;code&gt;\n&lt;/code&gt; (0x0A) between them. This can only be described as a &lt;a href="https://yaml-multiline.info/" rel="noopener noreferrer"&gt;YAML multiline string&lt;/a&gt;, because JSONL/NDJSON cannot be described as plain JSON/YAML due to the newline characters.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember to use &lt;code&gt;value: |&lt;/code&gt; to write multi-line strings in YAML, because the pipe will allow newlines to be passed through. Using &lt;code&gt;value: &amp;gt;&lt;/code&gt; would remove newlines and put each JSON instance onto the same line. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The sample code for either of these formats could look a bit like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/tickets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/jsonl; charset=utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Transfer-Encoding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chunked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ticket&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;tickets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JSON Text Sequence
&lt;/h3&gt;

&lt;p&gt;A third JSON streaming format which would be identical other than a weird little complication. The other two formats are just a newline character &lt;code&gt;\n&lt;/code&gt; (0x0A) at the end of the line, but &lt;a href="https://www.rfc-editor.org/rfc/rfc7464.html" rel="noopener noreferrer"&gt;RFC 7464: JSON Text Sequence&lt;/a&gt; requires a control character at the start ASCII Record Separator (0x1E). This is not a visible character in most contexts, but it will be in there like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x1E{"timestamp": "1985-04-12T23:20:50.52Z", "level": 1, "message": "Hi!"}
0x1E{"timestamp": "1985-04-12T23:20:51.37Z", "level": 1, "message": "Hows it hangin?"}
0x1E{"timestamp": "1985-04-12T23:20:53.29Z", "level": 1, "message": "Bye!"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;0x1E&lt;/code&gt; (ASCII Record Separator) indicates the start of a new JSON object in the stream. Control characters are a bit magical and invisible to most text editors so it can be a little confusing. Working with JSON Text Sequence tooling for both producing the stream and reading the stream can solve this problem, letting the tooling insert and read out the control characters without you needing to worry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Generator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;json-text-sequence&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ... snip express setup ...&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/tickets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json-seq&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Generator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ticket&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;tickets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://www.npmjs.com/package/json-text-sequence" rel="noopener noreferrer"&gt;json-text-sequence&lt;/a&gt; package makes this easier and provides a simple method for generating and consuming JSON Text Sequences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server-Sent Events (SSE)
&lt;/h3&gt;

&lt;p&gt;Streaming JSON as chunks of data is only one way that JSON gets streamed. What about sending events, with some JSON being passed along as attributes?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events" rel="noopener noreferrer"&gt;Server-Sent Events&lt;/a&gt; (SSE) can handle this, as a standard for sending real-time updates from a server to a client over HTTP. In OpenAPI, you can define SSE streams using the &lt;code&gt;text/event-stream&lt;/code&gt; content type and the &lt;code&gt;itemSchema&lt;/code&gt; keyword to describe the structure of the events being sent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A request body to add a stream of typed data.&lt;/span&gt;
  &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;text/event-stream&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;itemSchema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
        &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
          &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
          &lt;span class="na"&gt;retry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;event&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="c1"&gt;# Define event types and specific schemas for the corresponding data&lt;/span&gt;
        &lt;span class="na"&gt;oneOf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;const&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;addString&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;const&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;addInt64&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;int64&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;const&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;addJson&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;contentMediaType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
              &lt;span class="na"&gt;contentSchema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
                &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;foo&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
                &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;integer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;oneOf&lt;/code&gt; is optional, but a handy use of &lt;a href="//_guides/openapi/specification/v3.2/data-models/schema-composition.md"&gt;polymorphism&lt;/a&gt; to describe different schemas for each event - which can really help with documentation and validation.&lt;/p&gt;

&lt;p&gt;Valid events to come through this stream might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event: addString
data: This data is formatted
data: across two lines
retry: 5

event: addInt64
data: 1234.5678
unknownField: this is ignored

event: addJSON
data: {"foo": 42}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sentinel Events
&lt;/h2&gt;

&lt;p&gt;Some streaming systems do not always send all data or events in the exact same way. The items in a stream could be polymorphic objects, or there could be some special events that come through to say the stream is closed (also known as sentinel events).&lt;/p&gt;

&lt;p&gt;Instead of trying to handle all of these edge cases with special new keywords, OpenAPI allows you to use the standard JSON Schema keywords to model these variations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;text/event-stream&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;itemSchema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;oneOf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;your normal data/event schema&amp;gt;&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;const&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[DONE]"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whatever the schema is, it can be defined using the standard JSON Schema keywords like &lt;code&gt;oneOf&lt;/code&gt;, &lt;code&gt;anyOf&lt;/code&gt;, or &lt;code&gt;allOf&lt;/code&gt; to handle variations in the event structure. This allows you to define a flexible schema that can accommodate different types of events in the stream.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We're excited for OpenAPI v3.2 to launch (hopefully any time in the next few weeks?) and we're working hard to get Bump.sh ready to support as much of &lt;a href="//_posts/2025-07-22-openapi-3-2-what-to-expect.md"&gt;the new functionality&lt;/a&gt; as possible. Let us know in the comments what features you're looking forward to, and share any ideas you have for how we can improve our support for streaming JSON in APIs.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Top 5 API documentation tools</title>
      <dc:creator>Bump.sh</dc:creator>
      <pubDate>Wed, 11 Jun 2025 15:52:48 +0000</pubDate>
      <link>https://dev.to/bump/top-5-api-documentation-tools-4nj6</link>
      <guid>https://dev.to/bump/top-5-api-documentation-tools-4nj6</guid>
      <description>&lt;p&gt;Without documentation nobody knows an API exists or how to use it, so it’s worth investing the time in creating clear, useful, understandable documentation. This will help customers integrate with their applications quicker, cut down on support calls, and allow coworkers to onboard quicker as they join the company or move teams.&lt;/p&gt;

&lt;p&gt;Fully documenting an API can be a long and difficult process, but new tools are always popping aiming to solve the problem in different ways. Some are open-source and some are Software-as-a-Service, some focus on beautiful interfaces, some focus on powerful functionality, and some focus on jamming AI all over the place.&lt;/p&gt;

&lt;p&gt;There’s no one tool to rule them all, and different tools may be chosen depending on who is in charge of setting up the documentation (API developers, technical writers, governance teams) and the intended audience (public APIs, internal APIs, partner APIs).&lt;/p&gt;

&lt;p&gt;There’s also the question of if this is for a single API or multiple APIs, whether or not other types of guides are supported (often via Markdown), and whether they support API discoverability through API catalogs to help customers pick between those various APIs or if you need to build that yourself.&lt;/p&gt;

&lt;p&gt;To learn which documentation tools can be helpful for different scenarios, let’s compare the most popular OpenAPI documentation tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bump.sh&lt;/li&gt;
&lt;li&gt;Redoc&lt;/li&gt;
&lt;li&gt;Scalar&lt;/li&gt;
&lt;li&gt;Stoplight Elements&lt;/li&gt;
&lt;li&gt;ReadMe.io&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bump.sh
&lt;/h2&gt;

&lt;p&gt;Bump.sh is a SaaS solution focused on building “Stripe-like” three column API reference documentation from OpenAPI and AsyncAPI documents from any source, using any workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44viyantud9evtrz7zm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44viyantud9evtrz7zm1.png" alt="Screenshot of Bump UI" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bump.sh focuses on getting out of your way, staying clear of the “Walled Garden” approach others take. Instead of forcing everything to be done through a very specific way through a user interface, it integrates with existing Git/CI workflows, providing useful insight through their automatic changelog and breaking change detection in pull requests. It’s also one of the first few tools to support AsyncAPI as well as OpenAPI, allowing for event-driven APIs to be documented along side the usual REST/HTTP APIs.&lt;/p&gt;

&lt;p&gt;API Catalogs are a strong feature known as Hubs, which allow for multiple APIs to be deployed from a variety of Git repos, or you can get creative with CI/CLI/API integrations to bring in API descriptions for anywhere. This is brilliant for large organizations trying to bring all their APIs into one place, even if teams have wildly different workflows, directory structures, design-first/code-first, spread around different GitHub/GitLab/Azure workspaces, and even allows for some older groups still using Subversion for some reason. This is the only tool compared which allows for this flexible approach to API catalogs. With different “Guests” able to view each Hub, this is brilliant for Partner APIs, especially as they can subscribe to API changes to be alerted of anything they need to know about directly.&lt;/p&gt;

&lt;p&gt;The brand new API Explorer has brought powerful Try It functionality to documentation which people are coming to expect in all API docs, with a dedicated UI for building requests. This improves the UX compared to some competitors which try to handle this all through the main documentation view, because that gets pretty crowded when there are a lot of parameters to set on any given request. To avoid losing track of the docs, the try it allows them to pop up in a side pane, allowing for quick reference during request construction.&lt;/p&gt;

&lt;p&gt;Multiple branches and versioning also make Bump.sh a great option for teams working on Public APIs where multiple versions of API documentation need to be maintained.&lt;/p&gt;

&lt;p&gt;The team pride themselves on availability, and zero chatbots or automation between you and getting an answer from a friendly dedicated technical support staff member. They’re real people working on making real software and not trying to game anything with AI.&lt;/p&gt;

&lt;p&gt;Bump.sh is free for 1 API, going up to €249/mo for multiple APIs, and an Enterprise option which focuses on tackling more complex needs and deep UI and UX integration into existing CMS’s using far more useful enterprise solutions than the usual JavaScript-widget approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Version control-focused API documentation.&lt;/p&gt;

&lt;p&gt;✅ Blazing fast load times thanks to scanning OpenAPI / AsyncAPI changes and serving the results, instead of processing documents on-the-fly every time.&lt;/p&gt;

&lt;p&gt;✅ SEO-friendly thanks to the pre-rendered crawlable documentation.&lt;/p&gt;

&lt;p&gt;✅ Automatically detects and highlights API changes.&lt;/p&gt;

&lt;p&gt;✅ Supports AsyncAPI, OpenAPI 3.1, 3.0 &amp;amp; 2.0, Webhooks, and Overlays.&lt;/p&gt;

&lt;p&gt;✅ Enterprise: Can be run as .com/docs/* thanks to proxy support.&lt;/p&gt;

&lt;p&gt;✅ Enterprise: Can be embedded with custom header/footer with server-side rendered content for maximum SEO/crawler-friendly docs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Cloud hosted only, no self-hosted or open-source options.&lt;/p&gt;

&lt;p&gt;❌ CSS maintenance is done by Bump.sh (no conventional customization/theming), yet brought a level higher with the Embedded mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI/CD-focused teams integrating API documentation into DevOps workflows or docs-as-code workflows.&lt;/li&gt;
&lt;li&gt;Anyone trying to avoid being stuck in a walled garden. Your Git/CI is the source of truth.&lt;/li&gt;
&lt;li&gt;Teams working with complex API ecosystems, whether because multiple APIs, multiple API versions, many endpoints, deeply detailed objects, and/or fast evolving APIs.&lt;/li&gt;
&lt;li&gt;Tech reviewers eager for breaking change detection and API diffs to save them staring at a wall of potentially irrelevant YAML changes.&lt;/li&gt;
&lt;li&gt;Redoc&lt;/li&gt;
&lt;li&gt;Redoc is an old champion in the OpenAPI documentation world, built by Redocly to offer a beautiful “Stripe-like” two or three panel experience back when the only real choice was the less appealing Swagger UI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Screenshot of Redoc UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Redoc is also available as a self-hosted/open-source option, and a hosted version is available as part of a larger SaaS platform Realm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlx0dksjbeefawwg6fzx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlx0dksjbeefawwg6fzx.png" alt="Screenshot of Redoc UI" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Self-hosted Redoc only displays one API at a time, meaning anyone with multiple APIs is going to need to build their own developer experience hubs using CMS’, documentation tools, or custom coded solutions if they want coherent navigation between them all.&lt;/p&gt;

&lt;p&gt;The hosted Redoc on the $10/month Pro allows for multiple APIs but only within a single project, which means work needs to be done to get multiple OpenAPI documents into that project instead of supporting multiple APIs in multiple sources.&lt;/p&gt;

&lt;p&gt;The $24/month Enterprise plan comes with SSO for managing who can edit APIs, and “guest SSO” for hiding the resulting API documentation which is handy for partner APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Highly customizable, professional-looking UI.&lt;/p&gt;

&lt;p&gt;✅ Supports AsyncAPI, and OpenAPI 3.1, 3.0, and 2.0.&lt;/p&gt;

&lt;p&gt;✅ Can be self-hosted or used as a cloud service.&lt;/p&gt;

&lt;p&gt;✅ Includes “Try It” functionality on the cloud version.&lt;/p&gt;

&lt;p&gt;✅ Provides API governance through the hosted version, and a handy linting and bundling CLI tool.&lt;/p&gt;

&lt;p&gt;✅ Supports developer portal through Realm and Reunite SaaS products.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Requires some developer effort for customization.&lt;/p&gt;

&lt;p&gt;❌ No Try It on the self-hosted version.&lt;/p&gt;

&lt;p&gt;❌ Configuration is all done with YAML.&lt;/p&gt;

&lt;p&gt;❌ Builds interface on-the-fly by reading an OpenAPI document so large APIs load slowly.&lt;/p&gt;

&lt;p&gt;❌ Hosted version suffers very slow server-side rendering too.&lt;/p&gt;

&lt;p&gt;❌ Only add one Guest SSO identity provider per organization making partner APIs for multiple organizations difficult.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open-source API maintainers looking for a solid off-the-shelf open-source API documentation solution (self-hosted version).&lt;/li&gt;
&lt;li&gt;Teams who don’t mind writing some code to get highly customizable self-hosted API documentation, especially if trying to embed into existing CMS’ (self-hosted version).&lt;/li&gt;
&lt;li&gt;Publishing high quality reference documentation and guides for a single partner on an easily sharable link when no existing developer experience hubs exist (SaaS version).&lt;/li&gt;
&lt;li&gt;Scalar&lt;/li&gt;
&lt;li&gt;Scalar is made by developers, for developers, and you can tell. From the heavy focus on open-source tooling, to the dark-mode default with small text, and use of JetBrains Mono font, a quick glance at Scalar screams “programmers were here”.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scalar UI
&lt;/h2&gt;

&lt;p&gt;The toolsuite is very new, with a crux of their effort going into low-level open-source tooling to lay a groundwork for the rest of their tools to build upon. The nascent nature of their offering and their OSS focus doesn’t place them as a go-to solution for Enterprise customers who need more dedicated assistance, but their integration with open-source projects like Gitbook, Nitro, and Rust will make it a good choice for users of those tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fccfgim15o7ux5kuu8v2g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fccfgim15o7ux5kuu8v2g.png" alt="Screenshot of Scalar UI" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ A drop-in replacement for single developers and small teams switching away from SwaggerHub, replacing Swagger UI &amp;amp; Swagger Editor.&lt;/p&gt;

&lt;p&gt;✅ Supports OpenAPI 3.1, 3.0, and 2.0.&lt;/p&gt;

&lt;p&gt;✅ All versions of Scalar support a powerful Try It / API client.&lt;/p&gt;

&lt;p&gt;✅ Cloud version has a built in text-based OpenAPI editor which handles small single-file OpenAPI documents.&lt;/p&gt;

&lt;p&gt;✅ Supports guides as well as reference documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Customization and theming focuses mostly on color schemes and custom CSS.&lt;/p&gt;

&lt;p&gt;❌ Editor does not support external references.&lt;/p&gt;

&lt;p&gt;❌ Doesn’t offer advanced API governance tools.&lt;/p&gt;

&lt;p&gt;❌ Builds interface on-the-fly by reading an OpenAPI document so large APIs load slowly.&lt;/p&gt;

&lt;p&gt;❌ Free SaaS only gets one user, then its $12/seat, with SSO behind a “Talk to the CEO” button.&lt;/p&gt;

&lt;p&gt;❌ GitHub Sync only available on Pro, with no other way to deploy via CLI or CI/CD.&lt;/p&gt;

&lt;p&gt;❌  Supports multiple APIs but no API Catalog / Dev Portal functionality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solo API developers who want a desktop HTTP client which happens to also produce API documentation.&lt;/li&gt;
&lt;li&gt;Open-source tools (e.g. web application frameworks, content management systems) which could themselves be self-hosted with an API and generate API endpoints / OpenAPI. Scalar would help turn that users generated OpenAPI into API documentation for their end-users without any SaaS involved.&lt;/li&gt;
&lt;li&gt;Stoplight Elements&lt;/li&gt;
&lt;li&gt;Stoplight Elements is a Web/React component that drops into existing documentation or open-source, allowing anyone to enjoy Stripe-like API documentation. It focuses on being as beautiful as possible, whilst still delivering the same functionality and covering the same use cases as Swagger UI. The tool was aiming to knock Swagger UI off the “top spot” years back, but active development has slowed to a crawl in a plume of irony after Swagger UI owners SmartBear bought Stoplight. It’s getting bug fixes and a handful of tweaky features, and development may well pick up again in the future, so it’s not out of the game just yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stoplight Elements UI
&lt;/h2&gt;

&lt;p&gt;The self-hosted tool can take any OpenAPI document by URL or path, but can only handle one API at a time like most of the self-hosted tools. There is an extension called Elements DevPortal, which can handle multiple APIs and Markdown guides, but this assumes all the APIs are in the same Stoplight Platform “project”. It’s essentially a mini API Catalog, but the catalog cannot pull OpenAPI/Markdown content out of multiple projects or repos making the catalog functionality a little limited.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xhd27ool4uk7iimnki7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xhd27ool4uk7iimnki7.png" alt="Screenshot of Stoplight Elements UI" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Beautiful, interactive documentation with Try-It functionality.&lt;/p&gt;

&lt;p&gt;✅ Supports OpenAPI 3.1, 3.0, and 2.0.&lt;/p&gt;

&lt;p&gt;✅ Easy integration into existing documentation or apps via Web/React components.&lt;/p&gt;

&lt;p&gt;✅ Integrates with Stoplight Platform, a SaaS ecosystem which includes a GUI for API design, and API governance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Limited out-of-the-box customization compared to Redocly.&lt;/p&gt;

&lt;p&gt;❌ Confusing to get started for non technical users as it needs a web server and code to load the component.&lt;/p&gt;

&lt;p&gt;❌ Stoplight’s full suite can be expensive, with unlimited APIs/projects but paying per user.&lt;/p&gt;

&lt;p&gt;❌ Builds interface on-the-fly by reading an OpenAPI document so large APIs load slowly.&lt;/p&gt;

&lt;p&gt;❌ No API catalog functionality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Teams already using Stoplight for API design.&lt;/li&gt;
&lt;li&gt;Companies that prefer embedding documentation within existing apps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ReadMe
&lt;/h2&gt;

&lt;p&gt;ReadMe is a hosted developer portal which allows for API documentation in all forms, not just API reference documentation, but supports Markdown guides and even Recipes for documenting workflows and breaking down code samples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu3mq4ge45sgko8bbs95s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu3mq4ge45sgko8bbs95s.png" alt="Screenshot of ReadMe UI" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of deploying changes from a Git repository or providing an editor to make changes directly, there is a two-way sync to merge in changes.&lt;/p&gt;

&lt;p&gt;ReadMe is a strong pick for DevRel teams as it has built-in support for user feedback, a discussion forum, and tracks analytics. This can allow for data-driven improvements to the developer experience.&lt;/p&gt;

&lt;p&gt;The pricing starts off ok for startups at $99/month, but ramps up quickly to $399/month for custom CSS/HTML. Extras send the price even higher, with $100/month for developer dashboards. and another $150/month to enable a ChatGPT-enabled “Owlbot” taking a punt at answering questions with what might even occasionally be correct answers sometimes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Provides interactive API docs with an API explorer.&lt;/p&gt;

&lt;p&gt;✅ Includes a developer portal with guides and tutorials.&lt;/p&gt;

&lt;p&gt;✅ User feedback and discussions.&lt;/p&gt;

&lt;p&gt;✅ Great for SaaS companies offering public APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Pricing can be high for startups.&lt;/p&gt;

&lt;p&gt;❌ Cloud hosted only, no self-hosted or open-source options.&lt;/p&gt;

&lt;p&gt;❌ Less control over the doc styling compared to self-hosted solutions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Teams that need API documentation and developer engagement tools.&lt;/li&gt;
&lt;li&gt;Businesses that want built-in analytics and API usage tracking.&lt;/li&gt;
&lt;li&gt;Recommendations&lt;/li&gt;
&lt;li&gt;So which is the best tool? As always “it depends”, so here are some quick pointers to help find the right tool for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When it comes to API docs, there’s no shortage of options, and no single right answer for every team.&lt;/p&gt;

&lt;p&gt;If you care about performance and SEO Bump.sh is the right pick.&lt;/p&gt;

&lt;p&gt;If you’re looking for a tool that fits cleanly into a modern, Git-based workflow, scales across multiple APIs and teams, and doesn’t lock you into yet another platform, Bump.sh has your back.&lt;/p&gt;

&lt;p&gt;Bump.sh is built for engineers and tech writers who want docs to ship like code: fast, versioned, and CI-integrated. It handles the messy reality of modern API ecosystems (REST, event-driven, partners, multiple teams, multiple repos) and turns that into a clean, scalable developer experience.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OpenAPI 3.1 - The Cheat Sheet</title>
      <dc:creator>Bump.sh</dc:creator>
      <pubDate>Wed, 18 Sep 2024 15:09:40 +0000</pubDate>
      <link>https://dev.to/bump/openapi-31-the-cheat-sheet-c9l</link>
      <guid>https://dev.to/bump/openapi-31-the-cheat-sheet-c9l</guid>
      <description>&lt;p&gt;We can't tell you how stoked we are about this. It's been a while that we realized something key was missing, to help the entire community adopt and use &lt;a href="https://bump.sh/openapi" rel="noopener noreferrer"&gt;OpenAPI&lt;/a&gt; daily.&lt;/p&gt;

&lt;p&gt;Something short enough, while thorough enough, so that you always make sure you always completely describe your API, without missing any crucial information, nor wondering "Hugh... How do I write this again?" and having to scan through the entire specification.&lt;/p&gt;

&lt;p&gt;Something you could even hold in your hands. Because, yes, as much as we avoid printing things on a day-to-day basis, sometimes screens are not enough. Teachers, rest assured: our cheat sheet print-outs are too large to be hidden in your students pockets.&lt;/p&gt;

&lt;p&gt;Anyway, that's it, we made it. Let us introduce the OpenAPI 3.1 Cheat Sheet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn8aj3wkovvh9i9lhfb3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn8aj3wkovvh9i9lhfb3.png" alt="Image description" width="800" height="565"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://storage.googleapis.com/bump-blog-resources/openapi-31-cheasheet/openapi-31-cheatsheet-v1.pdf" rel="noopener noreferrer"&gt;Download the PDF version&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It took us about 6 months to produce this first version. First of all, because we're of course quite busy developing Bump.sh and serving our customers. But more importantly, because synthesizing OpenAPI on an A4/US letter sheet is just not trivial.&lt;/p&gt;

&lt;p&gt;The Specification covers a wide range of use cases. It is robust in the sense that your APIs can be completely described, so that humans and machines alike can discover it, and interact with it. In the end, an OpenAPI contract can become quite deep and complex. We wanted to squeeze the essence out of it, and brainstormed multiple times about what should be in (and how), and what should be out.&lt;/p&gt;

&lt;p&gt;You'll read it on your own, but here are the sections we retained:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.bump.sh/guides/openapi/specification/v3.1/understanding-structure/basic-structure/" rel="noopener noreferrer"&gt;Document Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.bump.sh/guides/openapi/specification/v3.1/understanding-structure/basic-structure/#2-info-object" rel="noopener noreferrer"&gt;General Information&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.bump.sh/guides/openapi/specification/v3.1/understanding-structure/paths-operations/" rel="noopener noreferrer"&gt;API Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.bump.sh/guides/openapi/specification/v3.1/data-models/schema-and-data-types/" rel="noopener noreferrer"&gt;Data Types and Schemas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.bump.sh/guides/openapi/specification/v3.1/advanced/security/" rel="noopener noreferrer"&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.bump.sh/guides/openapi/specification/v3.1/advanced/splitting-documents-with-ref/" rel="noopener noreferrer"&gt;Reuse Elements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.bump.sh/guides/openapi/specification/v3.1/data-models/schema-composition/" rel="noopener noreferrer"&gt;Polymorphism&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.bump.sh/guides/openapi/specification/v3.1/documentation/grouping-operations-with-tags/" rel="noopener noreferrer"&gt;Grouping and sorting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We had a chance to work on this with OpenAPI experts (👋 Phil Sturgeon, James Higginbotham and Kin Lane, as well as some of our key power users at Elastic, Lightspeed Commerce, and many more).&lt;/p&gt;

&lt;p&gt;And we wanted to make the outcome of that work accessible completely for free, as the entire OpenAPI community should benefit from it, free of charge. It is &lt;a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en" rel="noopener noreferrer"&gt;CC BY-NC-SA 4.0 licensed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To be honest and transparent, this is a first version of that Cheat Sheet. We might have been a little too enthusiastic to print it for apidays London 2024. Fetch your exclusive sample there: there won't be many, and we'll have to print new versions for Paris as we've already spotted some typos.&lt;/p&gt;

&lt;p&gt;They're fixed in the downloadable PDF version, but if you have a hard copy and spot those errors, we're paying a drink to the first 5 people who drop by our booth with the full list of errors.&lt;/p&gt;

&lt;p&gt;This Cheat Sheet will be lively in the coming weeks and months. We'll work on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;improving the current version&lt;/li&gt;
&lt;li&gt;making a web version of it&lt;/li&gt;
&lt;li&gt;covering the next versions of OpenAPI (Moonwalk, we see you)&lt;/li&gt;
&lt;li&gt;making one for AsyncAPI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Share it with your network, the person working next to you or the world via social media; it's built for that!&lt;/p&gt;

</description>
      <category>api</category>
      <category>openapi</category>
    </item>
    <item>
      <title>An AsyncAPI Example: Building Your First Event-driven API</title>
      <dc:creator>Bump.sh</dc:creator>
      <pubDate>Tue, 19 Sep 2023 08:44:20 +0000</pubDate>
      <link>https://dev.to/bump/an-asyncapi-example-building-your-first-event-driven-api-37jo</link>
      <guid>https://dev.to/bump/an-asyncapi-example-building-your-first-event-driven-api-37jo</guid>
      <description>&lt;p&gt;Event-driven APIs are APIs that use events to enable real-time and asynchronous communication between different components of a system. This leads to a couple significant benefits right out of the gate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clients receive real-time updates without constantly polling the server, which improves user experience.&lt;/li&gt;
&lt;li&gt;System components can communicate without being directly connected to each other, so API producers and consumers can be more loosely coupled.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Use Event-driven APIs?
&lt;/h2&gt;

&lt;p&gt;Let’s break those two ideas down a bit so you can really see what’s going on.&lt;/p&gt;

&lt;p&gt;An &lt;em&gt;event&lt;/em&gt; is any change in state or an update that a client might be interested in, like a new user registration or an update in the payment status of a transaction. In an event-driven system, a component known as the &lt;em&gt;publisher&lt;/em&gt; sends an event to a message broker. The message broker sends the event to all the other components, known as &lt;em&gt;subscribers&lt;/em&gt;, that have registered to receive that particular event. This allows the components of the system to communicate in real-time without being directly connected to each other.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4ncnxk0xo7vzlg5vbgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4ncnxk0xo7vzlg5vbgg.png" alt="Event Driven Architecture" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an example, picture a chat application. When a user sends a message, an event-driven API can immediately notify all the other users in the chat, allowing the message to display in their chat window without needing to refresh the page. In a traditional synchronous API, the client would need to poll the server to check for new messages very often and then update the user.  With event-driven APIs, clients receive real-time updates from the API without constantly polling for changes, making them more efficient when it comes to network resource usage. &lt;/p&gt;

&lt;p&gt;In a traditional synchronous request-response API, the components are tightly coupled. The consumer must make a request to the provider to receive data (say, for example, polling for new messages in a chat application). In an event-driven API, the components are decoupled. The publisher sends events to the message broker, which then broadcasts the events to the subscribers. The separate components can be more independent and flexible, since they don’t rely on direct communication with each other. &lt;/p&gt;

&lt;p&gt;However, in order for the system to work effectively, there must be a common understanding between the components regarding events and their data structures. This is where &lt;a href="https://www.asyncapi.com/" rel="noopener noreferrer"&gt;AsyncAPI&lt;/a&gt; comes in; it helps define a &lt;a href="https://bump.sh/blog/api-contracts-extended-introduction" rel="noopener noreferrer"&gt;contract&lt;/a&gt; that describes how the components communicate and behave effectively.&lt;/p&gt;

&lt;p&gt;Let’s walk through the process of implementing an event-driven API using AsyncAPI, a specification for defining asynchronous APIs. We’ll also introduce &lt;a href="https://bump.sh/" rel="noopener noreferrer"&gt;Bump.sh&lt;/a&gt;, a tool for documenting and tracking event-driven APIs lifecycle/changes, and demonstrate how you can use it in conjunction with AsyncAPI files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing a Node.js Event-Driven API with AsyncAPI
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.asyncapi.com/" rel="noopener noreferrer"&gt;AsyncAPI&lt;/a&gt; is a specification for defining the structure and behavior of event-driven APIs. It’s &lt;a href="https://www.asyncapi.com/blog/openapi-vs-asyncapi-burning-questions" rel="noopener noreferrer"&gt;similar to OpenAPI&lt;/a&gt;, a specification for defining REST APIs.&lt;/p&gt;

&lt;p&gt;However, AsyncAPI has specific features for defining the events and subscriptions of an event-driven API. It provides a standardized way to describe the events, channels, and message formats used in an asynchronous API, making it easier for developers to understand and use that API. &lt;/p&gt;

&lt;p&gt;Before we begin the process of implementing a Node.js event-driven API described using AsyncAPI, there are a few prerequisites that you will need to have installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional:&lt;/strong&gt; &lt;a href="https://mosquitto.org/" rel="noopener noreferrer"&gt;Mosquitto&lt;/a&gt;, an open-source message broker that                 implements the &lt;a href="https://mqtt.org/mqtt-specification/" rel="noopener noreferrer"&gt;MQTT protocol&lt;/a&gt;; this tutorial uses the &lt;a href="%E2%80%8B%E2%80%8Bhttps://test.mosquitto.org/"&gt;public test server&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have these installed, you can follow the steps below to implement your event-driven API.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create an AsyncAPI File
&lt;/h3&gt;

&lt;p&gt;First, create an AsyncAPI file. This will define the events and their corresponding data that you’ll use in your event-driven system. It also defines the structure and behavior of your asynchronous APIs.&lt;/p&gt;

&lt;p&gt;AsyncAPI files are written in YAML or JSON and follow a specific format defined by the &lt;a href="https://www.asyncapi.com/docs/reference" rel="noopener noreferrer"&gt;AsyncAPI specification&lt;/a&gt;. An AsyncAPI file consists of several main components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;asyncapi&lt;/code&gt;: Specifies the version of the AsyncAPI specification that the file follows; at time of writing, the latest available is v2.6.0, which is what this tutorial uses.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;info&lt;/code&gt;: Contains metadata about the API, such as the &lt;code&gt;title&lt;/code&gt;,  the &lt;code&gt;version&lt;/code&gt; or the &lt;code&gt;description&lt;/code&gt; of your API.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.asyncapi.com/docs/concepts/server" rel="noopener noreferrer"&gt;&lt;code&gt;servers&lt;/code&gt;&lt;/a&gt;: Lists the servers that the API is available on, along with the protocol and any additional configuration required to use the server. In our testing API, that will be the network location of our message broker.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.asyncapi.com/docs/concepts/channel" rel="noopener noreferrer"&gt;&lt;code&gt;channels&lt;/code&gt;&lt;/a&gt;: Defines the channels that the API exposes, along with the operations that can be performed on each channel.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;components&lt;/code&gt;: Defines reusable components that can be used throughout the AsyncAPI file, such as &lt;a href="https://www.asyncapi.com/docs/concepts/message" rel="noopener noreferrer"&gt;message&lt;/a&gt; payloads and security schemes. This section is optional, as you can define these components directly, but I do recommend it. As your AsyncAPI definition file starts to grow, this helps you avoid repeating yourself (e.g., when a message format is used in multiple channels).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The snippet below defines the first part of the AsyncAPI file for a chat application. It covers the general application descriptions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;asyncapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2.6.0&lt;/span&gt;
&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Chat Application&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;testing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test.mosquitto.org:1883&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mqtt&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test broker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This AsyncAPI file defines a chat application using the AsyncAPI 2.6.0 version.&lt;/p&gt;

&lt;p&gt;It also defines the &lt;code&gt;servers&lt;/code&gt; block that specifies the network location of your message broker. The API application defined here uses the MQTT protocol and is available on the testing server at &lt;code&gt;test.mosquitto.org:1883&lt;/code&gt;. This URL is a publicly available Mosquitto broker for test purposes; feel free to replace it with a local URL if you have Mosquitto installed on your environment.&lt;/p&gt;

&lt;p&gt;The following section defines the channels available within the API. It defines the different operations the chat application can perform and their payloads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;channels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;chat&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;publish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;onMessageReceieved&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text&lt;/span&gt;
        &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;subscribe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sendMessage&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text&lt;/span&gt;
        &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The channels section defines all the channels that the API exposes. In this case, there is a single channel called &lt;code&gt;chat&lt;/code&gt; that exposes a &lt;code&gt;publish&lt;/code&gt; and &lt;code&gt;subscribe&lt;/code&gt; operation. The &lt;code&gt;publish&lt;/code&gt; method allows clients to send messages to the chat application via the &lt;code&gt;chat&lt;/code&gt; channel, while the &lt;code&gt;subscribe&lt;/code&gt; method allows users to receive messages from the &lt;code&gt;chat&lt;/code&gt; channel.&lt;/p&gt;

&lt;p&gt;This might seem a bit counterintuitive as there are two sides to think about, the server application and the client. Instead, think about it this way: publish events are sent from the client to the application, while subscribe events are sent from the application to the clients.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Read more about &lt;a href="https://www.asyncapi.com/blog/publish-subscribe-semantics" rel="noopener noreferrer"&gt;pub-sub semantics here&lt;/a&gt;, then check out &lt;a href="https://github.com/asyncapi/spec/issues/618" rel="noopener noreferrer"&gt;this proposal&lt;/a&gt; that aims to resolve the confusion between publish and subscribe events. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the case of this tutorial, both operations have a very simple message payload of type &lt;code&gt;string&lt;/code&gt;, which defines the text to be sent on the message. However, the message could be more complex and in this case &lt;a href="https://www.asyncapi.com/docs/reference/specification/v2.6.0#schemaObject" rel="noopener noreferrer"&gt;described with JSON schema&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can review and copy &lt;a href="https://gist.github.com/mikeyny/2ab889716486944ff1eba999b4108190" rel="noopener noreferrer"&gt;the full file here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Generate the Application Code with AsyncAPI Generator
&lt;/h3&gt;

&lt;p&gt;After creating your AsyncAPI file, you can use the AsyncAPI Generator to automatically generate the code for your event-driven application. The AsyncAPI Generator is a command-line tool that can &lt;a href="https://github.com/asyncapi/generator#list-of-official-generator-templates" rel="noopener noreferrer"&gt;generate code in multiple languages&lt;/a&gt;, including JavaScript, Python, and Go.&lt;/p&gt;

&lt;p&gt;To use the AsyncAPI Generator, you will first need to install it using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g @asyncapi/generator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have installed the AsyncAPI Generator, you can use it to generate the code for your event-driven application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The generated code is meant to be a starting point, not a comprehensive build-and-use solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following command generates a functional node application from your AsyncAPI file. Make sure to replace the file and server names where appropriate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ag asyncapi.yaml @asyncapi/nodejs-template -p server=testing  -o example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command tells the AsyncAPI generator to generate Node.js code using the &lt;code&gt;asyncapi.yaml&lt;/code&gt; file that you created in the previous step. The generator will generate the code for the testing server we have just defined with our AsyncAPI file, and output those new files to a folder named &lt;code&gt;example&lt;/code&gt;. The AsyncAPI Generator supports code generation in &lt;a href="https://github.com/asyncapi/generator#list-of-official-generator-templates" rel="noopener noreferrer"&gt;many different languages&lt;/a&gt; such as Node, Java, Python, and Go.&lt;/p&gt;

&lt;p&gt;After running the command, you should have a full-fledged node application powering your event-driven application.&lt;/p&gt;

&lt;p&gt;You can run the following to install the dependencies and run the application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; node src/api/index.js

 SUB  Subscribed to chat
 PUB  Will eventually publish to chat
Chat Application 1.0.0 is ready!

🔗  MQTT adapter is connected!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Test the AsyncAPI Node.js Application
&lt;/h3&gt;

&lt;p&gt;To test the application, you need to send messages to the broker as a publisher. You can do this using the &lt;code&gt;MQTT.js&lt;/code&gt; library. Install it by running the following command in a separate terminal window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;mqtt &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command to send a message to the message broker. This command sends a publish command to the test broker on the &lt;code&gt;chat&lt;/code&gt; channel defined in your AsyncAPI file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mqtt pub &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="s1"&gt;'chat'&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="s1"&gt;'test.mosquitto.org'&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Hello World"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running this command, check the original window running the chat application, and you should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;← chat was received:
&lt;span class="s1"&gt;'{text: Hello World}'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This output means your application successfully received your message from the message broker. If you want to start implementing business logic, you can review the code in the example directory.&lt;/p&gt;

&lt;p&gt;You will find the handler for the messages under &lt;code&gt;examples/src/api/handlers/chat.js&lt;/code&gt;. The file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * 
 * @param {object} options
 * @param {object} options.message
 */&lt;/span&gt;
&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onMessageReceieved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Implement your business logic here...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="cm"&gt;/**
 * 
 * @param {object} options
 * @param {object} options.message
 */&lt;/span&gt;
&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Implement your business logic here...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Bump.sh with AsyncAPI
&lt;/h2&gt;

&lt;p&gt;By creating your AsyncAPI file, you actually also created an API contract ! You can &lt;a href="https://bump.sh/blog/api-contracts-extended-introduction" rel="noopener noreferrer"&gt;read all about them here&lt;/a&gt; but in short, an API contract specifies the components and describes the behavior of an API, for instance available events and data or the rules for using the API.&lt;/p&gt;

&lt;p&gt;You saw this earlier with the chat application implementation; you had to define the different channels as well as the operations that a client could perform on each channel.&lt;/p&gt;

&lt;p&gt;Having a clear and formal API contract can ensure that the different components of an event-driven system can communicate and work together effectively. It can also make it easier to collaborate with other developers and teams, since everyone will have a clear understanding of the API and how it’s working.&lt;/p&gt;

&lt;p&gt;You can use Bump.sh to document and keep track of the changes in your event-driven API via its AsyncAPI API contract. &lt;/p&gt;

&lt;p&gt;To use Bump.sh and generate your AsyncAPI based documentation, simply &lt;a href="https://bump.sh/users/sign_up?utm_source=bump&amp;amp;utm_medium=blog&amp;amp;utm_campaign=asyncapi-example-blog" rel="noopener noreferrer"&gt;create an account&lt;/a&gt;. Then you can simply drag and drop your AsyncAPI file in the onboarding flow.&lt;/p&gt;

&lt;p&gt;After signing up, fill out the following form with the details of your API:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx03ohynzs6fgtxmd9awn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx03ohynzs6fgtxmd9awn.png" alt="Bump.sh onboarding screen" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then proceed to upload your AsyncAPI file manually or using &lt;a href="https://github.com/bump-sh/cli" rel="noopener noreferrer"&gt;Bump.sh CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To upload your file using the CLI start by installing it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; bump-cli &lt;span class="c"&gt;# using npm&lt;/span&gt;
yarn global add bump-cli &lt;span class="c"&gt;# using yarn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then preview your generated API documentation by running :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bump preview path/to/file.json/yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI will respond with an URL that, if visited, will let you visualize for a few minutes how your API documentation would render in Bump.sh.&lt;/p&gt;

&lt;p&gt;When your AsyncAPI file is ready to be deployed, you can follow the simple steps of the &lt;a href="https://docs.bump.sh/help/getting-started/" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt; to have your API documentation live and ready to share.&lt;/p&gt;

&lt;p&gt;You can also connect the Bump.sh CLI to CI/CD tools, and there is even a GitHub Action you can add to any project. Which will allow you to automatically track and inform about API changes and deploy new versions of your API, among other cool possibilities you can read about on the &lt;a href="https://github.com/marketplace/actions/bump-sh" rel="noopener noreferrer"&gt;Bump.sh page in GitHub marketplace&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Event-driven APIs lead to real-time, responsive, and loosely-coupled systems, and AsyncAPI is a great way to define those APIs. By using AsyncAPI and Bump.sh together, you can create high-quality documentation for all your event-driven APIs.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to us if you have feedback, comments, or suggestions you’d like to share!&lt;/p&gt;

</description>
      <category>asyncapi</category>
      <category>eventdriven</category>
      <category>api</category>
      <category>node</category>
    </item>
    <item>
      <title>AsyncAPI vs. OpenAPI: Which Specification Is Right for Your App?</title>
      <dc:creator>Bump.sh</dc:creator>
      <pubDate>Thu, 03 Aug 2023 16:45:00 +0000</pubDate>
      <link>https://dev.to/bump/asyncapi-vs-openapi-which-specification-is-right-for-your-app-9l8</link>
      <guid>https://dev.to/bump/asyncapi-vs-openapi-which-specification-is-right-for-your-app-9l8</guid>
      <description>&lt;p&gt;Depending on how your application is designed and what it needs to accomplish, you probably want to consider choosing one type of communication protocol for your API over another—namely, synchronous or asynchronous. And which protocol you use determines which specification you need to follow for your API—&lt;a href="https://www.openapis.org/" rel="noopener noreferrer"&gt;OpenAPI&lt;/a&gt; or &lt;a href="https://www.asyncapi.com/" rel="noopener noreferrer"&gt;AsyncAPI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s take a brief look at the differences between synchronous and asynchronous APIs, and then we’ll talk about whether OpenAPI or AsyncAPI is best for communicating the ins and outs of your API to your users. &lt;/p&gt;

&lt;h2&gt;
  
  
  Synchronous vs. Asynchronous APIs
&lt;/h2&gt;

&lt;p&gt;Synchronous and asynchronous APIs differ mainly in how they process information.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Synchronous&lt;/em&gt; APIs respond to each client request with only minimal elapsed time, and clients must wait for the response before code execution can continue. This is the type of API that supports most of the internet, and they typically use the &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer" rel="noopener noreferrer"&gt;REST protocol&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Asynchronous&lt;/em&gt; APIs may provide a callback or notification when requested resources are ready, allowing clients to continue functioning without tying up resources waiting for a response from the API. These APIs use pub-sub messaging queues like &lt;a href="https://mqtt.org/" rel="noopener noreferrer"&gt;MQTT&lt;/a&gt; and &lt;a href="https://www.rabbitmq.com/" rel="noopener noreferrer"&gt;RabbitMQ&lt;/a&gt;, data streams like &lt;a href="https://kafka.apache.org/" rel="noopener noreferrer"&gt;Kafka&lt;/a&gt;, or bidirectional communication protocols like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" rel="noopener noreferrer"&gt;WebSockets&lt;/a&gt;. IoT devices also commonly use asynchronous APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing Between OpenAPI and AsyncAPI
&lt;/h2&gt;

&lt;p&gt;Documentation of your APIs is critical for communicating between backend and frontend developers. And good documentation can go beyond just improving the development experience - it can even increase adoption of your API.&lt;/p&gt;

&lt;p&gt;Industry-standard specifications like OpenAPI and AsyncAPI ensure that you’re effectively communicating to your users how they can interact with your API through an &lt;a href="https://bump.sh/blog/api-contracts-extended-introduction?utm_source=bump&amp;amp;utm_medium=blog&amp;amp;utm_campaign=blog-asyncapi-vs-openapi" rel="noopener noreferrer"&gt;API contract&lt;/a&gt;. Which spec you use to define and document your API depends on your use case, available resources, engineering team and community support, and chosen protocol to transmit data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In general, synchronous APIs can be defined using the OpenAPI standard, and asynchronous APIs can be defined using the AsyncAPI standard.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Protocols
&lt;/h3&gt;

&lt;p&gt;OpenAPI is typically used for RESTful APIs, which leverage HTTP or HTTPS as a transport protocol for data. The client makes a request to the server, which responds quickly (ideally within milliseconds or seconds). HTTP is mostly used as a unidirectional protocol, meaning the connection is closed after a single request and response. Each request must create a new connection to the server.&lt;/p&gt;

&lt;p&gt;To receive updates on any server changes, the client must rely on polling. Since the application does not know when a task will be completed, it must continue calling the API until the update is detected.&lt;/p&gt;

&lt;p&gt;AsyncAPI is based on event driven architectures (EDA). In this context, the sender and recipient don’t have to wait for a response from the other to do their next task or request.&lt;/p&gt;

&lt;p&gt;In event driven architectures, as you might have guess, it all revolves around events. An event is defined as a change of state. &lt;br&gt;
In an EDA, when an change of state occurs, the producer captures that event and sends it to all consumers who have subscribed to this event. There can be a broker in the middle in some cases. This way of architecturing APIs is refered to as Asynchronous.&lt;/p&gt;

&lt;p&gt;Asynchronous APIs can use bidirectional protocols, where a connection is maintained until it’s terminated by either the client or the server. Communication protocols like WebSockets allow the application to request data from the server but continue other processing while it waits for the response. Once resources are available to generate the response, the API produces a response, and the WebSocket connection streams the information back to the application.&lt;/p&gt;

&lt;p&gt;Applications can also subscribe to a channel on a message broker like MQTT, Kafka, or RabbitMQ where they can receive updates or notifications as events occur. When updates are no longer needed, the subscription can be terminated. &lt;/p&gt;

&lt;p&gt;A single API can make use of multiple protocols. We’ll talk more about that in a bit, but for now, suffice it to say that an API can combine synchronous and asynchronous methodologies, as well as use multiple asynchronous protocols. GraphQL APIs, for example, send queries over HTTP (a synchronous protocol), but also provide asynchronous messaging with WebSockets. &lt;/p&gt;

&lt;h3&gt;
  
  
  Simplicity of Implementation
&lt;/h3&gt;

&lt;p&gt;Since OpenAPI and AsyncAPI support different communication protocols, they require different skills to implement and different amounts of work as well. &lt;/p&gt;

&lt;p&gt;To implement an API designed according to OpenAPI, developers can use web application frameworks to set up the actual API. Authentication is also &lt;a href="https://spec.openapis.org/oas/latest.html#security-scheme-object" rel="noopener noreferrer"&gt;built into the standard&lt;/a&gt;, so everything needed to create your synchronous API is present once your OpenAPI document is created. Since synchronous APIs send messages directly to the endpoint, there’s no additional architecture required to build the API.&lt;/p&gt;

&lt;p&gt;On the other hand, implementing an asynchronous API is more complicated. Developers can still use web application frameworks, but they do need more architecture support than that. If your API uses a message broker as a middleman between application and API, that needs to be designed and built. If you’re using WebSockets to push notifications, both the server and the application need listener functions that keep the connection open.&lt;/p&gt;

&lt;h3&gt;
  
  
  Community Support
&lt;/h3&gt;

&lt;p&gt;AsyncAPI and OpenAPI are both open-source standards and part of the &lt;a href="https://www.linuxfoundation.org/" rel="noopener noreferrer"&gt;Linux Foundation&lt;/a&gt;. Both are stable, well-maintained specifications and should be supported well into the future. Still, there are a handful of differences when it comes to their ecosystems.&lt;/p&gt;

&lt;p&gt;OpenAPI is a more established standard, since it was developed for synchronous REST APIs. The OpenAPI specification has many contributors from the Linux Foundation and the community. Many more have contributed to the standard through discussion and examples. The &lt;a href="https://www.openapis.org/participate/how-to-contribute/governance" rel="noopener noreferrer"&gt;governance model of the OpenAPI Initiative&lt;/a&gt; allows both community and industry contributions in an effort to keep the specification vendor-neutral. To contribute, you must meet requirements for &lt;a href="https://www.openapis.org/membership/join" rel="noopener noreferrer"&gt;membership in the initiative&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;AsyncAPI is a newer standard based on OpenAPI. While it has fewer code contributors than OpenAPI, its popularity is quickly growing. AsyncAPI &lt;a href="https://www.asyncapi.com/blog/2021-summary" rel="noopener noreferrer"&gt;attributes its rising success&lt;/a&gt; to its community support and all the hosted tools related to AsyncAPI. In late 2020, AsyncAPI also formed an open governance model to &lt;a href="https://www.asyncapi.com/blog/governance-motivation" rel="noopener noreferrer"&gt;assure the community&lt;/a&gt; that no single company has control over AsyncAPI and that this initiative is, in fact, community driven. They even are &lt;a href="https://www.asyncapi.com/blog/asyncapi-joins-linux-foundation" rel="noopener noreferrer"&gt;a Linux Foundation Project&lt;/a&gt; since 2021.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;p&gt;Now, as we’ve already mentioned, whether you would use OpenAPI or AsyncAPI specification depends on what protocols your API uses. Which protocol you use depends on your specific use case and what backend resources are available for support. In general, OpenAPI is used to define APIs that provide immediate feedback (synchronous). The AsyncAPI spec defines APIs that don’t need to respond immediately to a request (asynchronous).&lt;/p&gt;

&lt;p&gt;But let’s see how that works out in some everyday use cases. When does one implementation have an advantage over the other?&lt;/p&gt;

&lt;h4&gt;
  
  
  RESTful APIs
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer" rel="noopener noreferrer"&gt;REST&lt;/a&gt; is a software architecture style commonly used to support APIs used on the web, and as mentioned earlier, synchronous APIs carry the day here. These are simple, uniform interfaces that are often used to support cloud applications and cloud services because they’re stateless, consistently available, and widely accessible. With these traits, a RESTful API can provide information on virtually any topic easily and reliably.&lt;/p&gt;

&lt;h4&gt;
  
  
  Internet of Things
&lt;/h4&gt;

&lt;p&gt;Internet of Things (IoT) devices need to handle inconsistent communications between the device and the API. For example, an IoT device may go out of internet range periodically, but will still need to send data to the API for processing. This means that data may be sent in bursts to the API when a connection is available. IoT devices may also need to notify the API when a significant event has occurred, as when a smoke alarm goes off or a camera detects motion. &lt;/p&gt;

&lt;p&gt;As a result of event processing, an IoT device may need to receive asynchronous notifications from the server. While the device itself holds raw data, servers collect and perform calculations of the data over time. The server may need to send notifications to the device when an event has occurred, like an IoT device losing power in your home.&lt;/p&gt;

&lt;h4&gt;
  
  
  Combining Synchronous and Asynchronous APIs
&lt;/h4&gt;

&lt;p&gt;Many SaaS API offerings exist to set up shopping carts for users and store inventory management for owners. These solutions tend to include a mixture of synchronous and asynchronous APIs. &lt;/p&gt;

&lt;p&gt;Inventory management applications, for example, use asynchronous API resources that allow users and owners to retrieve information about available inventory, user accounts, and pricing. Business owners can update their inventory, and it's automatically available to users when the API pushes data to the message broker. However, remember that synchronous APIs support most of the internet. An online retail shop may very well want the reliability of a RESTful API as part of its system to facilitate communication with a wide array of other organizations and developers.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Documenting in Any Case
&lt;/h2&gt;

&lt;p&gt;Regardless of which specification you choose to develop your API with, users need to be aware of new features and changes. Maintaining your API’s documentation and ensuring that it keeps to the standards of your spec can be a time-hungry task.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bump.sh/?utm_source=bump&amp;amp;utm_medium=blog&amp;amp;utm_campaign=blog-asyncapi-vs-openapi" rel="noopener noreferrer"&gt;Bump.sh&lt;/a&gt; transforms your OpenAPI and AsyncAPI documents into beautiful documentation. It lets your developers focus on building products rather than maintaining docs. Bump.sh provides automatic change detection by integrating with &lt;a href="https://docs.bump.sh/help/continuous-integration?utm_source=bump&amp;amp;utm_medium=blog&amp;amp;utm_campaign=blog-asyncapi-vs-openapi" rel="noopener noreferrer"&gt;CI tools&lt;/a&gt;, pushing notifications of the change to stakeholders, and enabling validation via its simple-to-use interface. &lt;a href="https://bump.sh/users/sign_up?utm_source=bump&amp;amp;utm_medium=blog&amp;amp;utm_campaign=blog-asyncapi-vs-openapi" rel="noopener noreferrer"&gt;Take its free trial for a spin&lt;/a&gt; to see how Bump.sh can make documenting any API - OpenAPI or AsyncAPI - simple. You can also try any AsyncAPI or OpenAPI file in the preview at the bottom of this page.&lt;/p&gt;

&lt;h2&gt;
  
  
  So… Which one to pick?
&lt;/h2&gt;

&lt;p&gt;To summarize, &lt;strong&gt;the API specification you should use depends entirely on what type of API you want to build&lt;/strong&gt;. Long story short, synchronous APIs use simple, direct endpoint communication to link a client to a server. When data consists of simple requests that can be completed by the server quickly, a synchronous, RESTful API that follows the OpenAPI specification is what you want.&lt;/p&gt;

&lt;p&gt;Asynchronous APIs use message brokers or pub-sub to communicate between server and application as data is made available. They’re useful for real-time applications that require frequent updates. They can be more complex to implement since they require more architecture than synchronous APIs, but you can stay organized thanks to the AsyncAPI specification.&lt;/p&gt;

&lt;p&gt;Both OpenAPI and AsyncAPI are open-source specifications and provide a standard method for designing and implementing APIs. A key asset of both specs is the ability to create comprehensive, industry-standard documentation for your API. By connecting your documents to &lt;a href="https://bump.sh/?utm_source=bump&amp;amp;utm_medium=blog&amp;amp;utm_campaign=blog-asyncapi-vs-openapi" rel="noopener noreferrer"&gt;Bump.sh&lt;/a&gt;, you can rest assured that your documentation is automatically updated for each API release.&lt;/p&gt;

&lt;p&gt;Author: Joanna Wallace&lt;/p&gt;

</description>
      <category>express</category>
      <category>openapi</category>
      <category>api</category>
      <category>restapi</category>
    </item>
    <item>
      <title>Perfectly sizing images in your API documentation</title>
      <dc:creator>Valériane Venance</dc:creator>
      <pubDate>Wed, 02 Aug 2023 14:59:13 +0000</pubDate>
      <link>https://dev.to/bump/perfectly-sizing-images-in-your-api-documentation-1kc0</link>
      <guid>https://dev.to/bump/perfectly-sizing-images-in-your-api-documentation-1kc0</guid>
      <description>&lt;p&gt;Images are cool and they should be everywhere in your API doc. End of this blog post, thanks everyone!&lt;/p&gt;

&lt;p&gt;Well, more seriously, many people, obviously including me, love a nice visual, especially when it comes to learning something new like, let’s say… how to use a new API. Bump.sh always supported the ability to add images in the markdown of your API documentation and has now extended it with the ability of sizing to your needs.&lt;/p&gt;

&lt;p&gt;Whether you want to have your API documentation more lively to your users with gifs, share your &lt;a href="https://bump.sh/blog/api-architecture-diagrams"&gt;API diagrams&lt;/a&gt;, illustrate complex API behaviors (like &lt;a href="https://bump.sh/blog/use-document-polymorphism-API"&gt;polymorphism&lt;/a&gt;) with a nice visual, and you have an API Contract based on &lt;a href="https://bump.sh/blog/what-is-openapi"&gt;OpenAPI&lt;/a&gt; or &lt;a href="https://bump.sh/blog/what-is-asyncapi"&gt;AsyncAPI&lt;/a&gt;, you can now make sure the images in your API documentation renders in the size you’d prefer them to.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Bump.sh renders images by default
&lt;/h2&gt;

&lt;p&gt;Usually, in markdown, you would use this syntax to add an image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Alt text&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;/path/to/image.jpg&lt;/span&gt; &lt;span class="nn"&gt;"Image title"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default Bump.sh lets the browser decide how it will display the generated html &lt;code&gt;&amp;lt;img src="image.url"&amp;gt;&lt;/code&gt;. For instance if the image is in a table cell, it will be limited to the size of the table cell, if in a paragraph, it will use the default image size.&lt;/p&gt;

&lt;p&gt;However, you can now decide on the image size yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to customize the image size in your API documentation
&lt;/h2&gt;

&lt;p&gt;Now you can take it a step even further into the personalisation with a &lt;code&gt;=dimension&lt;/code&gt; parameter that lets you manually decide how your image should be displayed in your documentation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;=dimension&lt;/code&gt; just extends the well known Markdown syntax by allowing you to give extra dimension information before the closing parenthesis&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Alt text&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;/path/to/image.jpg&lt;/span&gt; &lt;span class="nn"&gt;"Image title"&lt;/span&gt; =dimension)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As an example, if you wanted to display an image of 100 pixels height and 50 pixels width you could write&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Alt text&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;/path/to/image.jpg&lt;/span&gt; &lt;span class="nn"&gt;"Image title"&lt;/span&gt; =100pxx50px)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;=dimension&lt;/code&gt; uses the following syntax &lt;code&gt;=[width][unit]x[height][unit]&lt;/code&gt; and is itself completely optional as well as almost all its parameters: just &lt;code&gt;width&lt;/code&gt; &lt;em&gt;or&lt;/em&gt; &lt;code&gt;x&lt;/code&gt; + &lt;code&gt;height&lt;/code&gt; are mandatory. If you don't specify &lt;code&gt;width&lt;/code&gt; &lt;em&gt;or&lt;/em&gt; &lt;code&gt;height&lt;/code&gt;, the other value will be a ratio calculated from the original size of the image so it doesn't shrink.&lt;/p&gt;

&lt;p&gt;Telling this might be confusing so here are a few examples to better understand what you can do with this &lt;code&gt;=dimension&lt;/code&gt; parameter:&lt;/p&gt;

&lt;p&gt;Let’s take this SpongeBob plushie picture. See how it renders by default:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZOGEhs8I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/cu8U4wq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZOGEhs8I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/cu8U4wq.png" alt="SpongeBob plushie image in a Bump.sh documentation" width="800" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now let’s play around with the &lt;code&gt;=dimension&lt;/code&gt; parameter!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=100pxx50px   # with everything
=100x50     # without unit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fERG_g05--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/d6wu60d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fERG_g05--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/d6wu60d.png" alt="SpongeBob plushie image in a Bump.sh documentation with 150 x 50 px sizing" width="242" height="158"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=100        # without height (x separator not needed) and unit
=100px      # without height
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r6qGbK0W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/jExxH3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r6qGbK0W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/jExxH3b.png" alt="SpongeBob plushie image in a Bump.sh documentation with 100px sizing" width="254" height="288"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=x50        # without width and unit
=x50px      # without width
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9gyUyl0p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/BSJfnXr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9gyUyl0p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/BSJfnXr.png" alt="SpongeBob plushie image in a Bump.sh documentation with 100px sizing" width="108" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that not specifying an unit will fall back to pixel.&lt;/p&gt;

&lt;p&gt;It also supports all CSS length units, so you can work with &lt;code&gt;px&lt;/code&gt; for pixel, &lt;code&gt;%&lt;/code&gt;, or any other absolute or relative unit you are used to.&lt;/p&gt;

&lt;p&gt;Same image as above with &lt;code&gt;=dimension&lt;/code&gt;set to &lt;code&gt;=200cm&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WEmeePUD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/vcyBg4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WEmeePUD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/vcyBg4g.png" alt="SpongeBob plushie image in a Bump.sh documentation with 200cm sizing" width="498" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Always make sure how the property you use is handled by different browsers as it may differ.&lt;/p&gt;

&lt;p&gt;You can find an extended description of the behavior of this new image sizing feature &lt;a href="https://docs.bump.sh/help/specifications-support/markdown-support/#image-sizing"&gt;in the documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Trying with your own API documentation
&lt;/h2&gt;

&lt;p&gt;Bump.sh lets you preview how your documentation would look like.&lt;/p&gt;

&lt;p&gt;You can preview how your images will render while editing your API contract or in your tests using the &lt;a href="https://github.com/bump-sh/cli"&gt;Bump.sh CLI&lt;/a&gt; with the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; bump-cli   &lt;span class="c"&gt;## installs bump.sh cli&lt;/span&gt;

bump preview &lt;span class="nt"&gt;--live&lt;/span&gt; &lt;span class="nt"&gt;--open&lt;/span&gt; openapi-definition.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Option &lt;code&gt;--open&lt;/code&gt; will open the preview in your default browser, and &lt;code&gt;--live&lt;/code&gt; will automatically update the preview in your browser upon saving edits in the file.&lt;/p&gt;

&lt;p&gt;And do you know what’s best? You don’t even need a &lt;a href="https://bump.sh/users/sign_up?utm_source=bump&amp;amp;utm_medium=blog&amp;amp;utm_campaign=perfectly-sizing-images-blog"&gt;Bump.sh account&lt;/a&gt; to use our preview, so enjoy playing around with images to see how your API documentation could render with perfectly sized images 🖼️!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Images are cool and they should be everywhere in your API doc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xp34Wnp---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/P6bkeWG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xp34Wnp---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/P6bkeWG.png" alt="Images Everywhere meme" width="620" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Valériane Venance is Principal Developer Advocate at Bump.sh. She loves writing docs and articles. You can &lt;a href="https://twitter.com/intent/user?screen_name=Valeriane_IT"&gt;follow her&lt;/a&gt; on Twitter or &lt;a href="https://www.linkedin.com/in/vvenance/"&gt;connect&lt;/a&gt; on LinkedIn&lt;/em&gt;&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>asyncapi</category>
      <category>apidocumentation</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Creating an API with Express.js using OpenAPI</title>
      <dc:creator>Bump.sh</dc:creator>
      <pubDate>Mon, 24 Jul 2023 12:06:00 +0000</pubDate>
      <link>https://dev.to/bump/creating-an-api-with-expressjs-using-openapi-2749</link>
      <guid>https://dev.to/bump/creating-an-api-with-expressjs-using-openapi-2749</guid>
      <description>&lt;p&gt;&lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt; is a popular backend JavaScript framework for building landing pages and integrated content management systems or integrating APIs with other tools. With over &lt;a href="https://www.npmjs.com/package/express" rel="noopener noreferrer"&gt;twenty million weekly downloads on npm&lt;/a&gt; at the time of writing, the framework's popularity comes from its ease of setup and use, extensibility with first- and third-party middleware functions, and its flexible built-in router.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.openapis.org/" rel="noopener noreferrer"&gt;OpenAPI&lt;/a&gt; is a standard for describing HTTP APIs in a document that humans and computers alike can understand or consume. Building APIs according to the OpenAPI specification can ease friction between an API's developer and its consumers, especially in terms of how the API should operate. Some knowledge about the OpenAPI specification can definitely help you understand the examples provided.&lt;/p&gt;

&lt;p&gt;In this article, you'll learn how to build REST APIs using Express. You'll also learn how to document your APIs according to the OpenAPI specification with &lt;code&gt;express-openapi&lt;/code&gt;. Finally, you'll learn how to effectively manage your API documentation using &lt;a href="https://bump.sh/?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=express-openapi-blog" rel="noopener noreferrer"&gt;Bump.sh&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crash Course in Express
&lt;/h2&gt;

&lt;p&gt;The Express architecture is based around &lt;a href="https://expressjs.com/en/guide/using-middleware.html" rel="noopener noreferrer"&gt;middleware&lt;/a&gt;, which are functions that can access and modify the request and response object and either return a response or trigger subsequent middleware functions. Middleware can be registered by invoking the &lt;code&gt;.use()&lt;/code&gt; method on an Express application, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;middlewareFunction&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-middleware-function&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middlewareFunction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Express has three &lt;a href="https://expressjs.com/en/guide/using-middleware.html#middleware.built-in" rel="noopener noreferrer"&gt;built-in middleware functions&lt;/a&gt; for serving static files (&lt;code&gt;express.static&lt;/code&gt;, parsing JSON (&lt;code&gt;express.json&lt;/code&gt;) and URL-encoded request payloads (&lt;code&gt;express.urlencoded&lt;/code&gt;). Together with the Express router, these provide a good starting point for most applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Case for OpenAPI
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://bump.sh/blog/what-is-openapi?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=express-openapi-blog" rel="noopener noreferrer"&gt;OpenAPI specification&lt;/a&gt; is an opinionated, language-agnostic standard for describing HTTP APIs that allows humans and machines to understand and interact with an API without the need to access the source code. A valid OpenAPI description document is also called an &lt;a href="https://bump.sh/blog/api-contracts-extended-introduction?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=express-openapi-blog" rel="noopener noreferrer"&gt;API contract&lt;/a&gt; because, like a contract, it enforces a specific behavior that must be implemented by the developer and adhered to by the consumer.&lt;/p&gt;

&lt;p&gt;An API contract adds value in many ways, including easing the development burden, improving ease of adoption for first-time consumers, and using automated tools to reduce the amount of work needed to generate client code and documentation or validate I/O data.&lt;/p&gt;

&lt;p&gt;In the next few sections, we'll see API contracts in action as we build an Express application and generate documentation with Bump.sh.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing an API with OpenAPI and Express
&lt;/h2&gt;

&lt;p&gt;In this section, using Express, you'll build an API that follows the OpenAPI specification. You will be walked through steps to set up an Express application, configure it according to the OpenAPI spec, and see how to view your API documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;In order to follow along with this tutorial, you'll need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Familiarity with JavaScript (and Node.js)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A Node.js package manager — &lt;code&gt;npm&lt;/code&gt; was used in this article&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://bump.sh/users/sign_up/?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=express-openapi-blog" rel="noopener noreferrer"&gt;Bump.sh account&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the source code for the project in &lt;a href="https://github.com/bump-sh/express-oas-api-example/tree/main" rel="noopener noreferrer"&gt;this GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating an Express Application
&lt;/h3&gt;

&lt;p&gt;Let's start with creating an Express application. As mentioned, one of the reasons Express is so popular is that it's quick and easy to set up.&lt;/p&gt;

&lt;p&gt;First, create a new folder for your project. Spin up a terminal session and run the following command to create a folder named &lt;code&gt;express-oas&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;express-oas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, initialize a JavaScript project by adding a &lt;strong&gt;package.json&lt;/strong&gt; file. Using the same terminal session or via your computer's file manager, create a file named &lt;strong&gt;package.json&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;express-oas
&lt;span class="nb"&gt;touch &lt;/span&gt;package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the &lt;strong&gt;package.json&lt;/strong&gt; file using a text editor, then copy and paste the following in the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"express-oas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"express"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.18.2"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use &lt;code&gt;npm init&lt;/code&gt; or &lt;code&gt;yarn init&lt;/code&gt; to automatically generate a &lt;strong&gt;package.json&lt;/strong&gt; file. Both &lt;code&gt;npm init&lt;/code&gt; and &lt;code&gt;yarn init&lt;/code&gt; (on Yarn Classic) run interactively, meaning that you'll need to respond to a series of prompts before the file is generated. To skip these prompts and use the defaults, you can run the command with the &lt;code&gt;-y&lt;/code&gt; flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run interactively&lt;/span&gt;
npm init

&lt;span class="c"&gt;# Run non-interactively&lt;/span&gt;
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, install the &lt;code&gt;express&lt;/code&gt; package dependency from the npm or yarn registry and create your Express application.&lt;/p&gt;

&lt;p&gt;In your terminal, run the command to install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create a file named &lt;strong&gt;index.js&lt;/strong&gt; in your project's root folder. You can do that via the terminal by running the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open this file using your text editor, then import and initialize your Express application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running on &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default export from the &lt;code&gt;express&lt;/code&gt; package is a function that, when invoked, creates an &lt;code&gt;express&lt;/code&gt; application instance. This instance or object contains methods for routing HTTP requests, configuring middleware, and binding and listening for connections on a specified host and port.&lt;/p&gt;

&lt;p&gt;In the code block above, you configured an Express application and registered the &lt;code&gt;json()&lt;/code&gt; middleware, which parses incoming requests with JSON payloads and a matching &lt;code&gt;Content-Type&lt;/code&gt; header.&lt;/p&gt;

&lt;p&gt;If you try to access the application at this stage by running &lt;code&gt;node index.js&lt;/code&gt; and navigating to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; on a web browser, you'll be greeted by an error. There's no need to worry about this, however, as it just indicates that there are no routes or logic configured in your application yet. In the next section, we'll add some logic and set up the application's documentation with &lt;code&gt;express-openapi&lt;/code&gt;, an OpenAPI framework for Express.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrating OpenAPI with express-openapi
&lt;/h3&gt;

&lt;p&gt;For developing APIs, it helps to think of the API as a collection of resources, with each resource represented by a simple object that can be—from the moment of its creation—viewed, modified, or destroyed.&lt;/p&gt;

&lt;p&gt;For simplicity, you can use this &lt;a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete#RESTful_APIs" rel="noopener noreferrer"&gt;create, read, update, and delete (CRUD)&lt;/a&gt; pattern to help plan or design your API quickly. You can set up an OpenAPI-compliant API in a few steps using the &lt;code&gt;express-openapi&lt;/code&gt; package. For this one we will assume that our project has only one resource, called &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;express-openapi&lt;/code&gt; is an un-opinionated OpenAPI framework for Express, which supports OpenAPI versions 2.x and 3.0 at the time of writing. Configuration can be done in JavaScript or from a YAML string/file. In this project, you'll be using a JavaScript object.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;express-openapi&lt;/code&gt; allows you to keep the OpenAPI definition in sync with the code. Basically, you will provide an OpenAPI definition file with empty paths and they will be populated from your code. Doing this ensures the OpenAPI file will be exactly reflecting how the code behaves, updated as the code is. It also allows you if you go play around with the tool to validate your schemas, automatically provide &lt;code&gt;res.validateResponse&lt;/code&gt; tailored to a particular route, helps with your API security management, and so much more I can’t list them all now. The whole purpose of this framework is to stay as close as possible to express while leveraging the power of OpenAPI.&lt;/p&gt;

&lt;p&gt;To get started, run this command in your terminal to install the package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;express-openapi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the &lt;strong&gt;index.js&lt;/strong&gt; file in your editor and add the following import near the top of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import &lt;span class="o"&gt;{&lt;/span&gt; initialize &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'express-openapi'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;initialize&lt;/code&gt; import is a function that accepts a configuration object and sets up an OpenAPI-compliant contract that can be viewed or generated for your API. The required configuration parameters are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a reference to an Express application&lt;/li&gt;
&lt;li&gt;an &lt;code&gt;operations&lt;/code&gt; object containing exposed HTTP methods and handler functions&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;paths&lt;/code&gt; string that points to a directory where route files can be found&lt;/li&gt;
&lt;li&gt;an &lt;code&gt;apiDoc&lt;/code&gt; object describing the API's base definition, including schemas of objects used in your documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that either &lt;code&gt;operations&lt;/code&gt; or &lt;code&gt;paths&lt;/code&gt; will be required at any time. This means that if &lt;code&gt;operations&lt;/code&gt; is present, then &lt;code&gt;paths&lt;/code&gt; isn't required and vice versa.&lt;/p&gt;

&lt;p&gt;Now make the following changes to the &lt;strong&gt;index.js&lt;/strong&gt; file to see what this config looks like in action.&lt;/p&gt;

&lt;p&gt;As first argument, you need to pass a reference to your Express app, then optionally specify a path to the &lt;code&gt;docsPath&lt;/code&gt; keyword if you want the API contract file to be served by your server, in development mode this can be useful (as you will see later when using the Bump.sh CLI), however in production mode you might want to remove this and replace it with the &lt;code&gt;exposeApiDocs: false&lt;/code&gt; option. Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;docsPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api-definition&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;exposeApiDocs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NODE_ENV&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, configure the &lt;code&gt;apiDoc&lt;/code&gt; object by specifying the path of a file containing the base of your API definition. In this tutorial, you'll be using OpenAPI 3.1. Add the &lt;code&gt;apiDoc&lt;/code&gt; file path to the &lt;code&gt;initialize&lt;/code&gt; config object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// other objects here..&lt;/span&gt;
  &lt;span class="na"&gt;apiDoc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./doc/api-definition-base.yml&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And create the file &lt;code&gt;./doc/api-definition-base.yml&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.1.0"&lt;/span&gt;
&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;getting&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;started&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;API"&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0.0"&lt;/span&gt;
&lt;span class="na"&gt;servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/"&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
&lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schemas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object"&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string"&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;user's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;unique&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;identifier"&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string"&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;user's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;preferred&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string"&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Email&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;address"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the API definition &lt;strong&gt;paths&lt;/strong&gt; property is an empty object. This is because &lt;code&gt;express-openapi&lt;/code&gt; will generate its members based on the value of the &lt;code&gt;paths&lt;/code&gt; property given in the &lt;code&gt;initialize&lt;/code&gt; function dynamically, which you'll add next.&lt;/p&gt;

&lt;p&gt;To do this, we will import javascript files by adding the folder path or our API endpoints logic to the &lt;code&gt;initialize&lt;/code&gt; function call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="c1"&gt;// rest of code omitted for clarity&lt;/span&gt;
  &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./paths&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, you'll need to add a route with some operations to complete the &lt;code&gt;express-openapi&lt;/code&gt; initialization. The &lt;code&gt;express-openapi&lt;/code&gt; package uses filesystem-based routing. Let's look at the following routes we want to define:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /users
PUT /users/:id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They would need the following files to be created (assuming &lt;code&gt;./&lt;/code&gt; is the starting directory):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./paths/users.js
./paths/users/{id}.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While we'll be using more routes, these two files will be enough for what our project needs, so go ahead and create them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; paths/users
&lt;span class="nb"&gt;cd &lt;/span&gt;paths
&lt;span class="nb"&gt;touch &lt;/span&gt;users.js
&lt;span class="nb"&gt;cd users
touch&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll add some logic to our API application inside these files. Each file will contain a function as its default export, and this function will act as the corresponding path handler. For example, requests sent to &lt;code&gt;/users&lt;/code&gt; will be handled by the function exported in &lt;code&gt;./paths/users.js&lt;/code&gt;, and requests sent to &lt;code&gt;/users/{uniqueId}&lt;/code&gt; will be handled by the function exported in &lt;code&gt;./paths/users/{id}.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, open the &lt;strong&gt;users.js&lt;/strong&gt; file and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;operations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="nx"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;operations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add the following code to the &lt;strong&gt;users/{id}.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;operations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;PUT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;DELETE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PUT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;DELETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="nx"&gt;PUT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="nx"&gt;DELETE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;operations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's quickly break down what's happening in these files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a function as the default export, and this function returns an object representing valid operations (HTTP methods) for the route.&lt;/li&gt;
&lt;li&gt;As mentioned earlier, the file names correspond to the route that will be matched when your API is queried.&lt;/li&gt;
&lt;li&gt;For each operation defined in the &lt;code&gt;operations&lt;/code&gt; object, you need a corresponding handler function, and the function name must match the HTTP verb (PUT, GET, etc).&lt;/li&gt;
&lt;li&gt;Finally, the documentation for each handler function can be described by adding an &lt;code&gt;apiDoc&lt;/code&gt; property to the handler functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's missing now are: your API documentation and the actual API logic. We'll add those in the next few steps.&lt;/p&gt;

&lt;p&gt;First let's add your API endpoints documentation. We will update the &lt;code&gt;apiDoc&lt;/code&gt; property for the GET and POST handler functions in the &lt;strong&gt;users.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./paths/users.js&lt;/span&gt;
&lt;span class="c1"&gt;// rest of code hidden for clarity&lt;/span&gt;

&lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Returns list of users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getUsers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;List of users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#/components/schemas/User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Creates a new user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createUser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;requestBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#/components/schemas/User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Newly created user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#/components/schemas/User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// rest of code hidden for clarity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll also add the documentation for the GET, PUT, and DELETE handler functions in the &lt;strong&gt;users/{id}.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./paths/users/{id}.js&lt;/span&gt;
&lt;span class="c1"&gt;// rest of code hidden for clarity&lt;/span&gt;

&lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Returns a single user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getOneUser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#/components/schemas/User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;PUT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Updates an existing user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;updateUser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;requestBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#/components/schemas/User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Updated user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;$ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#/components/schemas/User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;DELETE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Deletes an existing user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;operationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deleteUser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="mi"&gt;204&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;apiDoc&lt;/code&gt; property of a function handler defines the OpenAPI documentation for that endpoint while the summary and operationId fields provide a brief description and a unique identifier, respectively. &lt;a href="https://expressjs.com/en/guide/routing.html#route-parameters" rel="noopener noreferrer"&gt;Route parameters&lt;/a&gt; and the required format for the request body data can be configured with the &lt;code&gt;parameters&lt;/code&gt; and &lt;code&gt;requestBody&lt;/code&gt; fields, respectively. Finally, the &lt;code&gt;responses&lt;/code&gt; field provides information about the possible responses—and their status codes—for an endpoint.&lt;/p&gt;

&lt;p&gt;Next, update the function handlers to include CRUD logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./paths/users.js&lt;/span&gt;

&lt;span class="c1"&gt;// rest of code hidden for clarity&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The GET and POST function handlers here respond to GET and POST requests made to &lt;code&gt;/users&lt;/code&gt;, respectively. The GET function retrieves all user data from a database, the &lt;code&gt;mockDatabaseInstance&lt;/code&gt;—which we'll get to later—and returns it in JSON format with a status code of 200. The POST function adds a new user to the database from data provided via the request's body and returns the updated user list with a status code of 201.&lt;/p&gt;

&lt;p&gt;We'll also need to update the function handlers in the &lt;strong&gt;/users/{id}.js&lt;/strong&gt; file. Open the file and update the GET, PUT, and DELETE functions to include the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./paths/users/{id}.js&lt;/span&gt;
&lt;span class="c1"&gt;// rest of code hidden for clarity&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PUT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;DELETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;204&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned earlier, requests made to &lt;code&gt;/users/someUniqueId&lt;/code&gt; will be routed to this file and handled according to their HTTP verbs. The GET function here retrieves a single user from the database, matching the ID provided in the request's path. The PUT function updates a single user, also matching the provided ID, and returns the updated user as JSON with a status code of 200. The DELETE function removes a user from the database using the ID provided in the request. No data is returned from the DELETE function, so the status code is 204.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mockDatabaseInstance&lt;/code&gt; object referenced in the function handlers code is a simple object with methods for updating and reading from an in-memory data store (an array of objects). We can add this to our project by creating a file named &lt;strong&gt;database.js&lt;/strong&gt; in the project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;database.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And adding the following code to the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mockDatabase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// user already exists, let's throw an error&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User already exists.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;dataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// user does not exist, let's throw an error&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`No user with ID &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was found`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;dataStore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;dataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updatedUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;updatedUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// user does not exist, let's throw an error&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`No user with ID &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was found`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;dataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;dataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataStore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;userExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// user does not exist, let's throw an error&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`No user with ID &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was found`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;addUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;getOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mockDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above defines a function named &lt;code&gt;mockDatabase&lt;/code&gt; that returns an object with multiple functions to perform CRUD operations on an in-memory data store, the &lt;code&gt;dataStore&lt;/code&gt; array. The functions &lt;code&gt;addUser&lt;/code&gt;, &lt;code&gt;updateUser&lt;/code&gt;, and &lt;code&gt;deleteUser&lt;/code&gt; respectively perform operations to add, update, or delete users from the data store. The &lt;code&gt;getOne&lt;/code&gt; and &lt;code&gt;getAll&lt;/code&gt; functions retrieve one or multiple users from the data store, while &lt;code&gt;userExists&lt;/code&gt; is a utility function for checking if a user with a matching ID exists in the data store.&lt;/p&gt;

&lt;p&gt;We instantiate and store the &lt;code&gt;mockDatabase&lt;/code&gt; in the &lt;code&gt;mockDatabaseInstance&lt;/code&gt; variable, and we export and use this in our function handlers. Let's update the rest of our code to include the &lt;code&gt;mockDatabaseInstance&lt;/code&gt; import.&lt;/p&gt;

&lt;p&gt;Open the files in your &lt;code&gt;paths&lt;/code&gt; directory, and add the following line at the top of each file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../database.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that for the &lt;strong&gt;paths/users/{id}.js&lt;/strong&gt; file, you need to add two dots and a slash (../) as it's nested one level deep:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mockDatabaseInstance&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../database.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, your API and its contract have been set up. When you test your application in the next section, you'll see that errors will be thrown for invalid requests or payloads that don't conform to the documentation you've described. This is where the &lt;code&gt;express-openapi&lt;/code&gt; library shines as you didn't need to define any validation code but the provided documentation schemas and constraints will do all the job for you.&lt;/p&gt;

&lt;p&gt;While you've learned to create an Express application with &lt;code&gt;express-openapi&lt;/code&gt; in this section, it's been light on information about the OpenAPI specification and the &lt;code&gt;express-openapi&lt;/code&gt; package. You can start with the &lt;a href="https://learn.openapis.org/" rel="noopener noreferrer"&gt;OpenAPI guide&lt;/a&gt; if you'd like to learn more about the OpenAPI specification and the &lt;a href="https://github.com/kogosoftwarellc/open-api/tree/master/packages/express-openapi" rel="noopener noreferrer"&gt;express-openapi documentation&lt;/a&gt; for more information on how to use the package.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running and Testing the Application
&lt;/h3&gt;

&lt;p&gt;It's time to run and test the application. Simply run &lt;code&gt;node index.js&lt;/code&gt; and navigate to &lt;a href="http://localhost:3000/api-definition" rel="noopener noreferrer"&gt;http://localhost:3000/api-definition&lt;/a&gt; in a browser to see your API definition.&lt;/p&gt;

&lt;p&gt;You can also test the API by visiting &lt;a href="http://localhost:3000/users" rel="noopener noreferrer"&gt;http://localhost:3000/users&lt;/a&gt; to list the users in your database.&lt;/p&gt;

&lt;p&gt;In a production environment, you will probably want to deploy the updated API definition each time you make a change in your code without having to expose the API definition on your express server.&lt;/p&gt;

&lt;p&gt;To do so, copy the following script into a new file named &lt;code&gt;contract.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAPIFramework&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openapi-framework&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Use OpenAPIFramework similarly than in the express-openapi library&lt;/span&gt;
&lt;span class="c1"&gt;// to generate the OpenAPI definition file of our API&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;framework&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;OpenAPIFramework&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;featureType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-openapi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;apiDoc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./doc/api-definition-base.yml&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./paths&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

&lt;span class="c1"&gt;// Output OpenAPI definition&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiDoc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple script which uses the &lt;code&gt;express-openapi&lt;/code&gt; package to generate the API definition file without the need to run an Express server.&lt;/p&gt;

&lt;p&gt;So if you run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node contract.js &amp;gt; doc/api-definition.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be able to snapshot the current OpenAPI definition file inside the &lt;code&gt;doc/api-definition.json&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Bump.sh for Documenting Your Express APIs
&lt;/h2&gt;

&lt;p&gt;Using OpenAPI (and the &lt;code&gt;express-openapi&lt;/code&gt; package) enables you to use API contracts that make collaboration easy among developers when building and integrating with APIs. However, manually generating and maintaining these contracts can be tough, as you just saw. Bump.sh can improve this collaboration by helping documenting your API based on the contract.&lt;/p&gt;

&lt;p&gt;As an API documentation management solution, &lt;a href="https://bump.sh/?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=express-openapi-blog" rel="noopener noreferrer"&gt;Bump.sh&lt;/a&gt; helps publish API contracts into developer portals, track changes, and alert teams when breaking changes are introduced. It essentially eases the workload of manually updating your API's documentation, communicating changes made to your API's consumers, and keeping track of all your product documentation.&lt;/p&gt;

&lt;p&gt;Bump.sh provides a &lt;a href="https://github.com/bump-sh/cli" rel="noopener noreferrer"&gt;command line interface (CLI) tool&lt;/a&gt; that lets you easily preview your API documentation while it's in development (with support for live reloading), deploy versions of your documentation automatically from your CI build step, compare changes made between versions of your API, as well as notify consumers of changes made to your APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Bump.sh for Express Applications
&lt;/h3&gt;

&lt;p&gt;To configure Bump.sh for your Express app, you need to add the Bump.sh CLI to your existing Express project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;bump-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned, &lt;code&gt;bump-cli&lt;/code&gt; can be used to preview, compare versions, or deploy new versions of your API documentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bump.sh/users/sign_up?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=express-openapi-blog" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; or &lt;a href="https://bump.sh/users/sign_in?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=express-openapi-blog" rel="noopener noreferrer"&gt;login&lt;/a&gt; in your Bump.sh  account. You can begin by navigating to your dashboard and clicking &lt;strong&gt;Create Documentation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvdwh5seq2d0dtpvi4ma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvdwh5seq2d0dtpvi4ma.png" alt="Bump.sh account dashboard" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, add your documentation's name and, optionally, specify its access level (public or private).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8onitchsjsxmi7soci6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8onitchsjsxmi7soci6.png" alt="Create new documentation wizard" width="800" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you'll be asked to upload a specification file. Choose the &lt;strong&gt;Use Bump.sh CLI&lt;/strong&gt; option, which will immediately take you to the newly created documentation's deployment configuration page. Here, you'll find the token that's required to deploy your documentation using the CLI. It's the string labeled &lt;strong&gt;Access token&lt;/strong&gt;, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kkf3w0jnuyxph7ku0ra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kkf3w0jnuyxph7ku0ra.png" alt="Bump.sh deployment configuration" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy this token and replace &lt;code&gt;YOUR_TOKEN&lt;/code&gt; with it when running the command to deploy your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx bump deploy http://localhost:3000/api-definition &lt;span class="nt"&gt;--doc&lt;/span&gt; YOUR_DOCUMENTATION_SLUG &lt;span class="nt"&gt;--token&lt;/span&gt; YOUR_TOKEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the command above will trigger a deployment that you can view by clicking &lt;strong&gt;View Documentation&lt;/strong&gt; from your documentation's General Settings page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj4jn3ohyhq5w50eglnf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj4jn3ohyhq5w50eglnf.png" alt="Documentation general settings" width="800" height="46"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your deployed documentation should open in a new tab, and it should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3em8ky42o0c8xizorhn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3em8ky42o0c8xizorhn.png" alt="Bump.sh deployed documentation" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Automate API documentation update with Bump.sh
&lt;/h3&gt;

&lt;p&gt;In order to automatically deploy a new version of your documentation every time you push code changes to a branch, we will add the &lt;a href="https://docs.bump.sh/help/continuous-integration/github-actions/?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=express-openapi-blog" rel="noopener noreferrer"&gt;Bump.sh Github Action&lt;/a&gt; to your repository.&lt;/p&gt;

&lt;p&gt;To deploy a new version on each push, create a file named &lt;code&gt;bump-deploy.yml&lt;/code&gt; in the &lt;code&gt;.github/workflows&lt;/code&gt; folder of your project, then paste the following code into the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy documentation&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy-doc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy API doc on Bump.sh&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install NodeJS&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install node dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate OpenAPI contract&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node contract.js &amp;gt; doc/api-definition.json&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy API documentation&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bump-sh/github-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;doc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;BUMP_DOC_ID&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{secrets.BUMP_TOKEN}}&lt;/span&gt;
          &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;doc/api-definition.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow runs every time &lt;code&gt;git push&lt;/code&gt; is run on the &lt;code&gt;main&lt;/code&gt; branch. It will generate the API definition thanks to the &lt;code&gt;contract.js&lt;/code&gt; script, then deploy the API definition file to Bump.sh thanks to the Bump.sh Github Action.&lt;/p&gt;

&lt;p&gt;Just make sure you provide your Bump.sh documentation slug (replace the &lt;code&gt;&amp;lt;BUMP_DOC_ID&amp;gt;&lt;/code&gt; value) and an &lt;a href="https://docs.github.com/en/actions/security-guides/encrypted-secrets" rel="noopener noreferrer"&gt;encrypted secret&lt;/a&gt; containing the Bump.sh access token used earlier in a &lt;code&gt;BUMP_TOKEN&lt;/code&gt; secret variable on your repository.&lt;/p&gt;

&lt;p&gt;The resulting action should run on each push to the &lt;code&gt;main&lt;/code&gt; branch:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzdytajfrhwwjmc28qrea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzdytajfrhwwjmc28qrea.png" alt="Github Action Deploy Summary" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your API consumers can then subscribe to changes made to your API by clicking on &lt;strong&gt;API Changelog&lt;/strong&gt; from your API documentation page. Either by completing the form or adding the RSS feed link to apps that can display RSS feeds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9rfal8gjorcdfjluigg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9rfal8gjorcdfjluigg.png" alt="Subscribe to API changelog" width="800" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By following this tutorial, you created an Express application and documented the API according to the OpenAPI specification with the &lt;code&gt;express-openapi&lt;/code&gt; npm package. You also learnt how to deploy a live version of your API documentation using Bump.sh.&lt;/p&gt;

&lt;p&gt;Documenting your APIs correctly is key to your API quality, usability, maintainability and helps your API consumers quickly get up to speed with using your product, reducing the number of support tickets and issues related to consuming your API.&lt;/p&gt;

&lt;p&gt;Bump.sh helps with documenting your APIs but goes one step further by giving you tools like &lt;a href="https://bump.sh/api-change-management/?utm_source=devto&amp;amp;utm_medium=post&amp;amp;utm_campaign=express-openapi-blog" rel="noopener noreferrer"&gt;an automatic API changelog&lt;/a&gt; with notifications and diffs and a hub to manage all your API documentation in one place.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Author: &lt;a href="https://portal.draft.dev/writers/rec98fcDmrzNUcuZz" rel="noopener noreferrer"&gt;Jerry Ejonavi&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>express</category>
      <category>openapi</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Bump.sh included in the GitHub Student Developer Pack</title>
      <dc:creator>Christophe Dujarric</dc:creator>
      <pubDate>Wed, 19 Jul 2023 09:24:51 +0000</pubDate>
      <link>https://dev.to/bump/bumpsh-included-in-the-github-student-developer-pack-akg</link>
      <guid>https://dev.to/bump/bumpsh-included-in-the-github-student-developer-pack-akg</guid>
      <description>&lt;p&gt;GitHub Education just announced that Bump.sh is included &lt;a href="https://education.github.com/experiences/mobile_app_development"&gt;in their latest Mobile Development Experience&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That brings back some memories...&lt;/p&gt;

&lt;h2&gt;
  
  
  Our roots in Mobile Development
&lt;/h2&gt;

&lt;p&gt;Five years ago, in a previous venture, we introduced a major issue in a mobile app. It brought the service down for all its users. The root cause? A breaking change in our API that we didn’t identify when releasing to production. That change was part of a much wider product evolution, including database migrations, making it virtually impossible to roll back and bring the service back up fast.&lt;/p&gt;

&lt;p&gt;This story probably rings a bell to many. &lt;/p&gt;

&lt;p&gt;And that’s precisely the origin of Bump.sh. We realized the lack of actionable API documentation tools, that would assist in identifying changes, and let developers discover, build and consume APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Helping students not reproduce our issues
&lt;/h2&gt;

&lt;p&gt;Today, we’re thrilled to open free access to &lt;a href="https://bump.sh/students?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=github_student"&gt;Bump.sh&lt;/a&gt; for all GitHub Students.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://education.github.com/pack"&gt;GitHub Student Developer Pack&lt;/a&gt; lets students worldwide access a wide variety of professional-grade tools that otherwise wouldn’t be affordable. While learning, they can directly benefit from what will be their day-to-day workspace once they start their career. They can complete student projects through a great developer experience. They can apply everything they learn about, hands-on.&lt;/p&gt;

&lt;p&gt;A keystone of API development, whether for Mobile or web apps, is in the specifications such as OpenAPI (ex-Swagger) or AsyncAPI. They make it possible to define &lt;a href="https://bump.sh/blog/api-contracts-extended-introduction?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=github_student"&gt;a robust contract&lt;/a&gt; that tells how to work with an API. We’re fervent advocates of specifications and encourage student developers to discover and learn how to use them early on.&lt;/p&gt;

&lt;p&gt;By offering &lt;a href="http://bump.sh?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=github_student"&gt;Bump.sh&lt;/a&gt; to students, we’re hoping it will assist them in those efforts. Bump.sh indeed generates stunning docs directly from OpenAPI and AsyncAPI contracts. It detects any change in those contracts and can warn a team whenever a breaking change occurs. More: through our &lt;a href="https://github.com/marketplace/actions/bump-sh"&gt;GitHub Action&lt;/a&gt;, get API docs automatically updated, and decide whether breaking changes should turn your commit status to red.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bump.sh/students?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=github_student"&gt;Read more&lt;/a&gt; about what’s included in our offer.&lt;/p&gt;

&lt;p&gt;Students, we’ll love to see what you’ll build. We’ll be there if you need any assistance on the road!&lt;/p&gt;

</description>
      <category>github</category>
      <category>api</category>
      <category>mobile</category>
      <category>documentation</category>
    </item>
    <item>
      <title>How Bump.sh works with… remote work?</title>
      <dc:creator>Jay Cormier</dc:creator>
      <pubDate>Mon, 17 Jul 2023 13:13:24 +0000</pubDate>
      <link>https://dev.to/bump/how-bumpsh-works-with-remote-work-4nhb</link>
      <guid>https://dev.to/bump/how-bumpsh-works-with-remote-work-4nhb</guid>
      <description>&lt;p&gt;Ever since a certain pandemic, remote work has become increasingly popular. It was enforced by lockdowns, adopted long-term by some teams, and criticized for allegedly hampering productivity. Lately, some companies have been reversing their approval of remote work. On the other hand, entire teams are advocating for it to become the norm.&lt;/p&gt;

&lt;p&gt;Our version of remote work has its own unique story. Legend has it that our two founders, Anthony and Sébastien, climbed to the top of the tallest building in France and held iPads to the sky to be etched by lightning with the founding principles of what would become &lt;a href="http://bump.sh/"&gt;Bump.sh&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Predictably, that wasn't covered by the warranty.&lt;/p&gt;

&lt;h2&gt;
  
  
  The usual suspects
&lt;/h2&gt;

&lt;p&gt;Our journey with remote work is a long story that began well before the pandemic. We have always had some portion of work-at-home (or elsewhere) in our previous professional experiences.&lt;br&gt;
Occasionally, for awaiting for a plumber or a delivery (that you missed. with no notice. and the delivery person rang but looks like you weren't at home. too bad.).&lt;br&gt;
Sometimes, a few days were spent working in peace, without the hustle and bustle of an open-space office.&lt;br&gt;
Or every week, because you lived far from the office and only drop by occasionally.&lt;/p&gt;

&lt;p&gt;Each in our own way, we gradually came to the conclusion that remote work is a natural way of working for us. It's aligned with how we view our work-life balance and our relationship with our team.&lt;/p&gt;

&lt;p&gt;You are probably familiar with the reasons.&lt;/p&gt;

&lt;p&gt;The ability to work from anywhere. Whether it's in the capital or in the remote countryside of Loire-Atlantique, an apartment or a cabin, or even if you want a change of scenery and decide to work astride a wild horse in Camargue.&lt;/p&gt;

&lt;p&gt;The gained autonomy has an undeniable impact on our daily life and overall well-being. The freedom of remote work means we can take our dog for a morning walk, see our kids off to school, or make a homemade lunch.&lt;/p&gt;

&lt;p&gt;Some of us take some time to go to the gym. Others would paint, play an instrument or fight a deadly threat hidden among the stars. Whatever. It's about having control over our day. We can seamlessly blend work and life without compromising on either.&lt;/p&gt;

&lt;p&gt;Not being geographically confined also allows us to &lt;a href="https://bump.sh/careers"&gt;recruit talent&lt;/a&gt;, wherever they may be (including in Camargue). By removing the constraint of a physical location and mandatory presence, we avoid the risk of missing out on individuals who have chosen to live where they feel their best.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our magic recipe
&lt;/h2&gt;

&lt;p&gt;Upon your arrival at &lt;a href="http://bump.sh/"&gt;Bump.sh&lt;/a&gt;, you will be faced with a crucial choice. Seated behind a desk, dressed in a black leather coat, one of our co-founders will present you with a crucial decision. In their right hand, the option to work remotely from the comfort of your home. In their left hand, the opportunity to work in a coworking space, as you may crave social interactions and the company of others.&lt;/p&gt;

&lt;p&gt;Once you have made your decision amidst breathless anticipation, they will explain that you can also mix it up occasionally. Nothing is set in stone.&lt;br&gt;
The idea is to create the best working environment for us. It could be a dedicated room at home (some even have verandas for that purpose). Sometimes, the need arises to experience the adventures and dramatic twists of a coworking space once or twice a week (it's better than a telenovela).&lt;/p&gt;

&lt;p&gt;To facilitate daily communication, we have implemented meetings with one significant constraint: almost no one likes meetings. We are constantly seeking the best formula for this format, but we have arrived at a result that is starting to please us.&lt;/p&gt;

&lt;p&gt;There are two main teams at Bump.sh (Product, which includes our engineers, and GoToMarket) that have a weekly meeting to discuss current topics. Then, there is an All-hands meeting where a representative from each team presents a summary, providing everyone with an overview of where things stand and how everyone is progressing.&lt;/p&gt;

&lt;p&gt;Of course, we needed effective means to compensate for the absence of the sacred Coffee Machine for informal discussions. To address this, we have a daily reminder and a voice chat lounge where we can exchange stories and share our current moods and experiences.&lt;/p&gt;

&lt;p&gt;This is where the importance of using the right tools to stay up-to-date comes into sharp focus. You're familiar with the classics: a shared calendar, a few emails, a well-known professional chat tool that we won't mention just to add a few lines to this article without shame or remorse.&lt;/p&gt;

&lt;p&gt;How do you indicate that you're open to a coffee chat with the rest of the team? A slot on a shared calendar? A specific status on that infamous tool-whose-name-we-won't-speak? An emoji? A dedicated channel?&lt;/p&gt;

&lt;p&gt;Like many of you, we use Slack as our primary communication tool. We also tried Gather.town, but unfortunately, it didn't resonate with everyone. For a long time, our meetings took place on &lt;a href="http://meet.coop/"&gt;meet.coop&lt;/a&gt;, an open-source video conferencing solution. However, &lt;a href="https://forum.meet.coop/t/changes-coming-to-meet-coop-please-read/1287"&gt;their announcement&lt;/a&gt; of discontinuing the service in the coming months pushed us towards new horizons (which we are still exploring).&lt;/p&gt;

&lt;p&gt;Collaboration at &lt;a href="http://bump.sh/"&gt;Bump.sh&lt;/a&gt; revolves around well-known figures in the industry. Our internal knowledge base, project management, meeting notes, and article drafts find their place on Notion. The hottest designs in your area can be found on Figma. And our Engineering team works continuously (*wink*) with GitHub.&lt;br&gt;
In fact, discussing our tools alone would warrant an article, but we wanted to give you a glimpse.&lt;/p&gt;

&lt;p&gt;Of course, working remotely doesn't mean we live as reclusive hermits, in our cabins deep in the woods, munching on raw roots.&lt;/p&gt;

&lt;p&gt;All it takes is to look up to see the signs: a planetary alignment, a constellation that shines a little brighter than the others, or even a meteor shower. These are the heralds of our famous and popular In Real Life (IRL) meetups.&lt;/p&gt;

&lt;p&gt;Travelling across the country, we gather in secret locations to celebrate APIs and our joy of working together. These are days of jubilation where we work studiously and feast like never before, returning to our huts and leaving behind the most mysterious secrets about these gatherings.&lt;/p&gt;

&lt;p&gt;To be more precise, every 3 months, we organize an IRL (In Real Life) gathering to make up for missed after-work events and lost time. We select a location that accommodates everyone, with each event held in a different place from the previous one. We set a date, rent a nice space where we can both work and have fun. Around that, we plan various activities, evenings, board games, a few bottles... and the rest becomes part of the story.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxx4u1iv1w63iv8x2mn15.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxx4u1iv1w63iv8x2mn15.jpg" alt="Don't mind the scoreboard" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  It can be that smooth, right?
&lt;/h2&gt;

&lt;p&gt;But here's the thing, remote work sometimes feels a lot like real office work, the kind with the accounting department giving you side-eye at the coffee machine ever since they noticed that strange overconsumption of post-its in your department. Don't deny it, the numbers never lie, they know.&lt;/p&gt;

&lt;p&gt;There will always be those moments of frustration when communication is challenging. Or a written message causes teeth to grind due to its borderline tone. Or you think that this issue could have been solved in two minutes if you could have just gotten up and showed your diagrams at the neighboring desk.&lt;/p&gt;

&lt;p&gt;We also might miss inviting a colleague for a drink after work. Or having a chair race in the open-space office (don't do this, it's highly risky and generates a lot of paperwork for HR, we won't back you up).&lt;/p&gt;

&lt;p&gt;But just as office work has its own challenges to overcome, we find ours much more comfortable to face. While working from home demands compartmentalization, discipline, trust (in oneself and in others), we still find ourselves in a healthy, comfortable, and caring environment.&lt;/p&gt;

&lt;p&gt;One could commute, wait for the elevator, settle at their desk, and keep an eye on the clock to await that perfect timing when taking a break won't offend anyone. Or one could work from home, on their sofa under a blanket with a good cup of coffee/tea within reach.&lt;/p&gt;

&lt;p&gt;But in the end, we all face the same situation: working together primarily means communicating with the tools we have. No one ever said it would be easy. But nothing stops you from making it more comfortable, inclusive, and warm for others and yourself.&lt;/p&gt;

&lt;p&gt;That's what we strive for at &lt;a href="http://bump.sh/"&gt;Bump.sh&lt;/a&gt;. And we have no intention of giving up.&lt;/p&gt;

</description>
      <category>remote</category>
      <category>workplace</category>
      <category>team</category>
    </item>
    <item>
      <title>A Developer's Guide to API-First Design</title>
      <dc:creator>Bump.sh</dc:creator>
      <pubDate>Wed, 14 Jun 2023 12:30:00 +0000</pubDate>
      <link>https://dev.to/bump/a-developers-guide-to-api-first-design-41f8</link>
      <guid>https://dev.to/bump/a-developers-guide-to-api-first-design-41f8</guid>
      <description>&lt;p&gt;API-first design is a software development approach built around the idea that the application programming interfaces (APIs) should be the primary focus of the development process, with other system components, such as the user interface (UI) being developed later.&lt;/p&gt;

&lt;p&gt;API-first design is becoming increasingly important as more and more organizations are turning to microservices and other architectural patterns to improve their ability to scale, innovate, and adapt to changing business needs. This approach enables the development of flexible and modular systems that can be easily integrated with diverse systems and services.&lt;/p&gt;

&lt;p&gt;In this article, you'll learn about the principles of API-first design and how it can benefit your organization. You'll understand how API-first design works and learn about the different stages of the API design process. By the end of this article, you'll have a comprehensive understanding of the benefits of API-first design, and how &lt;a href="https://bump.sh/?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-first-design" rel="noopener noreferrer"&gt;Bump.sh&lt;/a&gt; can serve as the single source of truth for all your APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Is API-first Design Important?
&lt;/h2&gt;

&lt;p&gt;As mentioned, API-first design is a specific methodology for building software systems, where the API is designed and developed before any other system components. APIs are emphasized as a core part of the software development process rather than as an afterthought. In short, the API is considered the backbone of the software, and the rest of the system is built around it.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1592921944818491394-869" src="https://platform.twitter.com/embed/Tweet.html?id=1592921944818491394"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1592921944818491394-869');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1592921944818491394&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;API-first design is commonly applied in API-centric products. For example, companies like Stripe or Twilio offer their APIs as a core offering to customers, so they have to design them to be intuitive and user-friendly.&lt;/p&gt;

&lt;p&gt;Companies using or moving to a microservice architecture will also often adopt an API-first design approach. Because APIs are so important in microservices, developing standards and a well-thought-out workflow through API-first design is very important.&lt;/p&gt;

&lt;p&gt;When done well, API-first design offers a number of benefits:&lt;/p&gt;
&lt;h3&gt;
  
  
  Faster Development Times
&lt;/h3&gt;

&lt;p&gt;By designing the API first, development teams can more easily work in parallel on different parts of an application. Having a well-documented API means that teams can stub out specific endpoints to test and build their own systems without having to have a running instance of every API on their machine.&lt;/p&gt;

&lt;p&gt;Similarly, this improves coordination between frontend and backend teams. Frontend developers can build based on the assumption that the backend will adhere to the established documentation, allowing backend developers to work in parallel with them.&lt;/p&gt;

&lt;p&gt;Finally, API-first design makes it easier to reuse endpoints and logic throughout the system. For example, if you’re building an e-commerce application, several parts of the application may need to estimate shipping costs (e.g., pricing page, checkout workflow, returns workflow, invoice generation, etc.). If there’s a single, documented endpoint available, you can ensure that each time it is called, the results will be the same.&lt;/p&gt;
&lt;h3&gt;
  
  
  Improved Developer Experience
&lt;/h3&gt;

&lt;p&gt;It’s often easy to tell when a system wasn’t built with the API in mind because it uses clunky or non-standard endpoints. For example, I recently ran across an API that used the following endpoint to edit a user object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST http://api.example.com/v1/user/edit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this approach technically works, it’s not common. Typically, in a REST API, modification of an object &lt;a href="https://restfulapi.net/rest-put-vs-post/" rel="noopener noreferrer"&gt;would use a &lt;code&gt;PUT&lt;/code&gt; or &lt;code&gt;PATCH&lt;/code&gt; request and include the object’s ID in the URL&lt;/a&gt;. So, consumers of this API must now very carefully read through all the documentation to be sure they use your API properly.&lt;/p&gt;

&lt;p&gt;Whether API consumers are internal or external, systems designed with the API in mind first will almost always provide a better experience to developers. They’re more likely to use established standards which make them much easier and less frustrating to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Collaboration and Communication
&lt;/h3&gt;

&lt;p&gt;Ultimately, all the advantages of API-first design come down to making communication and collaboration better.&lt;/p&gt;

&lt;p&gt;When your API is clearly defined and agreed upon up-front, multiple teams can work in parallel, engineers can move from working with one API to another seamlessly, and errors in the implementation or consumption of APIs are more clear.&lt;/p&gt;

&lt;h3&gt;
  
  
  When is API-First the Wrong Approach?
&lt;/h3&gt;

&lt;p&gt;Just because there are advantages to API-first design doesn’t mean it’s a panacea. For example, if you’re building a traditional server-rendered application without plans to offer an API, adding extra layers is a waste of time. API-first design can also hamper nascent projects that aren’t sure exactly how the data model will look when they’re finished.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://solidstudio.io/blog/origin-of-overengineering" rel="noopener noreferrer"&gt;Overengineering is a common problem in software development&lt;/a&gt;, and API-first design approaches are no different.&lt;/p&gt;

&lt;h2&gt;
  
  
  The API-First Design and Development Process
&lt;/h2&gt;

&lt;p&gt;Now that you've seen some of the advantages an API-first process provides, let's get into the practical aspects—what does API-first design look like?&lt;/p&gt;

&lt;p&gt;As the name implies, API-first design dictates that you plan your API as part of the application development process, but like all software, your API needs to be open to change as the system around it changes.&lt;/p&gt;

&lt;p&gt;Typically, a new API will undergo the following stages:&lt;/p&gt;

&lt;h3&gt;
  
  
  Define
&lt;/h3&gt;

&lt;p&gt;This is the initial stage of the API lifecycle, where you’ll define and establish the API's overall goals, requirements, and constraints. This stage is critical for setting the scope of the project and ensuring that the final API will meet the needs of its intended users and stakeholders.&lt;/p&gt;

&lt;p&gt;At this point, you should consider the technical and service-level requirements, the data format users will prefer (JSON, XML, etc.), the &lt;a href="https://medium.com/back-to-the-napkin/the-next-step-to-build-better-apis-consistent-data-structure-38667444f37e" rel="noopener noreferrer"&gt;data structure&lt;/a&gt;, and the downstream systems that rely on your API. You should also consider the audience for this API. Will it be publicly available? For private or internal use only? Or limited to verified partners?&lt;/p&gt;

&lt;p&gt;Finally, you should define any key roles or processes your team will use while building and maintaining the API. You’ll need to decide on the tools you’re going to use to design and document the API as well as a plan for change management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design
&lt;/h3&gt;

&lt;p&gt;Next, you will outline the API's design and structure. Based on the performance, scalability, security, and other requirements outlined in the &lt;em&gt;Define&lt;/em&gt; stage, you will need to make decisions like whether to use &lt;a href="https://blog.logrocket.com/graphql-vs-grpc-vs-rest-choosing-right-api/" rel="noopener noreferrer"&gt;REST, GraphQL, or gRPC&lt;/a&gt;, how to authenticate and authorize consumers, and how to report and track errors.&lt;/p&gt;

&lt;p&gt;During this stage, you can create API contracts that provide clear guidelines for the API's behavior. Assuming an HTTP API, developers will often use a standard specification like &lt;a href="https://bump.sh/blog/what-is-openapi?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-first-design" rel="noopener noreferrer"&gt;OpenAPI&lt;/a&gt; or &lt;a href="https://bump.sh/blog/what-is-asyncapi?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-first-design" rel="noopener noreferrer"&gt;AsyncAPI&lt;/a&gt; to define the &lt;a href="https://www.ibm.com/docs/en/amoc/3.0.1?topic=operations-defining-rest-api" rel="noopener noreferrer"&gt;API’s operations (verb and URL)&lt;/a&gt; and response format. Having contracts like this allows developers to properly implement the API, and it lets consumers mock the API so they can build downstream applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Develop and Document
&lt;/h3&gt;

&lt;p&gt;In the next stage, you will implement the API, and create the necessary documentation.&lt;/p&gt;

&lt;p&gt;Traditionally, documentation has been a manual process, but API tooling has come a long way, and now you can use tools like &lt;a href="https://bump.sh/?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-first-design" rel="noopener noreferrer"&gt;Bump.sh&lt;/a&gt; to automatically generate your API documentation from your contract defined during the design phase. This allows your developers to focus on implementing the API and building internal business logic without having to worry if they’re keeping their documentation up to date.&lt;/p&gt;

&lt;p&gt;As in building any web application, you’ll need to make decisions about the internal architecture of the API (framework, language, database, etc.), the ancillary services needed (message queues, notifications, etc.), and deployment options. If you’re in an established organization, many of these decisions might be mandated externally, but in greenfield projects, there’s often a lot of leeway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test
&lt;/h3&gt;

&lt;p&gt;Before deploying an API, it's important to thoroughly test it to ensure that it behaves as expected, meets the outlined spec, and will continue to behave as expected as the API changes. Typically, this includes unit testing, integration testing, and load testing. While &lt;a href="https://www.infoworld.com/article/3286529/test-automation-comes-of-age.html" rel="noopener noreferrer"&gt;automated testing should comprise the bulk of your API tests&lt;/a&gt; you’ll likely want to do some manual QA as well to catch any unexpected behaviors before you launch.&lt;/p&gt;

&lt;p&gt;After launch, testing is equally important, so focus on building repeatable testing practices: run them as part of your CI pipeline, keep an eye on code coverage metrics, and don’t let test debt pile up. As you might imagine, these tests will be invaluable once your API starts changing and growing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secure
&lt;/h3&gt;

&lt;p&gt;While security should have been considered at the design stage, this point is important enough to check again after implementation. You want to prevent any unauthorized use or abuse of your API to ensure that sensitive data is protected. Encryption, access controls, user authentication, and other security measures should all be tested and verified before deployment. All the security checks that can be repeated should also be included in your CI processes so they are conducted continuously.&lt;/p&gt;

&lt;p&gt;Most high-stakes API projects will have penetration tests conducted by internal or external auditors. If you’re new to API security, familiarize yourself with &lt;a href="https://owasp.org/www-project-api-security/" rel="noopener noreferrer"&gt;the OWASP API Security Top 10&lt;/a&gt; and make sure you’re covered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy
&lt;/h3&gt;

&lt;p&gt;After testing and securing the API, you can deploy it for use by its intended audience. Obviously, the specifics of this step vary greatly depending on your tech and infrastructure stack, but most companies use multiple environments to ensure their API can be deployed and that changes don’t cause unintended consequences when they’re released.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observe
&lt;/h3&gt;

&lt;p&gt;Observability has come a long way in the past few years, and modern tools allow you to easily track your API's usage, performance, access logs, and errors. Instrumentation should let you catch issues and help you understand how consumers are using the API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evolve
&lt;/h3&gt;

&lt;p&gt;It is worth noting that this API development lifecycle isn’t a one-time process. Like most software projects, you’ll come back to implement changes frequently, so you’ll need to have a plan for implementing, testing, and announcing those changes.&lt;/p&gt;

&lt;p&gt;Tools like &lt;a href="https://bump.sh/api-change-management?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-first-design" rel="noopener noreferrer"&gt;Bump.sh&lt;/a&gt; can help with this as it can track structural changes to your API to automatically update a &lt;a href="https://keepachangelog.com/en/1.0.0/" rel="noopener noreferrer"&gt;changelog&lt;/a&gt; and trigger a &lt;a href="https://docs.bump.sh/help/api-change-management/webhooks/?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-first-design" rel="noopener noreferrer"&gt;webhook to notify other services&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, this lifecycle isn’t necessarily linear: you may need to move backward before you can move forwards. For example, during the development stage, teams may find that certain requirements must be re-evaluated or redesigned. Or, during the testing stage, they may discover issues that require changes to the API's design or implementation. In such cases, teams may need to go back to a previous stage of the API lifecycle to address these issues before moving forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer API Tools
&lt;/h2&gt;

&lt;p&gt;I’ve hinted at tooling a couple of times in this piece, but because it’s such an important part of building a great API, I’ll dig deeper here. There are a few categories of tools that are important when designing and building APIs, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://bump.sh/blog/the-best-api-documentation-tools-for-dev-teams?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-first-design" rel="noopener noreferrer"&gt;&lt;strong&gt;Documentation tools&lt;/strong&gt;&lt;/a&gt; range from presentation-only tools to automatic doc generation tools. In any case, you’ll definitely need some way to document your API and manage changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mocking tools&lt;/strong&gt; allow you to stub all or part of your API so consumers can work without a deployed version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing tools&lt;/strong&gt; come in many different shapes and sizes but most will allow you to automatically run and call endpoints with various parameters to ensure the results match your expectations.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;API browser&lt;/strong&gt; can be helpful for browsing and troubleshooting endpoints or testing specific requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finding the right mix of tools often comes down to personal preference, cost, and ease of use or implementation. Ultimately, what works for one company might not work for another, so it’s important to evaluate all the options in your unique context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;API-first design is a powerful way of building software that prioritizes APIs and their consumers. Development teams can create better products and more efficient workflows by designing APIs first and then building the rest of the application around them.&lt;/p&gt;

&lt;p&gt;Additionally, by thinking about the API from the beginning of the development process, teams can better anticipate the needs of third-party developers and create a more user-friendly experience for them. Overall, API-first design is a key strategy for creating high-quality, effective APIs that are well-suited to the needs of modern software development.&lt;/p&gt;

&lt;p&gt;Getting your API-first design efforts off the ground can be made easier with Bump.sh. Bump.sh is the simplest way to automatically create API documentation portals for internal, partners, and public APIs. Feel free to look at our &lt;a href="https://bump.sh/users/sign_up?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-first-design" rel="noopener noreferrer"&gt;solution&lt;/a&gt;, and please reach out to us if you have any feedback, comments, or suggestions you'd like to share. We're always listening.&lt;/p&gt;

&lt;p&gt;Author: &lt;a href="https://portal.draft.dev/writers/recHYOn2s7qbIn9lc" rel="noopener noreferrer"&gt;Alex Doukas&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apidesign</category>
      <category>api</category>
      <category>apifirst</category>
      <category>designsystem</category>
    </item>
    <item>
      <title>API Contracts - an Extended Introduction</title>
      <dc:creator>Bump.sh</dc:creator>
      <pubDate>Mon, 12 Jun 2023 15:08:33 +0000</pubDate>
      <link>https://dev.to/bump/api-contracts-an-extended-introduction-4ig3</link>
      <guid>https://dev.to/bump/api-contracts-an-extended-introduction-4ig3</guid>
      <description>&lt;p&gt;An API contract is a document that showcases how an API behaves and how it should be used.&lt;br&gt;
This article is all about API contracts: how they can help your business, the best practices to follow, as well as some practical examples.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Are API Contracts Important?
&lt;/h3&gt;

&lt;p&gt;The purpose of an API contract is to ensure developers using the API can interact with it in a consistent and predictable manner.&lt;/p&gt;

&lt;p&gt;A consistent API contract also helps standardize integration with other systems, reducing misunderstandings and errors.&lt;/p&gt;

&lt;p&gt;It's a useful tool for promoting a shared understanding of your API, easing in changes, and assuring the users of your APIs stability and reliability.&lt;/p&gt;

&lt;p&gt;Having a defined API contract helps streamline processes for both internal and external API users. When multiple external systems or teams are involved, a contract can help avoid misunderstandings and reduce the risk of API usage errors.&lt;/p&gt;

&lt;p&gt;It’s also important in API-first design as downstream teams will often start building mocks of your API before the first version is actually live. Your API development team’s process is also improved with a contract in place, as there's a clear set of guidelines for how the API should behave.&lt;/p&gt;

&lt;p&gt;API contracts can contribute to the security and dependability of the systems that use them. By specifying rules around how different systems should interact, API contracts can help prevent misuse of data and ensure that systems can recover gracefully from errors or failures. Good API contracts will also include details about authorization, request limits, and usage restrictions, which helps users avoid accidentally losing access.&lt;/p&gt;

&lt;p&gt;Finally, almost any API that uses a strict contracting process will have better documentation than one that doesn’t. Often, API contracts are turned directly into documentation, making the lives of development teams much easier.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Are API Contracts ?
&lt;/h3&gt;

&lt;p&gt;API contracts can take many forms, such as a document describing the interface, a formal specification written in a particular language, or a set of code examples illustrating how the API should be used; it can also be written in a combination of formats.&lt;/p&gt;

&lt;p&gt;API Contracts often follow a preexisting specification like &lt;a href="https://spec.openapis.org/oas/latest.html" rel="noopener noreferrer"&gt;OpenAPI&lt;/a&gt;, &lt;a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt;, &lt;a href="https://spec.graphql.org/October2021/" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt;, &lt;a href="https://www.asyncapi.com/docs/reference/specification/v2.0.0" rel="noopener noreferrer"&gt;AsyncAPI&lt;/a&gt;, or &lt;a href="https://apiblueprint.org/documentation/specification.html" rel="noopener noreferrer"&gt;Blueprint&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using an established standard helps new developers working with your contract learn it faster and it helps your development team save time on creating and maintaining the contract. Most standard come with a set of tools and a publicly available community which gives them the advantage of almost always being better than coming up with your own API contract from scratch.&lt;br&gt;
These contracts typically set out information such as the API's expected behavior, data formats, authorization and authentication processes, error handling, and limitations. Seeing how the contract changes over time can also help users understand changes to your API as new versions are released.&lt;/p&gt;

&lt;p&gt;It may include details about the specific endpoints (i.e., URLs) that can be called, the parameters that can be passed to those endpoints, and the responses that will be returned. Some API contracts may also include information about authentication and authorization, error handling, and other details that are key to proper integration.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Should You Consider When Designing an API Contract?
&lt;/h3&gt;

&lt;p&gt;Here are some basic concepts to keep in mind while designing your API contract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep it simple, easy to understand, and consistent:&lt;/strong&gt; In most cases, you should use a predefined specification (as mentioned above) to help users learn and integrate your API into their applications more quickly while reducing the scope for misunderstandings or errors. A uniform vocabulary and style across the contract can also help developers identify what they need and quickly understand how to use the API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Document all parts of the API:&lt;/strong&gt; This API contract will be a very good place for everyone interacting with your API to have a complete overview of it. The more it is exhaustive, the more they will be able to fully view and understand the structure of your API. Including elements such as inputs, outputs, error codes, etc. is enormously helpful in the implementation process. Examples are also beneficial as they offer a clear understanding of how the API works and how to incorporate it into applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Thoroughly test the API against the contract:&lt;/strong&gt; You should test the implementation of your API against the stated contract before release, and provide means of reporting changes - especially breaking ones - or inconsistencies as the API evolves. This means your contract should be in a format allowing your QA process to read and validate against it. Ideally, the testing process should be automated so your API can be validated during the &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration" rel="noopener noreferrer"&gt;continuous integration&lt;/a&gt; process each time changes are made.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  API Contracts: Best Practices
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Defining the Expected Behavior of the API
&lt;/h3&gt;

&lt;p&gt;At a minimum, your API contract should showcase the expected behavior of your API and its endpoints as well as explore details about how an application will call the API. Here's an excerpt of an API contract showcasing the API behavior and the data you can get from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
GET /weather

Input parameters:
- location (string): The location for which to retrieve weather information (e.g. "New York, NY")
- version (string): The version of the API to use (e.g. "v1", "v2")

Output:
- temperature (float): The current temperature in degrees Fahrenheit
- condition (string): A description of the current weather conditions (e.g. "sunny", "cloudy", "rainy")

Example usage:

GET /weather?location=New%20York,%20NY&amp;amp;version=v2

Output:
{
  "temperature": 72.5,
  "condition": "sunny"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[&lt;em&gt;Representation of the behavior of the API&lt;/em&gt;]&lt;/p&gt;

&lt;p&gt;Your contract should always provide details on how your users can utilize your API. This excerpt, for example, specifies that the API can be accessed using a GET request to the &lt;code&gt;/weather&lt;/code&gt; endpoint and that it takes an input parameter, &lt;code&gt;location&lt;/code&gt;, which is a string representing the location for which to retrieve weather information. The second input parameter, &lt;code&gt;version&lt;/code&gt;, is also a string and represents the version of the API the user would like to interact with.&lt;/p&gt;

&lt;p&gt;It also makes clear that the API returns a JSON object with two fields: temperature, which is a float representing the current temperature in degrees Fahrenheit, and condition, which is a string describing the current weather conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specifying the Contract and API Version
&lt;/h3&gt;

&lt;p&gt;It is common, on an API lifecycle, to see changes to the API behavior itself.  As an API grows, changes will be made to the current version of the API. The contract is a good place to communicate to your users and API consumers about the changes in your API and how to keep using your API service after the change applies.&lt;/p&gt;

&lt;p&gt;If you need to make a breaking change or your API grows and changes so much that you have the need to release a new version of it, you will need to create a new contract. Each version of your API should possess its own. And ideally each version of the API has their own documentation.&lt;/p&gt;

&lt;p&gt;Your contract should note which API version it services.&lt;br&gt;
It should also display the API contract version, which can be different from your API version. For instance, in the OpenAPI spec, an &lt;a href="https://spec.openapis.org/oas/v3.1.0#fixed-fields-0" rel="noopener noreferrer"&gt;info.version&lt;/a&gt; field is used to explicitly state the version or revision of the API contract in use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;info:
  description: "A simple API example."
  title: "Example"
  version: "1.2"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[&lt;em&gt;An example of how to specify the version according to the Open API spec&lt;/em&gt;]&lt;/p&gt;

&lt;p&gt;As your API contract and API versions change, you should ensure these are noted in your changelog or release notes. This helps users know when a breaking release is made and what they need to do to keep their implementation working.&lt;/p&gt;

&lt;h3&gt;
  
  
  Document Data Formats, Limitations, and Restrictions
&lt;/h3&gt;

&lt;p&gt;Your API contract should accurately document the peculiarities and formats of data that a user might receive from API calls. &lt;a href="https://medium.datadriveninvestor.com/why-data-normalization-is-still-a-huge-challenge-for-organizations-6e0d5f5721d" rel="noopener noreferrer"&gt;Data normalization is notoriously difficult&lt;/a&gt;, so you want to help your API’s users as much as possible by giving them clear descriptions of return types and input expectations.&lt;/p&gt;

&lt;p&gt;It should also set out the limitations that the user should be aware of as they implement the API — for example, rate limits, availability schedules, and requirements for access to certain data. If these constraints are not clear it can be frustrating for users who suddenly hit unexpected limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Contract at the Age of Automation
&lt;/h2&gt;

&lt;p&gt;Your API contract does not only allow you all the things listed above, it’s also a good piece to add in your automations.&lt;/p&gt;

&lt;p&gt;A common practice is to have your unit tests results tested against the API contract. You can make your &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration" rel="noopener noreferrer"&gt;CI&lt;/a&gt; process fail if the behavior of the API is not matching the expectations of the contract, and you can also analyze changes (including breaking changes) directly from the CI as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next for your API Contract ?
&lt;/h2&gt;

&lt;p&gt;Once you’ve defined your contract and implemented your API, you can use a tool to &lt;a href="https://bump.sh/api-documentation?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-contracts" rel="noopener noreferrer"&gt;create the user-facing documentation&lt;/a&gt;. In addition to documentation generation based on API contract documents, Bump.sh also integrates with your CI pipeline to ensure that changes to the API are noted in the documentation upon each release.&lt;/p&gt;

&lt;p&gt;If you’re interested in learning more about API design or development, be sure to check out the &lt;a href="https://bump.sh/blog?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-contracts" rel="noopener noreferrer"&gt;Bump.sh blog&lt;/a&gt;, or &lt;a href="https://bump.sh/users/sign_up?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-contracts" rel="noopener noreferrer"&gt;sign up for free&lt;/a&gt; to see how Bump.sh can help you generate user documentation more easily.&lt;/p&gt;

</description>
      <category>apicontract</category>
      <category>documentation</category>
      <category>api</category>
      <category>asyncapi</category>
    </item>
    <item>
      <title>Creating Better API Architecture Diagrams</title>
      <dc:creator>Bump.sh</dc:creator>
      <pubDate>Mon, 12 Jun 2023 14:59:34 +0000</pubDate>
      <link>https://dev.to/bump/creating-better-api-architecture-diagrams-7in</link>
      <guid>https://dev.to/bump/creating-better-api-architecture-diagrams-7in</guid>
      <description>&lt;p&gt;Architecture diagrams are essential in the API development process. They provide a map of how different systems interact to help software teams manage and maintain them, and they provide insight into the architect’s vision for the entire system. Along with other elements like interactive API portals, API architecture diagrams also help enrich your API’s documentation.&lt;/p&gt;

&lt;p&gt;This guide will share more about the various types of API architecture diagrams and some tips for creating them. You will see several examples of these diagrams and learn about the utility of UML for modeling them. Finally, you’ll get some best practices for creating architecture diagrams as a supplement to your API documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are API Architecture Diagrams and Do You Need Them?
&lt;/h2&gt;

&lt;p&gt;API architecture diagrams are visual representations of the structure and interactions of the components of an API. They can help developers and architects plan the interface structure, users understand the intended use of the API, and they can also help QA engineers better test and debug the API.&lt;/p&gt;

&lt;p&gt;Typically, an API architecture diagram will &lt;strong&gt;identify the various API components, their relationships with each other, and the data flow between them&lt;/strong&gt;, but as you’ll see in this piece, there are many types of API diagrams worth looking at.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1356308080389193728-149" src="https://platform.twitter.com/embed/Tweet.html?id=1356308080389193728"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1356308080389193728-149');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1356308080389193728&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;Unfortunately, creating a good API architecture diagram takes time. As the author of the Tweet above points out, this particular diagram took 10 hours of work to complete. So, creating diagrams like this can be helpful, but your engineering and documentation teams will need to make time to get them right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of API Architecture Diagrams
&lt;/h2&gt;

&lt;p&gt;Depending on the API you’re documenting, the communication protocols you’re using, the complexity of the system, and the goals of the architecture diagram, you may diagram the API differently. In this post, I’ll primarily focus on diagramming &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer" rel="noopener noreferrer"&gt;REST&lt;/a&gt; APIs, but the types of API diagrams you can create are basically endless.&lt;/p&gt;

&lt;p&gt;That said, here are a few interesting common types of API architecture diagrams:&lt;/p&gt;

&lt;h3&gt;
  
  
  Sequence Diagrams
&lt;/h3&gt;

&lt;p&gt;One way to use an API diagram is to illustrate a specific workflow that consumers need to know about. A sequence diagram often includes the HTTP verb (&lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, or &lt;code&gt;DELETE&lt;/code&gt;) and resource name for each API call in the diagram. They can also be useful for noting any custom calls (like bulk endpoints) that your API offers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j6mojve91nkj1abdtgc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j6mojve91nkj1abdtgc.jpg" alt="API diagram that includes HTTP verb and resource" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The API diagram above uses the order of arrows to indicate the order in which the calls should be made. Complex workflows like authentication and authorization often require API calls to be made in a very specific order, so API architecture diagrams can help clarify this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kuze8z8xqovywvur9mu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kuze8z8xqovywvur9mu.png" alt="API flow diagram" width="800" height="622"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Example of a REST API sequence diagram with swimlanes.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Service Architecture Diagrams
&lt;/h3&gt;

&lt;p&gt;Another way to use API architecture diagrams is to show how multiple services are connected and integrated with one another.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuedwsr5ek4i977h6ox9u.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuedwsr5ek4i977h6ox9u.jpg" alt="API architecture diagram that shows system integration" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram above shows how an online store’s architecture diagram might look, including the resources, endpoints, and attributes of each resource.&lt;/p&gt;

&lt;p&gt;Service Architecture Diagrams help new users get a “lay of the land” when it comes to your API, meaning they can quickly see how all the resources and data models are related. This can help them plan out their application, especially if they’ll rely on several endpoints or services within your ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal API Architecture Diagrams
&lt;/h3&gt;

&lt;p&gt;Finally, your diagram might be focused on illustrating the internal architecture of your system rather than the external.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx97p1s1d5afmhbxbwqz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx97p1s1d5afmhbxbwqz.jpg" alt="Internal API architecture diagram" width="689" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These diagrams are useful for other engineers at your company to see how the system is designed so they can better understand errors and debug errors faster. They help new engineers onboard faster, and can serve as a reference point when designing new systems at the company. Finally, they help with internal processes like security audits as knowing all the layers a request goes through before accessing your data can help identify vulnerabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools for Creating API Architecture Diagrams
&lt;/h2&gt;

&lt;p&gt;Now that we have covered some types of API diagrams you might use, the next step is to figure out how to actually create the model for your API architecture diagram. There are many different tools available depending on your preference, team’s experience, and the purpose of your diagrams, but let’s take a look at three.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unified Modeling Language (UML)
&lt;/h3&gt;

&lt;p&gt;Engineers have a range of visual language models they can use to create graphical diagrams of software systems, but one of the most common standards for diagramming is &lt;a href="https://en.wikipedia.org/wiki/Unified_Modeling_Language" rel="noopener noreferrer"&gt;Unified Modeling Language (UML)&lt;/a&gt;. Many developers choose UML because of its:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Widespread use&lt;/strong&gt; - Using a &lt;a href="https://www.omg.org/spec/UML/Current" rel="noopener noreferrer"&gt;standard like UML&lt;/a&gt; ensures that multiple members of your team can pick it up and make modifications to the diagram in the future.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt; - Although the UML has a vast library of symbols and concepts designed explicitly for creating software architecture diagrams, you can also customize its elements to fit whatever technologies your project uses or visual representations you want to create. UML is not limited to object-oriented software modeling, but is also commonly used to explain business processes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tooling&lt;/strong&gt; - The popularity of the UML has led to the creation of a number of tools ranging from online tools for creating UML diagrams, to tools for generating code from diagrams. This ever-growing ecosystem of UML tools makes it more convenient than other languages of its kind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The downside to UML is that you have to learn its way of doing things, so there’s a bit of a learning curve to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mermaid
&lt;/h3&gt;

&lt;p&gt;UML is just one format for diagram design specifications. Another option is to use a code to diagram tool like &lt;a href="https://mermaid.js.org/" rel="noopener noreferrer"&gt;Mermaid&lt;/a&gt;. Mermaid transforms plain-text (&lt;a href="https://en.wikipedia.org/wiki/Markdown" rel="noopener noreferrer"&gt;Markdown&lt;/a&gt; inspired text definitions in this case) into full-fleshed visual diagrams. Their tool is &lt;a href="https://github.com/mermaid-js/mermaid" rel="noopener noreferrer"&gt;open-source and written in JavaScript&lt;/a&gt;, making it easy to customize if you’re so inclined. Advantages include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Use&lt;/strong&gt; - Markdown is a well-established language for developer documentation, and their &lt;a href="https://mermaid.live/edit" rel="noopener noreferrer"&gt;live editor&lt;/a&gt; includes examples to help you get started.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizability&lt;/strong&gt; - In addition to being open-source at its core, Mermaid allows you to build themes on top of the core product or use the API to generate diagrams programmatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrations&lt;/strong&gt; - You can install Mermaid on your own server or embed it directly into your documentation or developer portal, making it one of the most flexible options out there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Downsides to Mermaid could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The default chart and diagram types are limited. As mentioned, you can customize it as much as you want to create new types of diagrams, but that takes a fair bit of work and programming knowledge.&lt;/li&gt;
&lt;li&gt;Mermaid uses &lt;a href="https://mermaid.js.org/intro/n00b-syntaxReference.html" rel="noopener noreferrer"&gt;its own syntax&lt;/a&gt;. Even though it’s based on Markdown as mentioned above, it does take a bit of practice before you’ll be completely used to the tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lucidchart
&lt;/h3&gt;

&lt;p&gt;Another approach to creating API architecture diagrams is using a tool like &lt;a href="https://www.lucidchart.com/pages/" rel="noopener noreferrer"&gt;Lucidchart&lt;/a&gt;, which sort of combines the best of a structured language like UML with an open-ended drawing tool. This makes Lucid good for its:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adaptability&lt;/strong&gt; - With Lucid, you can create your own shared library of diagram elements (or use a standard like UML). These diagram elements can become your team’s visual language and help API diagrams across your entire company look similar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration&lt;/strong&gt; - As a purpose-built team diagramming tool, Lucid allows you to version and share documents with your team or the public.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The downside to Lucid is that it’s a little more complex to learn than a freeform drawing tool and it’s not free. After your 7-day trial, you’ll be paying—as of today—at least $9 per month for an individual account.&lt;/p&gt;

&lt;p&gt;Finally, it’s worth noting that the three options above aren’t mutually exclusive, and there are many other tools you can use to create API architecture diagrams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for API Architecture Diagrams
&lt;/h2&gt;

&lt;p&gt;Once you know what kind of API architecture diagram you need and how you’ll go about creating it, there are still a few design best practices to keep in mind. Even if your diagram is only intended for internal use, making it visually appealing can help people digest the information better and avoid confusion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the Right Type of Diagram
&lt;/h3&gt;

&lt;p&gt;I’ve already discussed a few types of API architecture diagrams above, but it’s worth noting that you need to consider the goals of your diagram before picking the type of diagram you should create. Remember, a good diagram takes time to design and maintain, so don’t do work you don’t need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Think of Accessibility
&lt;/h3&gt;

&lt;p&gt;Clarity is key when designing architecture diagrams. This is especially true for complex API diagrams, so it's a good idea to use contrasting colors and shapes for each type of component. You can play with colors, shapes, and background patterns for each component so they're easier to identify. Keep in mind that not all eyes work the same (for instance &lt;a href="https://www.clintoneye.com/color-blindness.html" rel="noopener noreferrer"&gt;one in 12 men are colorblind&lt;/a&gt;), so high contrast between elements and text is very important. Tools like &lt;a href="https://github.com/michelf/sim-daltonism/" rel="noopener noreferrer"&gt;Sim Daltonism&lt;/a&gt; on osX can help ensure that your diagrams are readable for everyone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep it Simple and Avoid Redundancy
&lt;/h3&gt;

&lt;p&gt;Make sure your diagram is as straightforward to understand as possible. Avoid redundant elements or unnecessary complexity like intersecting lines. Also, promote readability by using &lt;a href="https://en.wikipedia.org/wiki/Swimlane" rel="noopener noreferrer"&gt;swimlanes&lt;/a&gt;, leaving enough white space between diagram elements, and maintaining a uniform size of symbols and figures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoid Jargon
&lt;/h3&gt;

&lt;p&gt;To promote clarity and readability, it's good practice to use simple, easy-to-understand terms instead of technical jargon. In cases where this isn't possible, at least explain your terms. You can do this by including &lt;a href="https://www.quora.com/What-is-the-difference-between-map-legend-and-map-keys" rel="noopener noreferrer"&gt;a key or legend&lt;/a&gt; along with your diagram.&lt;/p&gt;

&lt;h3&gt;
  
  
  Going Further
&lt;/h3&gt;

&lt;p&gt;As mentioned previously, API diagrams are a great way to help a user understand your API. They're a great addition to the “Getting Started” section you’ll find in a lot of API documentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.bump.sh/help/specifications-support/markdown-support/?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-architecture-diagams" rel="noopener noreferrer"&gt;Bump.sh supports markdown&lt;/a&gt; descriptions and helps you share your API architecture diagrams via generated documentation based on an &lt;a href="https://bump.sh/blog/api-contracts-extended-introduction?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-architecture-diagams" rel="noopener noreferrer"&gt;API contract&lt;/a&gt;.&lt;br&gt;
To add an image to any markdown you just need the following syntax &lt;code&gt;![](https://rb.gy/i0zf0)&lt;/code&gt; where the link is a public URL to your image. More on that, brand new image sizing feature and best practices &lt;a href="https://docs.bump.sh/help/specifications-support/markdown-support/#images?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-architecture-diagams" rel="noopener noreferrer"&gt;in the &lt;strong&gt;Images&lt;/strong&gt; section of the documentation&lt;/a&gt;.&lt;br&gt;
It you want to play even more with markdown, the &lt;a href="https://docs.bump.sh/help/specifications-support/markdown-support/#adding-topics-to-your-documentation?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-architecture-diagams" rel="noopener noreferrer"&gt;&lt;code&gt;x-topics&lt;/code&gt; property&lt;/a&gt; makes it easy to add relevant content sections to your documentation for a well-organized, reader-friendly structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, you learned how API architecture diagrams can support your product and documentation efforts. You saw how diagrams can make systems that are easier to understand and maintain, and you learned about a few different types of API architecture diagrams that are available. Finally, you learned about a few tools and best practices for creating API architecture diagrams that are easier to read and maintain.&lt;/p&gt;

&lt;p&gt;Diagrams are just one tool in a developer’s toolbox for providing clarity around their APIs. You’ll also need documentation (which often includes relevant diagrams), an API contract, and a change management system.&lt;/p&gt;

&lt;p&gt;If you’re looking for more ways to provide clarity around your API, check out &lt;a href="https://bump.sh/?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-architecture-diagams" rel="noopener noreferrer"&gt;Bump.sh&lt;/a&gt;. Import API contracts into Bump.sh and automatically generate human-readable documentation, with &lt;a href="https://bump.sh/api-change-management?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-architecture-diagams" rel="noopener noreferrer"&gt;change-tracking&lt;/a&gt; and &lt;a href="https://docs.bump.sh/help/api-change-management/#changes-notification?utm_source=devto&amp;amp;utm_medium=devto-blog&amp;amp;utm_campaign=blog-api-architecture-diagams" rel="noopener noreferrer"&gt;notification capabilities&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Author: &lt;a href="https://portal.draft.dev/writers/recNA8hRZSciDpy1O" rel="noopener noreferrer"&gt;Damaso Sanoja&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>tutorial</category>
      <category>architecture</category>
      <category>diagrams</category>
    </item>
  </channel>
</rss>
