How to Create an Extension for Your Open API Specification
Tags: development, api, oas
Published: 2021-01-11 13:45:53

---
title: How to Create an Extension for Your Open API Specification
published: true
description: What do you do when you need something that OAS doesn't handle? Create your own extension, of course!
tags: 
  - development
  - api
  - oas
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/6eablmv5g46l3e3w1itg.jpg
canonical_url: https://www.readysetcloud.io/blog/allen.helton/how-to-create-an-extension-for-oas/
---

2021 is going to be [the year of the API](https://www.readysetcloud.io/blog/allen.helton/this-is-where-your-focus-should-be-in-tech-2021). We're going to focus on converging on a standard, providing public APIs, and fast-forwarding our rate of innovation.

With our focus on API design with [Open API Spec](https://www.openapis.org) (OAS), we are going to run into scenarios where some automation is needed but not currently possible. Maybe this automation is custom to you and your company or maybe it's a service you want to provide to developers everywhere. How do we go about implementing this automation? Through the use of an *extension*.

An [extension](https://swagger.io/docs/specification/openapi-extensions/) is a simple way to add functionality to your OAS. You add some attributes to your file, implement a handler to read it and take an action, and reap the benefits of automation!

Instead of explaining what an extension is conceptually, today I am going to walk you through the creation of a brand new one. We are going to make an extension that enhaces the [Postman contract test generator](https://www.readysetcloud.io/blog/allen.helton/dynamic-test-generation-with-oas) we made a while back.

The test generator is great, but it relies on seeded data to work properly. This means that prior to execution, specific data has to be in the database so the tests can use it. 

This causes a little bit of a problem because it increases the barrier to entry. It would be nice if there was a way to use the data generated from the tests in the tests themselves. Meaning when the generator does a **POST** to create a new entity, it can use the `id` of that entity in subsequent requests to **GET** or update with a **PUT**.

Let's walk through end-to-end how to solve this problem by building an extension.

![Photo by [Kayla Farmer](https://unsplash.com/@imagesbykayla?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/search?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)](https://readysetcloud.s3.amazonaws.com/oasExtension_6.jpg)
*Photo by [Kayla Farmer](https://unsplash.com/@imagesbykayla?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/search?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)*

# Identify the Business Problem
In our example, we want to be able to use values created by the generated tests in subsequent generated tests. The business problem can be stated:

> I want to use dynamic variables in my tests so I do not have to rely on seeded data.

Once you identify the business problem, you want to come up with a plan on how to best solve it. In our case, that involves using values created by the test generator in other requests. 

To do this, we must be able to save response values and use them in other requests. With this in mind, we should be able to start the next step, *defining the schema*.

![Image by [Free-Photos](https://pixabay.com/photos/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1149962) from [Pixabay](https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1149962)](https://readysetcloud.s3.amazonaws.com/oasExtension_7.jpg)
*Image by [Free-Photos](https://pixabay.com/photos/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1149962) from [Pixabay](https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1149962)*

# Define the Extension Schema
To use dynamic variables, we need to know when to *save* and *consume* them. 

## Saving Dynamic Variables
To save a variable from a dynamic test, we need to know when and where to grab the value from a response. In our example, certain response codes on specific endpoints will produce the values we want. 

There are two pieces of data we need to identify: **name of the variable** and **where to find it**. We also need to let our handler know that we want to save a variable.

With this in mind, the following schema supports our business need:

```
x-postman-variables:
  - type: save
    name: myVariable
    path: .id
```

With this schema, `type` will tell the handler that we want to save the variable. `name` is going to be the name of the variable in Postman. `path` is going to be the json path to the property in the response. You can see that we also made the extension an array in case we need to store multiple values from a single response.

We can now add the extension into our Open API spec under a specific response for a particular endpoint. We can reference the [Gopher Holes Unlimited](https://github.com/allenheltondev/gopher-holes-unlimited/) example API spec.

![Example usage of the extension in the Gopher Holes Unlimited OAS](https://readysetcloud.s3.amazonaws.com/oasExtension_4.jpg)
*Example usage of the extension in the Gopher Holes Unlimited OAS*

## Consuming Dynamic Variables
Now that we have our variables properly saved, it all comes down to using them in subsequent tests. With Open API Spec, we are able to define parameters used in our requests. 

Since we want to use a variable in subsequent requests, we should be sure to enrich our OAS `parameters` with the extension. Every time we use the parameter, the test generator will pull the current Postman variable value and use it in the test.

Consuming the values are significantly easier than saving because we just need to know the variable name. Which leads us to a schema of:

```
x-postman-variables:
  - type: load
    name: myVariable
```

With this schema, `type` says we are loading the value, and `name` tells our handler which variable we want. With this, we have our extension definition defined!

Adding the example into our OAS will look like:

![Example usage of consuming a variable in Gopher Holes Unlimited](https://readysetcloud.s3.amazonaws.com/oasExtension_5.jpg)
*Example usage of consuming a variable in Gopher Holes Unlimited*

# Implement the Handler
With the schema of the extension defined, it's now time to write the code that interprets the values. After all, an OAS document is just a definition. It doesn't actually *do* anything. 

Our extension is meant for usage exclusively with [Postman](https://www.postman.com/), so our handler is going to be written from within the pre-request and test scripts in the [Contract Test Generator](https://github.com/allenheltondev/postman-contract-test-generator) collection.

## Saving Extension Variables
The contract test generator already looks at allowed responses for each method on every endpoint. To implement the logic for our extension, we are going to be tying into that existing functionality. 

When we are saving the responses for each method, the handler will look for the extension and save off the variables to a `variables` property on the test.

![Save variable handler logic reading from our extension](https://readysetcloud.s3.amazonaws.com/oasExtension_1.jpg)
*'Save variable' handler logic reading from our extension*

You can see that it is saving the variables that have the `save` type defined.

## Persisting Response Values As Variables
Now it's time for the actual work: taking the value from the response at the defined path and saving it to a Postman collection variable. 

Again, it's not a terribly difficult code snippet, it just uses what we saved off from step 1.

![Persisting the response value into a Postman variable](https://readysetcloud.s3.amazonaws.com/oasExtension_2.jpg)
*Persisting the response value into a Postman variable*

Looking at what we've done, you can see that we are pathing to the property we want piece by piece. If we find it in the response, the value is saved to a collection variable. If no value is found, an assertion fails letting our tests know something went wrong.

## Using Response Values
The last piece to our puzzle is to load the value we just saved whenever it is needed. A function exists already in the test generator that replaces parameters with a provided example from the OAS. 

With our extension, we will modify that logic to use the value from the collection variable if necessary. If we don't find a value in the collection variable, we fall back to the example.

![Loading persisted variables into usable parameters](https://readysetcloud.s3.amazonaws.com/oasExtension_3.jpg)
*Loading persisted variables into usable parameters*

You can see here that the code is looking for our `x-postman-variables` extension for any parameters with the `load` save type. If there is one, it will use the collection variable. If not, it pulls from the example. 

The code has also been updated for query parameters and headers.

# Try it Out
That's it! With the implementation of the handler, everything should just work. 

Building an extension for your Open API Spec is as simple as that. Just three easy steps:

1. Identify the problem
2. Define the schema
3. Implement the handler

Of course if you want your extension to be used by other people, you will need to document the usage (like what I'm doing here!).

I hope you are inspired to make an extension of your own. The possibilities are limitless. The handler doesn't even have to be in Postman! It could be a script in your [CI pipeline](https://www.readysetcloud.io/blog/allen.helton/how-to-build-a-ci-cd-pipeline-in-aws-in-5-minutes-and-58-seconds-4de156477042), a custom resource in your AWS CloudFormation script, or even a little on-demand desktop app. 

Any way you go, you're bound to make the lives easier of your entire development team. 

So go out there and build some extensions! And if you haven't already, try out the [test generator](https://github.com/allenheltondev/postman-contract-test-generator), it's better than ever!