Salesforce, Python, SQL, & other ways to put your data where you need it

Need event music? 🎸

Live and recorded jazz, pop, and meditative music for your virtual conference / Zoom wedding / yoga class / private party with quality sound and a smooth technical experience

Writing a Swagger / OpenAPI schema for the YesNo API

24 May 2020 🔖 api salesforce integration intermediate tutorials
💬 EN

Table of Contents

In response to my “Salesforce Flow External Services” tutorial, reader “AMZ Cloud” asked, “How did you generate the ‘Service Schema Complete JSON’?”

The quick answer is: “by hand. With a lot of guessing and making mistakes.”

Learning YesNo’s API thoroughly

The first thing I did was visit YesNo’s API documentation at https://yesno.wtf/#api.

Screenshot of YesNo's API documentation

Having a little experience with HTTP-based APIs, I interpreted the documentation to mean that if I made an HTTP request using the “GET” method to one of the following four URLs:

  1. https://yesno.wtf/api
  2. https://yesno.wtf/api?force=yes
  3. https://yesno.wtf/api?force=no
  4. https://yesno.wtf/api?force=maybe

…then I would receive an HTTP response whose “body” was a concise piece of plaintext formatted in the JSON punctuation standard, indicating values for 3 “keys”:

  1. answer
    • (always a values of “yes”, “no”, or “maybe” – randomized if I visited the first URL possibility; fixed if I visited any of the “force=” URL possibilities)
  2. forced
    • (always a value of “false” if I visited the first URL possibility; always a value of “true” if I visited any of the “force=” URL possibilities)
  3. image
    • (always a URL to a file starting in https://yesno.wtf/ and ending in .gif)

Now that I personally understood everything about YesNo that I could possibly want to explain to my Flow, I needed to figure out how to to write it down according to “Swagger” / “OpenAPI 2.0” standards for “schemas.”


What is a schema?

  • Q: What’s a schema?
  • A: In this context, a “schema” is a file that:
    • is plain text
    • is formatted in a punctuation standard that makes it easy for a computer to read and interpret structure from (e.g. JSON or YAML)
    • describes where a given HTTP “REST”-flavored API lives on the internet
    • describes what HTTP requests you’re allowed to make to the API’s “endpoints
    • describes what kinds of HTTP responses you should expect in return from various requests to the API’s endpoints

YAML

To write my schema, I used online editor tools provided by SmartBear.

One thing to know about SmartBear’s editor tools is that they make you write your “schema” in a punctuation standard called “YAML.” We haven’t talked about YAML on the site before. Luckily, it’s not too difficult to guess your way around.

  • Like CSV and XML and JSON, YAML is a punctuation standard for formatting the context of plain-text files so that computers can interpret the contents of the file as “data” according to a human’s intent.
  • YAML is closer to XML and JSON than it is to CSV, because like XML and JSON, it’s optimized for holding “list-of-list”-shaped data. Therefore, just as XML and JSON are pretty interchangeable with each other, conceptually, YAML is pretty interchangeable with both of them – so much so that we’ll finish this tutorial by clicking a “Convert and save as JSON” button in our schema editor.
  • Unlike XML or JSON, though, whitespacing and line breaks are part of the YAML punctuation standard.

Defining a schema in SwaggerHub

[[[TO DO:]]] WRITE ME!

Set up an account

[[[TO DO:]]] WRITE ME


Create a new Schema

From within your SwaggerHub “hub” at https://app.swaggerhub.com/home, click “Create New API.”

I believe it was somewhere in the middle of the page before I had created any;

Screenshot of creating a new schema in SmartBear's Swagger Hub

In the dialog box that pops up, enter the following and click Save

  • OpenAPI version: 2.0
  • Template: None
  • Name: YesNo
    • (or whatever makes sense to you for recordkeeping within your “hub” of schemas stored in SmartBear’s service – you’ll see in subsequent screenshots that I had to make it “YesNoTutorial” because I’d already used up “YesNo” on a finished product that I hyperlinked to in other discussions)
  • Version: 1.0.0
    • (or whatever makes sense to you – this will become part of the data within your schema)
  • Title: YesNo
    • (or whatever makes sense to you – this will become part of the data within your schema)
  • Description: This is a sample YesNo server.
    • (or whatever makes sense to you – this will become part of the data within your schema)

Screenshot of creating a new schema in SmartBear's Swagger Hub

Ta-da: the beginnings of your first schema

You will be taken to a URL of the format https://app.swaggerhub.com/apis/YOUR_SWAGGERHUB_USERNAME/YOUR_PROJECT_NAME/YOUR_VERSION_NUMBER, and the code editor will read as follows:

swagger: '2.0'
info:
  version: '1.0.0'
  title: 'YesNo'
  description: 'This is a sample YesNo server.'
paths: {}
# Added by API Auto Mocking Plugin
host: virtserver.swaggerhub.com
basePath: /kswaggerhub/YesNoTutorial/1.0.0
schemes:
 - https

Screenshot of a "bare" schema in SwaggerHub

See how “version” and “title” and “description” are considered sub-properties of a key called “info” in the second line of the YAML-formatted file? As promised, the values you typed into the “new schema” window are here. Edit them here and click “Save” above the central code-editing panel if you’ve changed your mind about what you’d like them to say. (Although note that editing the version number will change your “Save” button into a “Create new version” button, since SwaggerHub has to generate a new editing URL for you when you change the version number.) Note that if you change these, your previewer at right will keep up with the changes you make in the center panel.

SwaggerHub also added a few extra pieces of data to the schema for us:

  • It gave the file a “swagger” property of 2.0, as specified in “OpenAPI version” while creating the file
  • It gave the file a “schemes” property containing a 1-item list of acceptable internet communication standards – in this case, just “secure HTTP,” or https. That’s fine – YesNo’s URL includes an “s” in the “https://...,” so let’s stick with that.
  • It gave the file “host” and “basePath” properties saying where on the internet the API “lives.”
    • We’ll have to update this to tell it that the host is yesno.wtf, not virtserver.swaggerhub.com and get rid of basepath altogether – but at the last minute, after we’re done testing, because SwaggerHub will just keep un-doing our work every time we save until then.

Add “/api” as an “endpoint” in “tags”

YesNo only has one “endpoint” in its whole API – the URL that ends in “/api” – so we’ll only have one “endpoint” to specify in a part of the Swagger / OpenAPI 2.0 standard under a property of the document called “tags”.

Copy and paste the following code into the bottom of your central YAML editing panel and click the blue “Save” button above the panel (it will turn gray once you’ve saved your work):

tags:
  - name: api
    description: The only endpoint YesNo offers
    externalDocs:
      description: Find out more
      url: 'https://yesno.wtf/#api'

Screenshot of our SwaggerHub schema after adding a tag


Define a “YesNoMaybe” as shorthand

We have work to do further specifying how “/api” works over at YesNo, but before we do, we’re going to take a moment to specify what kind of structure to expect in the “response body” that arises from making a request to https://yesno.wtf/api.

We’ll call this specification YesNoMaybe, which will serve as a nice shorthand when we get around to specifying how “/api” works.

Copy and paste the following text into the end of your schema, making sure that your cursor was at the far left side of the editor, not indented, when you do, and save your work:

definitions:
  YesNoMaybe:
    type: object
    required:
      - answer
      - forced
      - image
    properties:
      answer:
        type: string
        description: 'yes, no, or maybe'
        example: 'yes'
        enum:
          - 'yes'
          - 'no'
          - 'maybe'
      forced:
        type: boolean
        description: Did you force the answer with a query parameter?
        example: false
      image:
        type: string
        description: The URL to a random GIF of a celebrity expressing the answer
        example: 'https://yesno.wtf/assets/no/13-755222c98795431aa2e7d453ab1e75a1.gif'

Screenshot of our SwaggerHub schema after adding a definition

As you can see, our YAML-formatted “schema” file now has a new property named “definitions”, which contains a 1-item list of sub-properties.

That sub-property is called “YesNoMaybe” because I thought that’d make a good name.

YesNoMaybe” itself has 3 sub-properties, called “type”, “required”, and “properties”.

We set the value of the property “type” gets set to “object” to indicate that the shorthand “YesNoMaybe” is shorthand for structured data. (We’ll use “required” and “properties” to indicate just how it’s structured.)

Remember, HTTP requests to https://yesno.wtf/api and its variants all return an HTTP response whose “body” that is a concise piece of plaintext formatted in the JSON punctuation standard, indicating values for 3 “keys”:

  1. answer
    • (always a values of “yes”, “no”, or “maybe” – randomized if I visited the first URL possibility; fixed if I visited any of the “force=” URL possibilities)
  2. forced
    • (always a value of “false” if I visited the first URL possibility; always a value of “true” if I visited any of the “force=” URL possibilities)
  3. image
    • (always a URL to a file starting in https://yesno.wtf/ and ending in .gif)

Screenshot of YesNo's API documentation

The fact that YesNo’s API always includes each of these 3 “keys” in the JSON-formatted body of its response means that we can tell our “schema” that they are to be expected. Hence listing them under “required”.

Finally, as sub-properties to “properties”, we’ll list 3 more things called “answer,” “forced”, and “image.”

Each of these will have 3 sub-properties of “type(used by computers like Salesforce Flow to determine what “data type” to interpret a piece of the response as – “string” is a programmer-ey way of saying “plain text”)description(free-form hints for human eyes) and “example(also geared at human eyes). “answer” will also have a 4th sub-property of “enum” to specify that its possible responses are limited to “yes”, “no”, and “maybe(potentially used by computers like Salesforce Flow, if a user interface wanted to get fancy and render picklists for data entry and such).

Although “forced” has a limited set of possible values, it doesn’t need an “enum” sub-property because “true” and “false” as the only 2 options are implied by saying its data type is “Boolean.”

Note that in the “example” and “enum” properties, “string”-typed values have little single quotes (') around them. Make sure you get that right when typing up your schema.


Flesh out the “/api” as an “endpoint” in “paths”

Now that we’ve defined a “YesNoMaybe,” let’s finish explaining with our schema how “https://yesno.wtf/api” works.

Personally, I like to have my “paths” block of my schema between my “tags” and “definitions block, so put an empty line between the last line of the “tags” block (“url: 'https://yesno.wtf/#api'“) of YAML-formatted text and the first line of the “**definitions**” block of YAML-formatted text, making sure your cursor is at left, not indented.

Copy and paste in the following code:

paths:
  /api:
    get:
      tags:
        - api
      summary: 'Seek a random yes, no, or maybe'
      operationId: seekAnswer
      produces:
        - application/json
      parameters:
        - name: force
          in: query
          description: Use this to force one of the 3 valid answers
          required: false
          type: string
          enum:
            - 'yes'
            - 'no'
            - maybe
      responses:
        '200':
          description: successful operation
          schema:
            $ref: '#/definitions/YesNoMaybe'

If you get a “duplicated mapping key” error at the bottom of your editor in a red box, delete the line of YAML-formatted text near the top that SwaggerHub had put in between “description: 'This is a sample YesNo server.' and # Added by API Auto Mocking Plugin that reads:

paths: {}

(Sorry, I forgot to take that out earlier.)

Save your work.

Screenshot of our SwaggerHub schema after adding a definition

As you can see, our YAML-formatted “schema” file now has a new property named “paths”, which contains a 1-item list of sub-properties.

That sub-property is called “/api” because that’s the part of the URL to the API that comes between the “base path” (in this case, https://yesno.wtf) and the optional question mark indicating the beginning of “query parameters.”

/api” itself has just 1 sub-property, called “get”, because the “https://yesno.wtf/api” endpoint of the YesNo API only responds to the “GET” HTTP method. We don’t need to bother explaining what the API might do in response to any other HTTP methods.

get” has 6 sub-properties:

  1. tags
  2. summary
    • Here we type some human-readable text, like 'Seek a random yes, no, or maybe', to tell humans what to expect when performing a GET HTTP request against https://yesno.wtf/api.
  3. operationId
  4. produces
    • We know (because we’ve studied JSON and recognize it on sight when reading the YesNo API documentation) that the entire body of an HTTP response to a GET HTTP request against https://yesno.wtf/api is formatted according to the JSON punctuation standard. The code to indicate that in this case is “application/json”.
    • I’m not sure yet exactly why “application/json is a 1-item list under “produces” rather than a simple single value like you see after “summary.” But it is.
  5. parameters
    • Let’s come back to this in a minute. It’s long.
  6. responses
    • Here we make a list of all possible HTTP response status codes that performing a GET HTTP request against https://yesno.wtf/api might return.
    • Well, maybe not all the ones it might return. But all the ones we care to teach our Flow to anticipate.
    • I tried my best to break https://yesno.wtf/api – like visiting https://yesno.wtf/api?force=HelloWorld – and couldn’t ever get it to return anything but 200 (success) with well-formatted (although sometimes unexpected in terms of its contents) data – so I think it’s safe to only specify what happens in response to 200.
    • We make up a human-friendly “description like “successful operation(it’s pretty standard to match what the 200 code is actually officially named in this part).
    • We also add a “schema” sub-property and give it a value of “$ref: '#/definitions/YesNoMaybe'” to say, “Computer – go see YesNoMaybe, below, if you really want to know what the response will look like.”

Phew! Just one thing left: let’s dig into “parameters.”

Good question. I wrote it by hand, using an online tool to facilitate the effort.

I think it might’ve been SmartBear’s “Swagger Hub,” but that’s now behind a login-wall rather than out in the open, so I’m not 100% sure. To get onto its free tier, sign up, ignore the prompt to do a 14-day trial, visit pricing, click “Start Now” in the free tier, and log in again. That should take you to https://app.swaggerhub.com/home. Create a new “API” off their “pet store” template and cut/paste/edit pieces of it around until you think it represents the API you’re working with.

Note that you use SwaggerHub in a text-editing format called YAML. Like CSV and XML and JSON, YAML is a set of punctuation standards that let you give structure to plaintext data. Like CSV files, things like spacing and line breaks can be part of the meaningful, structural punctuation. But like XML and JSON, YAML is meant to represent more complex data structures than CSV is meant to represent. I hope that helps you get started guessing how you might edit it.

When you have something you’re happy with … okay, shoot, where’s the “export to JSON” button …

Ah! You know what? I did all my guessing-and-editing at SmartBear’s login-free editor https://editor.swagger.io/. But I like the one behind the login-wall now that I see it, for development work. The nav panel on the login-wall one helps you jump around the code editor more easily.

You can see the YAML version of my “Swagger / OpenAPI 2.0”-formatted schema for YesNo here, if it helps to have that as well as the “pet store” example. Remember, you can find sample output from the YesNo API endpoint here or here and its documentation here.

When you’re happy with your YAML specification and feel like the preview structure at left and right in the behind-the-login-wall editor represent how your real-world API actually behaves (or at least how the part of it that you want to expose to Flow behaves), copy and paste your YAML into https://editor.swagger.io/ and click “File” - “Convert and save as JSON”.

That’s the text you’ll need to paste into Salesforce’s “Service Schema Complete JSON” box.

Good luck!

--- ---