portman: turning an OpenAPI document into a Postman collection with tests
Port OpenAPI Specs to Postman Collections, inject test suite and run via Newman 👨🏽🚀
At a glance
- What is it?
- portman is a TypeScript CLI that reads an OpenAPI document, converts it into a Postman collection, injects contract and variation tests into it, and can upload the collection and run it through Newman. The value is speed of setup, and the cost is that the test execution environment ends up being Postman and Newman rather than code you own.
- Who is it for?
- portman fits a team that already writes OpenAPI documents and wants a runnable Postman collection with contract and variation tests without hand writing requests, and it does not fit a team that needs stateful end to end flows or a test harness owned in its own repository.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A spec in, a tested collection out
portman does what its description says: it ports an OpenAPI spec to a Postman collection, with contract and variation tests included. The README frames the value in terms of what the spec already contains. Portman uses OpenAPI documents, with all their defined API request and response properties, to power the Postman collection, and it injects the contract and variation tests with a minimum of configuration.
The workflow it targets is contract first development. A team writes or maintains an OpenAPI document, and rather than hand writing Postman requests and assertions, the tool derives both from the spec. Every method and endpoint combination in the document becomes a request in the collection, and each one is accompanied by a set of contract tests. The result can be uploaded to the Postman app, or run locally through Newman, or both as part of a CI/CD pipeline.
Two format versions are supported, OpenAPI 3.0 and OpenAPI 3.1, which matters because a 3.1 document with webhooks and JSON Schema flavoured types exercises different code paths in the converter.
The audience is API developers who already write the spec and want a fast path to a runnable test suite, plus the platform teams who put such a suite into a pipeline. The npm package is @apideck/portman, and the homepage is getportman.com.
Contract tests, variation tests and fuzzing are different assertions
The feature list is where the actual scope of the tool becomes visible, and the three test flavours are worth separating.
Contract tests check the response against the schema the spec declares. Since the spec is the source of the request and the expected response properties, the contract test is generated rather than written, and each endpoint in the collection gets its own set.
Variation tests are the opposite idea: they send inputs that should fail, which is how a spec's constraints get enforced from the client side. There is a separate examples directory for variation tests and for contract content types, and the README points at a dedicated folder for each suite, which tells you these are configurations rather than hard-coded behaviour.
Beyond those, the list includes injecting Postman integration tests, injecting pre-request and tests scripts at either collection or operation level, modifying requests through overwrites and variable assignment, and fuzzing Postman requests. The examples directory names these folders explicitly, including testsuite-content-tests, testsuite-fuzzing-tests, testsuite-overwrites, testsuite-assign-overwrite, testsuite-assign-variables, testsuite-pre-request-scripts and testsuite-contract-content-types.
The practical upshot is that the tool can produce a collection that is only a request list, or a collection with a full test harness around it, depending on configuration. Which of those you get is a configuration decision, and the default configuration is the contract test suite.
Configuration lives in files, and one deprecated option can break a run
There are three ways to start, and they differ in how much you configure before the first run.
The first is to install the CLI and let it create a configuration, by running portman --init. The second is to copy .env.example to .env, add the environment variables your collection needs, and copy and customise the default configuration files in the root directory, whose names end in .default.json. The third is to run it with no configuration at all on an existing spec, which the README presents as the way to see what the tool generates before investing in setup.
The install itself is a normal npm dependency.
$ npm install --save @apideck/portmanA global install and the no-install npx route are the other two options.
$ npm install -g @apideck/portman$ npx @apideck/portman -l your-openapi-file.yamlThere is one migration note worth reading before you upgrade. The README flags an important change for anyone on version 1.28.0 who passes a custom Postman config file with the --postmanConfigFile flag: the parametersResolution option must be set to either Example or Schema, because the requestParametersResolution and exampleParametersResolution options are deprecated options of the underlying openapi-to-postman converter.
The other two layers of configuration are documented elsewhere and Portman passes them through. The options for converting OpenAPI to Postman live in the openapi-to-postman package documentation, and the options for filtering flags, tags, methods and operations live in the openapi-format package, which also has an online playground.
The CLI is a URL or a file plus a bag of Newman switches
The usage banner shows the shape of the tool: a url or a local spec, an optional base url override, and a flag for including tests.
Usage: -u <url> -l <local> -b <baseUrl> -t <includeTests>
Options:
--help Show help [boolean]
--version Show version number [boolean]
--url,-u URL of OAS to port to Postman collection [string]
--local, -l Use local OAS to port to Postman collection [string]
--baseUrl, -b Override spec baseUrl to use in Postman [string]
--output, -o Write the Postman collection to an output file [string]
--oaOutput Write the (filtered) OpenAPI file to an output file [string]
--runNewman, -n Run Newman on newly created collection [boolean]
--newmanRunOptions JSON stringified object to pass options for configuring Newman [string]
--newmanOptionsFile Path/URL to Newman options file to pass options for configuring Newman [string]Three of those options are worth pausing on. The --output flag writes the collection to a file instead of only uploading it. The --oaOutput flag writes the filtered OpenAPI document to a file, which is the way to see what the filtering actually produced. And the --newmanOptionsFile flag takes a path or a URL to a Newman options file, so the run configuration is a reviewable artefact rather than a wall of command line arguments.
The --baseUrl override is the one with a failure mode. It replaces the base url from the spec, which is what you want when the collection runs against a different environment than the one the document describes. If you forget it, the generated requests point wherever the spec said, and the tests fail against the wrong host rather than against the wrong schema.
One small inconsistency in the documentation is worth knowing about. The getting started section shows the shorter npx portman form, while the installation section notes that a local install requires npx @apideck/portman or, with an older npm, the path to the binary inside node_modules. Both work, but the command you copy into a pipeline should be the one your npm version actually supports.
Uploading to Postman and injecting variables needs keys in the environment
Two integrations sit outside the local conversion, and both are configured through environment variables rather than the JSON config.
The first is uploading the collection to your Postman app, which needs a Postman API key. The .env.example file lists a POSTMAN_API_KEY entry for that, and there is a separate .env-postman-app.example file at the top of the repository for the app upload path.
The second is the set of variables that the tool injects into the collection for the consumer to fill in.
### PORTMAN INJECTED VARIABLES
PORTMAN_MANAGEMENT_API_KEY='[EXAMPLE-replace with valid api key]'
PORTMAN_BEARER_TOKEN='[EXAMPLE-replace with valid token]'
PORTMAN_APPLICATION_ID=[EXAMPLE]
PORTMAN_SERVICE_ID=[EXAMPLE]
PORTMAN_CONSUMER_ID=[EXAMPLE]
### POSTMAN APP
POSTMAN_API_KEY=[replace with valid Postman api key]These are placeholders that a consumer replaces with the credentials their API expects, which is a sensible default for a tool that generates requests for an unknown service. It also means the generated collection is not runnable as it stands, and the values have to come from somewhere before Newman can exercise the endpoints.
For running the tool in a container, the Dockerfile is three lines of substance.
FROM node:lts-alpine
ARG PORTMAN_VERSION=latest
RUN npm install -g "@apideck/portman@${PORTMAN_VERSION}"
ENTRYPOINT ["portman"]The image installs a pinned or latest version of the package globally and makes the CLI the entrypoint, so the container takes a spec file as its input. The version argument defaults to latest, which is a choice to think about if you want a reproducible build.
Where a Postman-centred pipeline stops being the right answer
The tool is good at its job, and the job has a specific shape. Everything ends up in a Postman collection, and the execution environment is Newman, which is a Node runner for Postman collections and scripts. That is a fine target for a request and response API, and it is what makes the tool fast to adopt.
It is a poor fit when the thing you need to test is not a request and a response. Contract testing in the strict sense, where a consumer's expectations are published and the provider is checked against them independently, is not what a generated collection does, because the expectations are derived from the same document that describes the implementation. A generated contract test tells you the service still matches its own spec, which is useful and is not the same guarantee.
The other mismatch is scale and realism. A collection generated from a large spec produces a large number of requests, and Newman running them is a request-level test, so stateful flows, long sequences and realistic concurrency need workarounds rather than configuration.
The alternative approach is to skip Postman and test against the spec directly, with a tool that generates test cases from the schema and runs them against a live service in your own test code. The difference in approach is where the assertions live. Portman puts them in a collection and a runner that somebody else maintains, with the Postman runtime as a dependency of your pipeline. A spec-driven runner puts them in your repository, in the language and test framework you already use, and the cost is that you write and maintain the harness yourself rather than accepting the generated one.
Apache 2.0, a busy release line, and modern tooling around it
The licence is Apache-2.0, with a LICENSE.md file at the top of the repository and the same value in the package.json metadata. The package is published as @apideck/portman at version 1.35.2, with the homepage set to apideck.com and the author listed as Apideck.
Releases are frequent. The list shows v1.35.2 on 2026-10-14, v1.35.1 on 2026-10-13 and v1.35.0 on 2026-05-23, and the last push was on 2026-10-14 with the repository not archived. A patch release on consecutive days followed by a five month gap is the pattern of a tool that is maintained rather than continuously churned, and it means an upgrade is cheap, since the configuration surface is documented in the repository rather than in a hosted service.
The development tooling in the package.json is modern and worth a glance. Linting and formatting use oxlint and oxfmt rather than the older eslint and prettier pair, the test script runs jest with coverage and no cache, and there is a separate script for the OpenAPI upgrade risk test that is excluded from the main run. Formatting and linting are wired to a husky directory, so the checks run before a commit rather than in review.
The tree also shows the configuration surface in one place: portman-config.default.json and portman-config.example.json for the tool's own settings, postman-config.default.json and postman-config.example.json for the converter, a postman-config.k6.json for the k6 route, and a postman-config.legacy.json kept for older behaviour. That last file is the kind of artifact that explains why the README bothers to flag a deprecated option.
Editorial conclusion
portman fits a team that already writes OpenAPI documents and wants a runnable Postman collection with contract and variation tests without hand writing requests, and it does not fit a team that needs stateful end to end flows or a test harness owned in its own repository. Before adopting it, generate one collection from a single service spec, run it with the Newman flags you intend to use in CI, and check the deprecated options notice in the README against your own Postman config file.
Frequently asked questions
How do I install portman and generate a Postman collection?
Install the package with npm install --save @apideck/portman, or globally with npm install -g @apideck/portman, or run it without installing through npx. Then point it at a spec with the local or url flag, for example npx @apideck/portman -l your-openapi-file.yaml, or run portman --init to generate a configuration first.
What are the contract and variation tests in portman?
Contract tests check responses against the schema the OpenAPI document declares, and they are generated for every method and endpoint combination in the spec. Variation tests send inputs that should fail, so the spec constraints are enforced from the client side.
Which OpenAPI versions does portman support?
The README lists support for OpenAPI 3.0 and OpenAPI 3.1. The tool also supports filtering the spec, with those options documented in the openapi-format package and its online playground.
How do I run the generated collection with Newman in portman?
Use the --runNewman flag to run Newman on the newly created collection, with --newmanOptionsFile taking a path or URL to a Newman options file, or --newmanRunOptions for a JSON string of options. The Docker image can also be used, since it installs the CLI globally and sets it as the entrypoint.
What changed in portman 1.28.0 for custom Postman config files?
If you use version 1.28.0 with a custom Postman config file passed through the --postmanConfigFile flag, the parametersResolution option must be set to either Example or Schema, because the requestParametersResolution and exampleParametersResolution options are deprecated openapi-to-postman options.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/apideck-libraries-portman)Was this useful?