Postman’s integrated API Builder lets you design your APIs with an API definition. But even with the help of the API Builder, creating an OpenAPI specification can be difficult. On the other hand, it’s easier to create collections in Postman. Postman Collections make it easy to add requests, create JSON responses and request bodies. For even greater visibility, consider using Postman Insights to monitor and debug your endpoints in real-time (currently an Alpha feature) and, ensuring they remain reliable.
To help bridge the gap between the API Builder and Postman Collections and help you with your API-first design, we exposed the collection transformation endpoint in the Postman API. How does it work? Call the endpoint and you’ll get a response that contains your collection’s OpenAPI definition. It’s that simple!
With this endpoint, you can:
- Use collections as the tool for your API-first design. You can design your API in a collection, add the corresponding examples, share it with your stakeholders, and create mock servers. Once the API design is approved, you can convert your collection to an OpenAPI definition with this endpoint.
- Automatically convert a collection into an OpenAPI definition and programmatically sync the API definition in Postman.
If you maintain a collection with documentation and examples of your API, you can easily generate the OpenAPI definition and save it to a file in your repository on the command line. It’s as easy as:
- Getting the OpenAPI definition of the collection using the Postman API.
- Extracting response text and formatting it with jq.
- Saving the OpenAPI definition to a file.
In this post, we’ll show you how you can use this workflow to turn your collections into usable OpenAPI definitions.
Step 1: Get the collection’s OpenAPI definition with the Postman API
First, run the following command, replacing {{collectionId}}
with your collection’s ID and {{postman-api-key}}
with your Postman API key value:
curl --location --request GET 'https://api.getpostman.com/collections/{{collectionId}}/transformations' \
--header 'Content-Type: application/json' \
--header 'x-api-key: {{postman-api-key}}'
This command calls the collection transformation endpoint and returns a response body similar to the following:
{"output":"{\"openapi\":\"3.0.3\",\"info\":{\"title\":\"Blogpost: convert collection into OpenAPI\",\"version\":\"1.0.0\"},\"servers\":[{\"url\":\"https://postman-echo.com\"}],\"paths\":{\"/get\":{\"get\":{\"tags\":[\"default\"],\"summary\":\"Retrieve resource\",\"parameters\":[{\"name\":\"queryParam\",\"in\":\"query\",\"schema\":{\"type\":\"string\"},\"example\":\"value\"}],\"responses\":{\"200\":{\"description\":\"OK\",\"headers\":{\"Date\":{\"schema\":{\"type\":\"string\",\"example\":\"Tue, 19 Sep 2023 07:55:16 GMT\"}},\"Content-Type\":{\"schema\":{\"type\":\"string\",\"example\":\"application/json; charset=utf-8\"}},\"Content-Length\":{\"schema\":{\"type\":\"integer\",\"example\":\"455\"}},\"Connection\":{\"schema\":{\"type\":\"string\",\"example\":\"keep-alive\"}},\"ETag\":{\"schema\":{\"type\":\"string\",\"example\":\"W/\\\"1c7-uf8/UqqY3lVr9ce8gw2ezu2U6bA\\\"\"}},\"set-cookie\":{\"schema\":{\"type\":\"string\",\"example\":\"sails.sid=s%3ASfWFAgot9KIrPVWc1LFU9epZytyvAMzh.5h4u9nIlNba1z%2F%2Fcyc21Qym8MIzrDQ68R%2BzyTgZVH%2Bk; Path=/; HttpOnly\"}}},\"content\":{\"application/json\":{\"schema\":{\"type\":\"object\"},\"example\":{\"args\":{\"queryParam\":\"value\"},\"headers\":{\"x-forwarded-proto\":\"https\",\"x-forwarded-port\":\"443\",\"host\":\"postman-echo.com\",\"x-amzn-trace-id\":\"Root=1-650953e4-6ae9504466614d120d93feb1\",\"user-agent\":\"PostmanRuntime/7.33.0\",\"accept\":\"*/*\",\"postman-token\":\"1a1e92e9-e27c-4b7c-9854-420db16e6262\",\"accept-encoding\":\"gzip, deflate, br\"},\"url\":\"https://postman-echo.com/get?queryParam=value\"}}}}}}},\"/post\":{\"get\":{\"tags\":[\"default\"],\"summary\":\"Create resource\",\"responses\":{\"404\":{\"description\":\"Not Found\",\"headers\":{\"Date\":{\"schema\":{\"type\":\"string\",\"example\":\"Tue, 19 Sep 2023 07:56:03 GMT\"}},\"Content-Length\":{\"schema\":{\"type\":\"integer\",\"example\":\"0\"}},\"Connection\":{\"schema\":{\"type\":\"string\",\"example\":\"close\"}},\"set-cookie\":{\"schema\":{\"type\":\"string\",\"example\":\"sails.sid=s%3AhbKkbH0EoTr-OyyTjQMnC1Cntxxy2EM5.o1yU%2FgQzMnS5GL8S%2FbGODfPy9gn3qOpIVY1Wd%2BxjMjk; Path=/; HttpOnly\"}}},\"content\":{\"text/plain\":{\"schema\":{\"type\":\"string\"},\"example\":null}}}}}}}}"}
The output field in the endpoint’s response contains the generated OpenAPI 3.0.3 definition in a stringified format.
Step 2: Extract and format the response’s text with jq
Next, we’ll want to extract the output
field from the response and save it to a file in JSON format. We’ll use jq to do this in the following command:
curl --location --request GET 'https://api.getpostman.com/collections/{{collectionId}}/transformations' \
--header 'Content-Type: application/json' \
--header 'x-api-key: {{postman-api-key}}' \
| jq '.output | fromjson'
In this command, we’re sending the collection transformation’s output
contents and piping it to jq with the jq '.output | fromjson'
command. The jq command extracts the output
field, then reads the JSON string with the fromjson
jq function. Note that all the jq arguments are enclosed in single quote ('
) characters.
When you run this command, it prints a properly-formatted JSON object:
Step 3: Save the OpenAPI definition to a file
Lastly, we’ll dump the output from jq into a JSON file:
curl --location --request GET 'https://api.getpostman.com/collections/{{collectionId}}/transformations' \
--header 'Content-Type: application/json' \
--header 'x-api-key: {{postman-api-key}}' \
| jq '.output | fromjson' \
> my_openapi.json
In this step, we’re directing the output from jq to a file. This file contains the formatted OpenAPI definition generated from the given collection ID. You can then use this file to create an API definition in Postman’s API Builder:
Next steps
This is just one example of how you can create an OpenAPI from a collection and use it. Do you have a specific use case? How do you design and develop your APIs? Are you using the API design-first approach? Let us know about your use cases!