OpenAPIを元にしたPostmanコレクションの作成・更新を自動化する方法

# はじめに

これは、REST APIの仕様書としてOpenAPI Specification（以下、OAS）を管理していて、そのOASを元にPostmanコレクションを作成・更新したい思っている人向けの記事です。

PostmanはGUIベースのアプリケーションであり、このGUIからOASをインポートして新規のコレクションを作成できます。作成後は、GUIを介してコレクションを直接更新ができます。しかし、この手動でのGUIを通したコレクションの作成・更新だけでなく、自動化したいニーズもあるかと思います。たとえば、GitHubなどのコード管理システムでOASファイルを管理しているシナリオでは、以下のような手順でのコレクションの作成・更新が考えられます：

1. コード管理システム（GitHubなど）で管理しているOASファイルを更新する
2. OASファイルの更新をトリガーにCI/CDワークフロー（GitHub Actionsなど）が実行され、その中でOASを元にコレクションを自動的に作成・更新する

本記事では、このようなシナリオを実現するために、Postmanが提供するOSSライブラリであるopenapi-to-postmanと、Postmanクラウド上のPostmanアセットを管理・操作できるPostman APIを活用する方法を紹介します。

## openapi-to-postmanとは？

Postmanが提供するOSSで、OpenAPI 3.0、3.1仕様を [Postman コレクションv2 形式](https://schema.postman.com/collection/json/v2.1.0/draft-07/docs/index.html)に変換するためのCLIやライブラリを提供します。

https://github.com/postmanlabs/openapi-to-postman

以下、openapi-to-postmanを活用してOASファイル `oas.yaml`からPostmanコレクションデータファイルを生成する例です。

CLIで実行する例: 

```bash
# Postmanコレクションデータファイル、collection.jsonを出力
openapi2postmanv2 -s oas.yaml -o collection.json -p -O folderStrategy=Tags,includeAuthInfoInExample=false
```

Node.jsモジュールとして実行する例:

```jsx
const fs = require('fs'),
  Converter = require('openapi-to-postmanv2'),
  openapiData = fs.readFileSync('oas.yaml', {encoding: 'UTF8'});

Converter.convert({ type: 'string', data: openapiData },
  {}, (err, conversionResult) => {
    if (!conversionResult.result) {
      console.log('Could not convert', conversionResult.reason);
    }
    else {
      console.log('The collection object is: ', conversionResult.output[0].data);
    }
  }
);
```

## Postman APIとは？

[Postman API](https://documenter.getpostman.com/view/12959542/UV5XjJV8)は、Postmanクラウド上のPostmanデータを管理・操作するためのAPIです。Postman APIを使用することで、Postmanデータをプログラムで簡単に操作し、開発ツールチェーンに統合することができます。

Postmanデータには、Postmanワークスペース、コレクション、環境、モニター、モックサーバーなど、Postmanアプリで操作する様々なデータが含まれます。Postman APIを活用したPostmanデータのCURD処理については、次の記事を参照ください。

https://qiita.com/yokawasa/items/abba626c305de10126a0

実際にPostman APIを試してみる際は、パブリックに公開されている[Postman API用コレクション](https://www.postman.com/postman/workspace/postman-public-workspace/documentation/12959542-c8142d51-e97c-46b6-bd77-52bb66712c9a
)があるので、それをフォークしてご自身のワークスペースでお試しいただくのが良いでしょう。

コレクション更新用APIリクエスト設定ページのイメージ：

![Screenshot_2024-05-13_at_1.36.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/0fd29d36-e249-29b2-0188-085ae05ca1c7.png)

# OpenAPIを元にコレクションを新規作成

それでは、本題であるOASを元にPostmanコレクションを新規作成する手順をご紹介します。手順は以下の2つのステップになります。

1. openapi2postmanを使用してOASデータからPostman コレクションデータを生成
2. 生成したコレクションデータを元に、Postman APIを使用して新規のコレクションを作成

なお、本記事ではOASのサンプルとして[Petstore OpenAPI Spec 3.0](https://petstore3.swagger.io/api/v3/openapi.json)を使って説明をすすめます。

## (1) OASデータからPostman コレクションデータを生成

まずは、サンプルの[OASファイル](https://petstore3.swagger.io/api/v3/openapi.json)を`oas.json`という名前でダウンロードします。

```
curl -o oas.json https://petstore3.swagger.io/api/v3/openapi.json
```

つづいて、openapi2postmanツールで、`oas.json`を元にPostmanコレクション（`collection.json`）を生成します。

```bash
# install openapi2postman (もしインストールまだなら)
# ここではglobalにインストール。ローカルならば -gオプションはずす
npm install -g openapi-to-postmanv2

# openapi2postmanでoas.jsonからPostmanコレクション（collection.json）を生成
openapi2postmanv2 -s ./oas.json \
    -o collection.json -p \
    -O folderStrategy=Tags,parametersResolution=Example,enableOptionalParameters=false
```

引数の説明

- `-s <file>` (または `--spec <file>`): インプットするOASファイルのパス
- `-o <file>` (または `--output <file>`): 出力されるPostmanコレクションファイルのパス
- `-p` (または `--pretty`): ファイルへの書き込みをプリティに(整形)する
- `-O <options>` (または `--options <options>`): OASからPostmanコレクション生成のためのオプション。ここでは、下記の内容で生成オプションを指定。詳細は[こちらのページ](https://github.com/postmanlabs/openapi-to-postman/blob/develop/OPTIONS.md)を参照ください

OASからPostmanコレクション生成のためのオプション

- folderStrategy=Tags: OASのパスに従ってPostmanコレクションのフォルダを作成するか、タグに従ってフォルダを作成するかを選択。`Paths`または`Tags`が選択可能で、ここでは`Tags`を選択
- parametersResolution=Example: OASの[schema](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.2.md#schemaObject)に基づいてリクエストパラメーターを生成するか、スキーマの[example](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.2.md#exampleObject)例に基づいてパラメーターを生成するかを選択。`Schema`か`Example`が選択可能で、ここでは`Example`を選択
- enableOptionalParameters=false: OASで`required:true`で指定していないオプショナルなパラメーターはコレクションのAPIリクエスト設定のパラメーターで明示的にチェックなしにする（選択されていない状態にする）。デフォルトはtrueで、パラメーターが明示的にチェックされるようになる

:::note 
補足: openapi-to-postmanのバージョンと利用可能なオプションについて

openapi-to-postman (default v2)のバージョンが`4.22.0`もしくはそれ以下の場合、v1でのみサポートされるオプションを利用できたが、`4.23.0`以降のバージョンでは利用できなくなっているので注意が必要となります。例えば、`4.23.0`以降のバージョンでは利用できなくなったものに以下のオプションが挙げられます:

- collapseFolders
- optimizeConversion
- requestParametersResolution
- exampleParametersResolution

オプションに関する詳細は[こちらのページ](https://github.com/postmanlabs/openapi-to-postman/blob/develop/OPTIONS.md)を参照ください
:::

なお、上記の処理で得られるコレクションデータ(json)は次のようになります。

```json:collection.json
{
  "item": [
    {
      "name": "pet",
      "description": "Everything about your Pets",
      "item": [ "...内容省略..." ]
    },
    {
      "name": "store",
      "description": "Access to Petstore orders",
      "item": [ "...内容省略..." ]
    },
    {
      "name": "user",
      "description": "Operations about user",
      "item": [ "...内容省略..." ]
    }
  ],
  "event": [],
  "variable": [
    {
      "key": "baseUrl",
      "value": "/api/v3"
    }
  ],
  "info": {
    "_postman_id": "45badc05-a0d1-41dd-ab31-77d16c26e338",
    "name": "Swagger Petstore - OpenAPI 3.0",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "description": {
      "content": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)\n\nContact Support:\n Email: apiteam@swagger.io",
      "type": "text/plain"
    }
  }
}
```

## (2) 1で作成したコレクションデータを元にPostman APIを使って新規コレクションを作成

[Postman API](https://www.postman.com/postman/workspace/postman-public-workspace/collection/12959542-c8142d51-e97c-46b6-bd77-52bb66712c9a)の [コレクション作成API](https://www.postman.com/postman/workspace/postman-public-workspace/request/12959542-049042b8-447f-4f71-8b79-ae978cf40a04)を使って作成します。

- APIエンドポイント: `https://api.getpostman.com/collections`
- クエリパラメーター:  (任意)  `workspace=＜ワークスペースID＞`
    - ＜ワークスペースID＞: コレクションの作成先のワークスペースのID。ワークスペースIDの指定は任意であり、このクエリパラメーターを含めない場合、システムは `My Workspace`  にコレクションを作成します
- HTTPメソッド :  `POST`
- ヘッダー:   `X-API-Key`: `<Postman APIキー>`

上記で取得したコレクションデータの中身を [コレクション作成API](https://www.postman.com/postman/workspace/postman-public-workspace/request/12959542-049042b8-447f-4f71-8b79-ae978cf40a04)のリクエストボディに下記のフォーマットでセットします。

```json
{
  "collection": {
     "...(1)で取得したコレクションデータの中身..."
   }
}
```

今回サンプルとして使用したPetstoreコレクションのデータで新規作成する場合、リクエストボディは次のようになります。

```jsx
{
  "collection": {
    "item": [
      {
        "name": "pet",
        "description": "Everything about your Pets",
        "item": [...omit...]
      },
      {
        "name": "store",
        "description": "Access to Petstore orders",
        "item": [...omit...]
      },
      {
        "name": "user",
        "description": "Operations about user",
        "item": [...omit...]
      }
    ],
    "event": [],
    "variable": [
      {
        "key": "baseUrl",
        "value": "/api/v3"
      }
    ],
    "info": {
      "_postman_id": "45badc05-a0d1-41dd-ab31-77d16c26e338",
      "name": "Swagger Petstore - OpenAPI 3.0",
      "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
      "description": {
        "content": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)\n\nContact Support:\n Email: apiteam@swagger.io",
        "type": "text/plain"
      }
    }
  }
}

```

以下は、Node.jsでこのリクエストを送信するためのサンプルコードです。axiosライブラリを使用しています。

```jsx
const axios = require('axios');
let data = JSON.stringify({
  "collection": {"コレクションJSONデータ"}
});
let workspaceID = "ワークスペースID";
let config = {
  method: 'post',
  maxBodyLength: Infinity,
  url: 'https://api.getpostman.com/collections?workspace=' + workspaceID,
  headers: { 
    'Content-Type': 'application/json', 
    'X-API-Key': '<Postman APIキー文字列>'
  },
  data : data
};

axios.request(config)
.then((response) => {
  console.log(JSON.stringify(response.data));
})
.catch((error) => {
  console.log(error);
});

```

上記の内容のリクエスト送信が成功すれば、指定したワークスペースにコレクションが新規に作成されます。コレクションのサイズが大きければ大きいほど作成に時間がかかるのでご注意ください。

:::note 
💡 補足

OASを元にPostmanコレクションを新規作成するのに次の2つのPostmanAPIが活用できます：

- コレクション作成API ([POST - Create a collection](https://documenter.getpostman.com/view/12959542/UV5XjJV8#049042b8-447f-4f71-8b79-ae978cf40a04))
- インポートOpenAPI定義API ([POST - Import an OpenAPI definition](https://documenter.getpostman.com/view/12959542/UV5XjJV8#346e9bad-5d56-47db-9f4d-ba4ff8231e38))

本記事ではコレクション更新方法との統一感を加味してコレクション作成APIを活用してます

:::

# Postman APIを活用して既存のコレクションを更新

OASを元に既存のPostmanコレクションを更新する手順は、新規コレクション作成とのほぼ同じで、次の２ステップになります。

1. openapi2postmanを使用してOASデータからPostman コレクションデータを生成
2. 生成したコレクションデータを元に、Postman APIを使用して既存コレクションを更新

(1)はコレクション新規作成のと全く同じなので省略します。ここでは(2)のみ紹介します。

先に(1)で生成したコレクションデータを元に、[Postman API](https://www.postman.com/postman/workspace/postman-public-workspace/collection/12959542-c8142d51-e97c-46b6-bd77-52bb66712c9a)の [コレクション更新API](https://www.postman.com/postman/workspace/postman-public-workspace/request/12959542-bc8b292b-ffbb-4c67-a2a1-2fc416e2aef8)で、既存のコレクションを更新します。

- APIエンドポイント: `https://api.getpostman.com/collections/＜コレクションID＞`
    - ＜コレクションID＞: 更新対象である既存のコレクションID
- HTTPメソッド : `PUT`
- ヘッダー:   `X-API-Key`: `<Postman APIキー>`

リクエストボディはコレクション新規作成APIと同じで次のフォーマットになります。

```json
{
  "collection": {
     "...(1)で取得したコレクションデータの中身..."
   }
}
```

以下は、Node.jsでこのリクエストを送信するためのサンプルコードです。


```jsx
const axios = require('axios');
let data = JSON.stringify({
  "collection": {"コレクションJSONデータ"}
});
let collectionID = "コレクションID";
let config = {
  method: 'put',
  maxBodyLength: Infinity,
  url: 'https://api.getpostman.com/collections/' + collectionID,
  headers: { 
    'Content-Type': 'application/json', 
    'X-API-Key': '<Postman APIキー文字列>'
  },
  data : data
};

axios.request(config)
.then((response) => {
  console.log(JSON.stringify(response.data));
})
.catch((error) => {
  console.log(error);
});
```

上記のリクエスト送信が成功すれば、指定した既存のコレクションが更新されます。コレクションのサイズが大きければ大きいほど更新に時間がかかるのでご注意ください。

# おわりに

本記事では、openapi-to-postmanとPostman APIを活用して、OASを元にPostmanコレクションの作成・更新を自動化する方法を紹介しました。これまで何度かOASを元にPostmanコレクションの作成・更新を自動化する方法について質問をいただいたので記事にまとめてみました😁

なお、OASを元にしたPostmanコレクション作成・更新において、新しい機能要望や既存の機能に対して変更要望などがでてくるかもしれません。今回紹介した[openapi-to-postman](https://github.com/postmanlabs/openapi-to-postman)はOSSですし、[OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md)と[Postmanコレクション](https://schema.postman.com/collection/json/v2.1.0/draft-07/docs/index.html)のフォーマットは共に標準フォーマットとして公開されています。よって、その場合は、ご自分で改良や機能追加も可能ですし、興味があれば好みのツールを作ることも可能かと思います。ぜひ挑戦してみてください。

# APPENDIX

## PostmanアプリでOpenAPIを元にコレクションを新規作成（インポート）

PostmanアプリでOpenAPIからコレクションを作成する方法を紹介します。

既存のOpenAPI 3.0と3.1の定義（OpenAPI仕様）をPostmanにインポートできます。PostmanはYAMLとJSONの両方のフォーマットをサポートしてます。

API定義をPostmanにインポートするには、サイドバーのインポートを選択します。すると、次のようなインポート用のモーダルが立ち上がります。

![Screenshot_2024-04-21_at_16.46.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/3b34e7c0-b97d-f0f6-e96c-8def5f4fcdf0.png)

API定義はローカルのファイルやディレクトリ、URL、生のJSONやYAMLといったテキストからインポートできます。API定義を指定すると、次にインポート方法の選択をします。

![Screenshot_2024-04-21_at_16.46.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/8177209c-d2c8-1660-15a6-68e48d9c649f.png)

「Postman Collection」は定義をコレクションとしてインポートします。こちらを指定すると、次のようにOpenAPIを元にPostmanコレクションが作成されます。

![Screenshot_2024-04-21_at_17.34.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/c83f8f06-63ef-ba34-790e-2ea49a803235.png)

一方、「OpenAPI 3.0 with a Postman Collection」はコレクションとともにAPI定義も一緒にインポートするかを選択できます。これはAPIビルダーと呼ばれる機能で、詳しくは「**[Design your API in Postman using the API Builder](https://learning.postman.com/docs/designing-and-developing-your-api/the-api-workflow/)**」ページを参照ください。

![Screenshot_2024-04-21_at_17.24.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/88665ac1-fdfd-c758-d979-35a02354c01e.png)

また、View Import Settings（インポート設定を表示）を選択すると、その他の設定オプションが表示されます。これらのオプションの詳細については、[こちらのページ](https://github.com/postmanlabs/openapi-to-postman/blob/develop/OPTIONS.md)を参照ください。