3 Example OpenAPI Definitions

3 Example OpenAPI Definitions

Posted in

For many years, whenever anyone wanted to learn about APIs, they’d inevitably encounter the Petstore API. Created by Swagger, Petstore API serves as a fully working template so you can see an API in action. It’s like Example.com but for API definitions. It lets you test out authorization tokens, try out different endpoints, and interact with a database. You can see payloads returned as JSON files and try out basic CRUD commands.

Petstore API isn’t the only API template in town, though. APIs have evolved to do a lot more than update a database. APIs can power products and services all on their own, for example, as you’ll see with the Museum API. Others interact with multiple systems, creating a rough approximation of something like a travel app, which the Train Travel API does well.

Below, we’ll examine all three OpenAPI API descriptions in depth to give you a better idea of what they have in common, how they’re different, and how things have changed since Swagger first introduced the PetStore API.

PetStore API

The PetStore API is best known as a way to practice working with and implementing REST and executing the standard HTTP commands that drive most APIs.

For best results, open the PetStore API example in a new tab. You might want to open the source code in its own tab, as well. We’re mainly interested in the openapi.yaml file.

Looking at these two examples will help give you a better idea of how an OpenAPI description manifests in real life. As you can see from the OpenAPI description, this description was created using the OpenAPI 3.0.2 description.

After some general housekeeping, the API description and its origins are described, and the different sections that make up the PetStore API are explained. It then goes on to specify the actions that can be performed in each section. The Pet section allows users to upload an image of a pet using POST, for example. Following the openapi.yaml is an excellent blueprint for learning how to think about API design.

PetStore can also give you hints on how to code a REST API if you take the time to pour over the code. If you scroll down to the bottom of Petstore.Swagger.io, you’ll see the section for Models. Parsing through each of the models will show you what variables each model is expecting, for instance. The petId parameter only accepts an integer, as specified by integer($int64). The name parameter expects a string, though, as specified in the API description.

The PetStore API has its critics, though. Some take issue with the lack of resources being pluralized, for example. The first tag is Pet, for example, when it should be pets. Once you start to notice the errors, others start to stand out. The login and logout functions are less than obvious, as they’re nested under the USER endpoint, which arguably also should be pluralized.

Based on criticisms some developers have for the PetStore API, it’s clear that it’s lacking in real-world usefulness. It’s useful as a general Hello World but it’s lacking as an effective API design training manual.

Train Travel API

Now let’s turn our attention to the first OpenAPI definition to replace the PetStore API. The Train Travel API was created to address some of the API design concerns mentioned above. The Train Travel API is also contained in a single openapi.yaml file, making it slightly more efficient for use in mockups and documentation.

The Train Travel API is based on real-world examples, making it slightly more useful and practical than the PetStore API. It’s also based on real needs, as the author wanted a way to search for trains that would accept bicycles or pets. The BookingPayments function is based on the actual Stripe Payments API. Spending some time with the mock-up will give the user a pretty good idea of how to implement accepting different kinds of payments, whether they come from a credit or debit card or a bank account.

The Train Travel API uses appropriate web standards when possible and draft standards otherwise. It also uses standard HTTP codes, which makes its payloads easily understandable and consumable by tools like API documentation generators. Some of the Train Travel API’s implementation is particularly elegant, though, like their choice to contain results using a Wrapper-Collection instead of returning raw JSON. This structure allows the user to easily add simple HATEOAS controls or pagination controls. These are then expanded using allOf for responses instead of having to define that format repetitively.

The Train Travel API was explicitly created for OpenAPI 3.1, as opposed to PetStore API, which was written in OpenAPI 2.0 and later converted into OpenAPI 3.0. This means the Train Travel API works better with WebHooks than the PetStore API. It also uses unevaluatedProperties instead of additionalProperties, which means it understands the use of allOf in subschemas, so no properties get lost accidentally. OpenAPI 3.1 also supports Property Examples, which help properties make more sense in API documentation generators.

The Train Travel API is a much better model of current API best practices. It’s also easier to work with in demos, thanks to its efficient .yaml structure. If you’re looking to learn or demonstrate current API principles, you’ll be much better off working with the Train Travel API than PetStore.

Museum API

Created by Redocly, the Museum OpenAPI definition is another API definition written to take advantage of OpenAPI 3.1. It operates similarly to the Train Travel API, performing multiple functions that simulate a real museum API. These include everything from creating special events to retrieving museum hours. These are primarily accomplished using OpenAPI tags, which is one of the Museum API’s most striking features. OpenAPI tags dictate what endpoint a resource belongs to. The tag section also lets you include information about each tag. The Museum API tag section looks like this:

tags:
  - name: Operations
    description: Operational information about the museum.
  - name: Events
    description: Special events hosted by the Museum.
  - name: Tickets
    description: Museum tickets for general entrance or special events.

Each endpoint also contains a section for the tags that pertain to it.

 /special-events:
    post:
      summary: Create special events
      description: Creates a new special event for the museum.
      operationId: createSpecialEvent
      tags:
        - Events

Best of all, many documentation tools use tags as a way to group navigation. They can also be customized to return additional information using the x-displayName variable. The x-tagGroups can be used to group tags together, too, which is convenient for navigating and organizing large APIs.

Final Thoughts on OpenAPI Definitions

While the PetStore API may not deserve the ire it gets from a lot of the API development community, it doesn’t fully represent modern API design. As we have seen, it can be useful for visualizing API design by digging into its .yaml file and studying its structure. However, it doesn’t fully take advantage of the OpenAPI 3.0 specification or follow all of today’s best practices for API design. If you’re serious about learning modern API design, you might do better to study the Train Travel API and then supplement it with the Museum API.

You can’t ever have too many examples of API design done right. If you’re looking for more examples of OpenAPI 3.1 best practices to model your APIs after, you can also check out Speakeasy’s OpenAPI 3.1 Reference. It’s incredibly clean, sleek, and easy to understand. Best of all, the documentation and sample code are presented side-by-side — no tabbing required! Seeing a description of the different OpenAPI 3.1 components in plain language right next to the .yaml code is a huge help for taking an API description out of the realm of abstraction and into practical reality.