API Testing in CI with the Postman CLI โ
Most API teams already have a Postman collection somewhere, full of requests and a few pm.test() assertions. Running those tests by hand before a release is a waste. The collection should run on every merge request, and a failing test should fail the build. Here's how I do it with the Postman CLI.
๐ Postman CLI vs Newman โ
For years the answer was Newman, Postman's open-source collection runner on npm. It still works, and Postman has never announced an end-of-life date for it. But releases have slowed: 6.2.1 came out in August 2024, and the next one, 6.2.2, didn't arrive until January 2026.
The Postman CLI launched in September 2022 alongside Postman v10. It's closed source, but it's signed and maintained by Postman, and it gets new releases every few days. Postman's migration guide now calls it the recommended tool for running collections. The big change came with Postman 12 in March 2026, which introduced the YAML-based v3 collection format that you keep in Git. Newman only understands the v2.1 JSON format, so it can't run v3 collections.
My rule of thumb:
- Newman if you want a fully open-source runner that needs no Postman account, and your collections are v2.1 JSON files.
- Postman CLI for everything else, especially if your workspace is on Postman 12 or you want run results to show up in Postman.
๐ฆ Installing It in a Pipeline โ
The installation docs offer an install script, or an npm package for any OS:
npm install -g postman-cli
postman --versionIn CI I use the npm route on a Node image, because it's one line and works the same everywhere. Alpine Linux isn't supported, so use a Debian-based image.
๐ Logging In with an API Key โ
If you run a cloud collection by ID, the CLI needs to log in. Create a Postman API key, store it as a masked CI variable, and log in without a browser:
postman login --with-api-key "$POSTMAN_API_KEY"The authentication docs recommend this method for CI. If your team is on Postman's EU data residency plan, add --region eu. Never put the key in the repository or in the pipeline file itself.
If the collection is a file in your repository, you can skip logging in. The CLI runs it locally, but it won't upload results to Postman.
โถ๏ธ Running Collections and Environments โ
The core command is postman collection run. It takes a collection ID or a file path. -e takes an environment ID or file, and --env-var overrides single values:
postman collection run "$POSTMAN_COLLECTION_ID" \
-e "$POSTMAN_ENVIRONMENT_ID" \
--env-var "baseUrl=$API_BASE_URL" \
-r cli,junit \
--reporter-junit-export results/junit.xmlI find --env-var really useful in CI. You keep one "CI" environment in Postman and inject the base URL of the review app the pipeline has just deployed.
๐จ Failing the Build โ
This works out of the box. If any assertion fails, postman collection run exits with a non-zero code, and the CI job fails. A single failing test is enough to return exit code 1.
Two flags are worth knowing:
--bailstops at the first error. Use--bail failureto stop when a test fails.-x/--suppress-exit-codeforces exit code 0 even when tests fail. Don't use it in a gating job. A "green" pipeline with failing tests is worse than no tests at all.
๐ฆ GitLab CI Example โ
This is the job I'd add to .gitlab-ci.yml. Set POSTMAN_API_KEY as a masked, protected variable under Settings โ CI/CD โ Variables:
api-tests:
stage: test
image: node:22
variables:
POSTMAN_COLLECTION_ID: "12345678-aaaa-bbbb-cccc-1234567890ab"
POSTMAN_ENVIRONMENT_ID: "12345678-dddd-eeee-ffff-1234567890ab"
before_script:
- npm install -g postman-cli
- postman login --with-api-key "$POSTMAN_API_KEY"
script:
- >
postman collection run "$POSTMAN_COLLECTION_ID"
-e "$POSTMAN_ENVIRONMENT_ID"
--env-var "baseUrl=$API_BASE_URL"
-r cli,junit
--reporter-junit-export results/junit.xml
artifacts:
when: always
reports:
junit: results/junit.xmlWith the artifacts:reports:junit block, GitLab shows failing tests in the merge request widget, so you don't have to dig through job logs. when: always makes sure the report is uploaded even when the job fails, and that's exactly when you need it.
One caveat: the reporter docs say the JUnit, JSON and HTML reporters only work with v2 collections. If you've moved to v3 YAML collections, you only get CLI output for now.
๐ A Note on GitHub Actions โ
On GitHub there's an official action, postmanlabs/postman-cli-action. It installs the CLI and logs in for you:
- uses: postmanlabs/postman-cli-action@v1
with:
api-key: ${{ secrets.POSTMAN_API_KEY }}
command: collection run 12345678-aaaa-bbbb-cccc-1234567890ab -e 12345678-dddd-eeee-ffff-1234567890ab๐ฏ Conclusion โ
The Postman CLI turns the collection your team already maintains into a real quality gate. Install it, log in with a masked API key, run the collection against the right environment, and let the exit code do its job. If you're starting fresh in 2026, I'd skip Newman and go straight to the Postman CLI.