<?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: Kanad Gupta</title>
    <description>The latest articles on DEV Community by Kanad Gupta (@kanad).</description>
    <link>https://dev.to/kanad</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%2Fuser%2Fprofile_image%2F681372%2F70e88367-a7c3-41f5-933b-132dc6ac20b5.png</url>
      <title>DEV Community: Kanad Gupta</title>
      <link>https://dev.to/kanad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kanad"/>
    <language>en</language>
    <item>
      <title>Authenticating Into ReadMe’s CLI With 1Password and Your Fingerprint ☝️</title>
      <dc:creator>Kanad Gupta</dc:creator>
      <pubDate>Thu, 04 May 2023 15:53:29 +0000</pubDate>
      <link>https://dev.to/readme/authenticating-into-readmes-cli-with-1password-and-your-fingerprint-22oa</link>
      <guid>https://dev.to/readme/authenticating-into-readmes-cli-with-1password-and-your-fingerprint-22oa</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v2GT2IYp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.readme.com/content/images/2023/05/1p-banner-1360x500.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v2GT2IYp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.readme.com/content/images/2023/05/1p-banner-1360x500.png" alt="Authenticating into the ReadMe CLI using Touch ID" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Long-time followers of the ReadMe blog know &lt;a href="https://blog.readme.com/two-factor-auth/"&gt;I have been absolutely shameless in my love for 1Password&lt;/a&gt;. It's a great password manager that we use here at ReadMe to securely store shared logins, API keys, and more. Staying secure online is increasingly difficult these days, and we’ve been able to safely rely on 1Password for best-in-class security with a convenience and user experience that lives up to one of &lt;a href="https://readme.com/values?ref=blog.readme.com"&gt;our core ReadMe values&lt;/a&gt;: “strive for simplicity.”&lt;/p&gt;

&lt;p&gt;So it should come as no surprise that I’m very stoked to announce ReadMe's partnership with 1Password. With &lt;a href="https://developer.1password.com/docs/cli/shell-plugins/readme/?ref=blog.readme.com"&gt;the ReadMe shell plugin for the 1Password CLI&lt;/a&gt;, together we’re making your experience with ReadMe’s developer tools even more convenient and secure. Get the details below! 🤝&lt;/p&gt;

&lt;h2&gt;
  
  
  Juggling API keys: a necessary DX evil 🤹
&lt;/h2&gt;

&lt;p&gt;Let’s first start with some background. Over the last year or so, we’ve been making several improvements to the developer experience around API keys in ReadMe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://github.blog/changelog/2022-08-17-readme-is-now-a-github-secret-scanning-partner/?ref=blog.readme.com"&gt;secret scanning partnership with GitHub&lt;/a&gt; to automatically revoke exposed ReadMe API keys and notify our users ♻️&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://docs.readme.com/main/reference/intro/authentication?ref=blog.readme.com#generating-new-api-keys-"&gt;ReadMe API key management dashboard&lt;/a&gt; which gives you the ability to provision multiple keys for your project and makes it easier to rotate keys out 🔄&lt;/li&gt;
&lt;li&gt;Interactive &lt;a href="https://docs.readme.com/main/reference/intro/authentication?ref=blog.readme.com"&gt;Getting Started and Authentication pages&lt;/a&gt; in the API reference section, where you can browse your ReadMe API keys and make authenticated requests to the ReadMe API directly from the docs (and yes, you can also &lt;a href="https://docs.readme.com/main/docs/reference-core-pages?ref=blog.readme.com"&gt;set these pages up for your users&lt;/a&gt;!) 🔑&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While these changes have been great from a security and developer experience standpoint, none of these could possibly address a common problem amongst developers: juggling lots of API keys. Figuring out where keys came from, rotating keys, maintaining separate keys for separate environments/users…the list goes on! It’s a necessary evil for developers when a key inevitably gets leaked 🙀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6yESN9WH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/11/GS-A-Pages-in-Hub.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6yESN9WH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/11/GS-A-Pages-in-Hub.gif" alt="Authenticating Into ReadMe’s CLI With 1Password and Your Fingerprint ☝️" width="800" height="440"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Getting Started and Authentication pages in the API reference 🔑&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our knowledge base has grown to the point of &lt;a href="https://docs.readme.com/main/changelog/2022-11-30-v4-286-0?ref=blog.readme.com"&gt;switching over to a multi-project setup for our docs&lt;/a&gt;. Because of this, we’re now working with many API keys across several ReadMe projects, which is also the case with many of our Enterprise customers. And once you start dealing with multiple API keys that you’re sharing with your team, it can get chaotic rather quickly.&lt;/p&gt;

&lt;p&gt;1Password has proven to be a useful management tool for API keys not only because of its security, but also because you can jot down notes for a given API key. You can use this to provide helpful context for fellow engineers, like expiration dates, links to management dashboards, where it’s used, etc. While it’s easy enough to store these credentials in your password manager, what about using your password manager as the single source of truth so you can load secrets into your developer environments in a secure, automated way?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p7U5pyMN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.readme.com/content/images/2023/01/CleanShot-2023-01-24-at-15.03.03%402x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p7U5pyMN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.readme.com/content/images/2023/01/CleanShot-2023-01-24-at-15.03.03%402x.png" alt="Authenticating Into ReadMe’s CLI With 1Password and Your Fingerprint ☝️" width="800" height="736"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;When adding an API key to 1Password, include detailed notes for context — your fellow engineers will thank you!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Luckily, &lt;a href="https://blog.1password.com/shell-plugins-roundup/?ref=blog.readme.com"&gt;1Password introduced shell plugins&lt;/a&gt;, which are integrations that securely pass API keys into your favorite command line tools, including &lt;code&gt;gh&lt;/code&gt; (the GitHub CLI), &lt;code&gt;twilio&lt;/code&gt; (the Twilio CLI), and (you can probably guess where I’m going with this…) &lt;code&gt;rdme&lt;/code&gt; (the ReadMe CLI)! Let’s dive into the ReadMe shell plugin below.&lt;/p&gt;
&lt;h2&gt;
  
  
  Say hello to the ReadMe shell plugin 🐚
&lt;/h2&gt;

&lt;p&gt;With the ReadMe shell plugin set up, you can keep your ReadMe API key in 1Password and securely pass it into your &lt;code&gt;rdme&lt;/code&gt; commands. What does this look like in practice? A quick scan of your fingerprint (if you’re a macOS user):&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/XckXvuvZI0E"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Pretty slick, right? Let’s walk through how this all works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, make sure you have &lt;a href="https://github.com/readmeio/rdme?ref=blog.readme.com#readme"&gt;the latest version of &lt;code&gt;rdme&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://1password.com/downloads?ref=blog.readme.com"&gt;the 1Password desktop app&lt;/a&gt; (Mac or Linux only), and &lt;a href="https://developer.1password.com/docs/cli/get-started/?ref=blog.readme.com#install"&gt;the 1Password CLI&lt;/a&gt; (version 2.12.0 or above) installed 💿&lt;/li&gt;
&lt;li&gt;Next, &lt;a href="https://developer.1password.com/docs/cli/shell-plugins/readme/?ref=blog.readme.com"&gt;set up the ReadMe shell plugin for the 1Password CLI&lt;/a&gt;. This will create (or import, if it already exists) a 1Password item that contains your ReadMe API key 🐚&lt;/li&gt;
&lt;li&gt;Once everything is set up, 1Password CLI will listen to your terminal for &lt;code&gt;rdme&lt;/code&gt; commands that require authentication (i.e., authenticated commands like &lt;code&gt;rdme openapi&lt;/code&gt; are listened for and non-authenticated commands like &lt;code&gt;rdme --help&lt;/code&gt; will be ignored) 👂&lt;/li&gt;
&lt;li&gt;When a &lt;code&gt;rdme&lt;/code&gt; command is executed that requires authentication, the 1Password CLI will prompt you for your fingerprint (or whatever authentication setup you have for the 1Password app) ☝️&lt;/li&gt;
&lt;li&gt;The 1Password vault is unlocked, your ReadMe API key is securely passed into the terminal command, and &lt;code&gt;rdme&lt;/code&gt; is connected to your ReadMe project 🚀&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While this approach to passing credentials into &lt;code&gt;rdme&lt;/code&gt; is both convenient and secure, do you want to know what’s my favorite part about this experience? If you’re juggling many API keys across several ReadMe projects like we are, you can store all of them in 1Password and have the ReadMe shell plugin confine your credentials to a specific directory or terminal session.&lt;/p&gt;

&lt;p&gt;With the ReadMe shell plugin, you’ll be an expert API key juggler in no time!&lt;/p&gt;

&lt;h2&gt;
  
  
  Some bonus “action” 🎬
&lt;/h2&gt;

&lt;p&gt;But wait, there’s more! As an added benefit of securely storing API keys in your 1Password vault, you can safely &lt;a href="https://developer.1password.com/docs/ci-cd/github-actions?ref=blog.readme.com"&gt;load them into CI/CD environments&lt;/a&gt;, like GitHub Actions. This is great news, because &lt;a href="https://blog.readme.com/auto-magically-sync-to-readme-with-github-actions/"&gt;&lt;code&gt;rdme&lt;/code&gt; happens to have first-class support for GitHub Actions&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Here’s yet another great example of how 1Password and &lt;code&gt;rdme&lt;/code&gt; can work together in harmony to securely sync a directory of Markdown files to ReadMe:&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="c1"&gt;# Runs on every push to the `main` branch&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="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&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;sync-to-readme&lt;/span&gt;&lt;span class="pi"&gt;:&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;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;Load secret from 1Password&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;1password/load-secrets-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="c1"&gt;# Export loaded secrets as environment variables&lt;/span&gt;
          &lt;span class="na"&gt;export-env&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;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;OP_CONNECT_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;Your Connect instance URL&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;OP_CONNECT_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.OP_CONNECT_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;RDME_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;op://engineering/readme/api-key"&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;Sync OpenAPI file to ReadMe 🦉&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;readmeio/rdme@v8&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="c1"&gt;# `rdme` automatically reads the `RDME_API_KEY` env variable&lt;/span&gt;
          &lt;span class="na"&gt;rdme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docs ./documentation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s break down what’s happening in the example above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This workflow kicks off when a commit is pushed to the &lt;code&gt;main&lt;/code&gt; branch of your GitHub repository.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.1password.com/docs/ci-cd/github-actions?ref=blog.readme.com#export-secrets-as-environment-variables"&gt;1Password’s GitHub Action&lt;/a&gt; establishes a secure connection to 1Password, grabs the ReadMe API key value and exports that as an environmental variable called &lt;code&gt;RDME_API_KEY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/marketplace/actions/rdme-sync-to-readme?ref=blog.readme.com#authentication"&gt;&lt;code&gt;rdme&lt;/code&gt; GitHub Action automatically detects&lt;/a&gt; &lt;code&gt;RDME_API_KEY&lt;/code&gt; as an environmental variable containing your ReadMe API key, and uses that to sync your Markdown docs (located in the &lt;code&gt;documentation/&lt;/code&gt; folder) to your ReadMe project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the power of 1Password and &lt;code&gt;rdme&lt;/code&gt;, you can securely sync your docs to ReadMe — whether you’re working in the command line or in a GitHub Actions runner 😌&lt;/p&gt;

&lt;h2&gt;
  
  
  Now let’s get you plugged in 🔌
&lt;/h2&gt;

&lt;p&gt;Ready to start syncing? The integrations described above are available now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Head over to &lt;a href="https://developer.1password.com/docs/cli/shell-plugins/readme/?ref=blog.readme.com"&gt;the 1Password Developer docs&lt;/a&gt; to get the ReadMe shell plugin up and running 🐚&lt;/li&gt;
&lt;li&gt;Check out our docs on &lt;a href="https://docs.readme.com/main/docs/rdme?ref=blog.readme.com#github-actions-usage"&gt;setting up the &lt;code&gt;rdme&lt;/code&gt; GitHub Action&lt;/a&gt; and &lt;a href="https://developer.1password.com/docs/ci-cd/github-actions/?ref=blog.readme.com"&gt;1Password’s docs on loading secrets into your GitHub Actions workflows&lt;/a&gt; 🌊&lt;/li&gt;
&lt;li&gt;Check out my appearance on the &lt;a href="https://randombutmemorable.simplecast.com/episodes/the-developer-special?ref=blog.readme.com"&gt;"The Developer Special" episode of 1Password's "Random but Memorable" podcast&lt;/a&gt;. We have a wide-ranging conversation about 1Password's developer tools, developer tools in general, and upcoming projects we're cooking up here at ReadMe 🎙️&lt;/li&gt;
&lt;li&gt;Join us on May 11th in SF at &lt;a href="https://apimixtape.com/?ref=blog.readme.com"&gt;API Mixtape&lt;/a&gt;, where we'll be talking all things developers with folks from 1Password, Twilio, and more. Use the code 1PASS for a &lt;strong&gt;free&lt;/strong&gt; ticket (hurry, just a few of these codes are available!)  📼&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re always looking for ways to make ReadMe’s developer tools safer and more enjoyable to use. If you have any feedback about your ReadMe experience, feel free to reach out to us at &lt;a href="//mailto:support@readme.io?ref=blog.readme.com"&gt;support@readme.io&lt;/a&gt; or &lt;a href="https://github.com/readmeio/rdme/issues/new?ref=blog.readme.com"&gt;open up an issue in the &lt;code&gt;rdme&lt;/code&gt; repository&lt;/a&gt;. We’d love to hear from you! 🦉&lt;/p&gt;

</description>
      <category>devrel</category>
      <category>cli</category>
      <category>githubactions</category>
      <category>1password</category>
    </item>
    <item>
      <title>Helping Your Users Write Succinct API Calls With "api" ✍️</title>
      <dc:creator>Kanad Gupta</dc:creator>
      <pubDate>Wed, 21 Dec 2022 20:51:09 +0000</pubDate>
      <link>https://dev.to/readme/helping-your-users-write-simpler-api-calls-with-api-2e53</link>
      <guid>https://dev.to/readme/helping-your-users-write-simpler-api-calls-with-api-2e53</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V0YzpYo4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.readme.com/content/images/2022/12/Boarding-Plane.psd.full.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V0YzpYo4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.readme.com/content/images/2022/12/Boarding-Plane.psd.full.png" alt='Helping Your Users Write Simpler API Calls With "api" ✍️' width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to &lt;a href="https://blog.readme.com/why-dx-matters-driving-api-success-with-a-user-first-approach/"&gt;developer experience (DX) at ReadMe&lt;/a&gt;, two mantras often come to mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Awesome by default&lt;/strong&gt; 🆒 While developers often benefit from having a slew of configuration options and flags available in their tooling, &lt;strong&gt;&lt;em&gt;too&lt;/em&gt;&lt;/strong&gt; many options can feel overwhelming, particularly for first-time users. Having a sensible default experience will help your developers get to that first successful API call even faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meet users where they are&lt;/strong&gt; 🤝 No two developers are alike, so your API (&lt;a href="https://blog.readme.com/onboarding-users-with-personalized-docs/"&gt;and your docs!&lt;/a&gt;) should reflect that. Your developers will often have different use cases, different technical stacks, and different levels of experience with APIs. The more your API can accommodate your developers and their diverse needs, the higher your API adoption.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these in mind, we’re always looking for new ways to make APIs more accessible and lower the on-ramp to getting started. Today, we’re sharing more about &lt;a href="https://github.com/readmeio/api"&gt;&lt;code&gt;api&lt;/code&gt;, our open-source SDK generator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;api&lt;/code&gt; takes your OpenAPI definition and generates a powerful SDK that’s custom-tailored to your API. With the world-class developer experience that an &lt;code&gt;api&lt;/code&gt; SDK provides, making API calls has never felt easier or more magical 🪄&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;api&lt;/code&gt; origin story 💭
&lt;/h2&gt;

&lt;p&gt;You’ve probably heard a lot about APIs, but what exactly is &lt;code&gt;api&lt;/code&gt; and why does it matter?&lt;/p&gt;

&lt;p&gt;Let’s start by looking at a typical code sample for an API call. In this example, the sample is written in JavaScript, and it uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;the Fetch API&lt;/a&gt; to &lt;a href="https://docs.readme.com/main/reference/getopenroles"&gt;fetch our current job openings from the ReadMe API&lt;/a&gt;:&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://dash.readme.com/api/v1/apply&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ReadMe’s API reference automatically generates code samples for your endpoints in dozens of languages and libraries, including &lt;code&gt;fetch&lt;/code&gt;. And for good reason too — &lt;code&gt;fetch&lt;/code&gt; is popular, versatile, and it’s available everywhere!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s baked into every modern web browser (including the one you’re likely reading this on!) 🌐&lt;/li&gt;
&lt;li&gt;It can run on the server out-of-the-box (thanks to runtimes like &lt;a href="https://deno.com/deploy/docs/runtime-fetch"&gt;deno&lt;/a&gt; and &lt;a href="https://nodejs.org/en/blog/announcements/v18-release-announce/#fetch-experimental"&gt;Node.js 18&lt;/a&gt;) 📦&lt;/li&gt;
&lt;li&gt;It offers a tremendous amount of flexibility to handle a wide variety of API use cases 💪&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this approach isn't for everybody. Since &lt;code&gt;fetch&lt;/code&gt; and other generic HTTP clients are designed to make calls to nearly every API under the sun, there’s inherently going to be verbosity, boilerplate code, and a whole lot of configuration options. This makes your typical, off-the-shelf HTTP client pretty confusing for many API users.&lt;/p&gt;

&lt;p&gt;At ReadMe, we’re constantly keeping an eye on the best DX out there, and we’ve come to notice a trend. Many of the top &lt;a href="https://techcrunch.com/2022/06/18/the-rise-of-api-first-companies-in-fintech-and-beyond/"&gt;API-first companies&lt;/a&gt; out there offer their own custom &lt;a href="https://en.wikipedia.org/wiki/Software_development_kit"&gt;SDKs&lt;/a&gt;, such as &lt;a href="https://stripe.com/docs/js"&gt;Stripe&lt;/a&gt;, &lt;a href="https://www.twilio.com/docs/libraries/js-libraries"&gt;Twilio&lt;/a&gt;, and &lt;a href="https://github.com/plaid/plaid-node"&gt;Plaid&lt;/a&gt; (and I’m only linking to their JavaScript SDKs!).&lt;/p&gt;

&lt;p&gt;Those companies and their respective SDKs are the tip of the iceberg. API-first companies are continually investing in SDKs for a variety of programming languages, and for good reason. With an SDK that’s custom-tailored to a single API, their users have much less boilerplate code and confusing configuration options to deal with, so they can get to that first successful API call even faster.&lt;/p&gt;

&lt;p&gt;Thousands of great APIs run their developer hubs on ReadMe, where our customers are already documenting every little detail about their API using &lt;a href="https://docs.readme.com/docs/openapi"&gt;the OpenAPI Specification&lt;/a&gt;. This got us thinking: “the OpenAPI Specification already provides a ton of valuable information about an API, what if we use this to generate an SDK that’s as good as &lt;a href="https://github.com/makenotion/notion-sdk-js"&gt;Notion’s JavaScript SDK&lt;/a&gt;”?&lt;/p&gt;

&lt;p&gt;And that, my friends, is how &lt;code&gt;api&lt;/code&gt; came to fruition. 🌱&lt;/p&gt;

&lt;h2&gt;
  
  
  Making &lt;del&gt;fetch&lt;/del&gt; &lt;code&gt;api&lt;/code&gt; happen 💄
&lt;/h2&gt;

&lt;p&gt;Let’s revisit our previous example: fetching current job openings from the ReadMe API. The &lt;code&gt;fetch&lt;/code&gt; sample we looked at works perfectly fine, but what would an API call look like if the ReadMe API had a custom-tailored SDK? That’s where &lt;code&gt;api&lt;/code&gt; comes in.&lt;/p&gt;

&lt;p&gt;Here’s what &lt;a href="https://docs.readme.com/main/reference/getopenroles"&gt;the same API call&lt;/a&gt; looks like with a code snippet using the &lt;code&gt;api&lt;/code&gt;-generated SDK:&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;readme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOpenRoles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="o"&gt;=&amp;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="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;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how there is far less boilerplate code than the &lt;code&gt;fetch&lt;/code&gt; example, and much of the complexity is abstracted away. But the code sample does the exact same thing!&lt;/p&gt;

&lt;p&gt;Let’s break down the process of SDK generation, end to end:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The ReadMe API is documented using an OpenAPI definition. Within that definition, there is an &lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#operationObject"&gt;operation&lt;/a&gt; with an ID (i.e., &lt;code&gt;operationId&lt;/code&gt;) called &lt;code&gt;getOpenRoles&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Anytime an API user (in this case, someone that wishes to &lt;a href="https://readme.com/careers"&gt;apply for a job at ReadMe&lt;/a&gt;) runs the installation command to set up the SDK, &lt;code&gt;api&lt;/code&gt; takes the OpenAPI definition and generates an SDK that’s completely customized to the ReadMe API. It contains methods for every operation available in the API definition, as well as detailed descriptions of every request and response parameter.&lt;/li&gt;
&lt;li&gt;Once the installation is complete, the user imports the SDK into their code and starts writing. Thanks to the comprehensive TypeScript definitions produced by &lt;code&gt;api&lt;/code&gt;, code completion platforms like &lt;a href="https://code.visualstudio.com/docs/editor/intellisense"&gt;IntelliSense&lt;/a&gt; can guide them along as they write their snippet. They’re able to successfully hit the ReadMe API with a code snippet that’s a fraction of the length and complexity of the corresponding &lt;code&gt;fetch&lt;/code&gt; snippet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s the developer experience ethos we’re going for with &lt;code&gt;api&lt;/code&gt;: a readable, succinct code snippet that will get you to that first successful call in a jiffy. 🥜&lt;/p&gt;

&lt;h2&gt;
  
  
  Elevate your OpenAPI-powered DX with &lt;code&gt;api&lt;/code&gt; 📈
&lt;/h2&gt;

&lt;p&gt;One important design consideration as we built &lt;code&gt;api&lt;/code&gt; is that we wanted the SDK generation to be completely agnostic of your documentation platform, much like OpenAPI itself. Because &lt;code&gt;api&lt;/code&gt; is built on top of the OpenAPI specification, anybody that describes their API using OpenAPI can step up their DX with a custom SDK generated by &lt;code&gt;api&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are a few requirements to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org"&gt;Node.js&lt;/a&gt; and &lt;code&gt;npm&lt;/code&gt; installed&lt;/li&gt;
&lt;li&gt;A local directory with a &lt;code&gt;package.json&lt;/code&gt; file created&lt;/li&gt;
&lt;li&gt;An OpenAPI definition, either located in your directory or served from a URL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have everything in order, you can generate a custom-tailored SDK by running the following command from the root of your directory and following the prompts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx api &lt;span class="nb"&gt;install &lt;/span&gt;path-to-api-definition
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the SDK is generated, you’ll be writing succinct code snippets and getting to that successful first API call in no time 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Two birds 🐦, one incredible DX 🌟
&lt;/h2&gt;

&lt;p&gt;If there’s one thing that developers, technical writers, and pretty much &lt;strong&gt;anyone&lt;/strong&gt; enjoys, it’s being able to stretch your work so it goes further and saves you time. And that’s another reason why we’re so excited about &lt;code&gt;api&lt;/code&gt; and how it leverages the existing OpenAPI ecosystem to supercharge your users’ developer experience in ReadMe.&lt;/p&gt;

&lt;p&gt;Before &lt;code&gt;api&lt;/code&gt; came around, there were already many great ways that a comprehensive OpenAPI definition could set your API reference apart and further set your users up for success:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comprehensive security scheme definitions can help your users navigate one of the trickiest parts of getting started with an API: authentication!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ncsRyREp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/GS-A-Pages-in-Hub.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ncsRyREp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/GS-A-Pages-in-Hub.gif" alt='Helping Your Users Write Simpler API Calls With "api" ✍️' width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detailed request parameter descriptions and definitions (with default values, enums, and examples!) eliminate ambiguity and help your users understand exactly what data to send to your API:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nWZNjzdS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.33.10.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nWZNjzdS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.33.10.gif" alt='Helping Your Users Write Simpler API Calls With "api" ✍️' width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By capturing exhaustive response schemas and plenty of examples for every edge case, your users will know exactly what to expect from your API’s responses:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mhyb2SFN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.38.12.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mhyb2SFN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.38.12.gif" alt='Helping Your Users Write Simpler API Calls With "api" ✍️' width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But who said that a great developer experience should start and end with your docs? By investing in the above aspects of your OpenAPI definition, your users’ experience with your &lt;code&gt;api&lt;/code&gt;-generated SDK becomes even more magical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Thanks to that security scheme definition, passing in authentication credentials into your SDK is a one-liner:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;API_KEY&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;ul&gt;
&lt;li&gt;Because of those detailed request parameter definitions, passing in request parameters is a much more straightforward exercise that uses a fraction of the boilerplate code. And thanks to the power of TypeScript, users will get helpful cues about the parameters as they write in their editor:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gpSezXaJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.16.15.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gpSezXaJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.16.15.gif" alt='Helping Your Users Write Simpler API Calls With "api" ✍️' width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;And because of those exhaustive response schemas, users will also be able to leverage TypeScript hints to parse out response bodies:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3DLtyBge--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.28.15.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3DLtyBge--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.28.15.gif" alt='Helping Your Users Write Simpler API Calls With "api" ✍️' width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s already a tremendous amount of value in putting together a rock-solid OpenAPI definition. With &lt;code&gt;api&lt;/code&gt;, you get even more developer experience bang for your OpenAPI buck 💸&lt;/p&gt;

&lt;h2&gt;
  
  
  Available now in your ReadMe API reference 🦉
&lt;/h2&gt;

&lt;p&gt;If you have an API reference section that’s powered by ReadMe, your users can start writing better API calls with &lt;code&gt;api&lt;/code&gt; today. They can select &lt;strong&gt;Node&lt;/strong&gt; in the language selector and select the &lt;strong&gt;api&lt;/strong&gt; library to get started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gB94ilnb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.30.09%402x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gB94ilnb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.readme.com/content/images/2022/12/CleanShot-2022-12-14-at-13.30.09%402x.png" alt='Helping Your Users Write Simpler API Calls With "api" ✍️' width="800" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run into any issues, check out &lt;a href="https://api.readme.dev/docs"&gt;our docs&lt;/a&gt; and feel free to contact us at &lt;a href="https://www.notion.so/Plan-for-bin-readme-com-2ad33cb9b9aa431abdb2b1bc80028b9c"&gt;support@readme.io&lt;/a&gt;. &lt;code&gt;api&lt;/code&gt; is proudly open-source (shoutout to &lt;a href="https://twitter.com/sharpfarts"&gt;Jon&lt;/a&gt; for your all your hard work on this!) so feel free to open up an issue in &lt;a href="https://github.com/readmeio/api"&gt;the &lt;code&gt;api&lt;/code&gt; GitHub repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devrel</category>
      <category>openapi</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
