Newman CLI — Running Postman Collections from Terminal

9 min read

The Collection Runner is great for interactive work; for CI, you need a runner that lives in a terminal. Newman is Postman's official command-line tool. It takes the same collection JSON the GUI runs and executes it identically — no Postman app required. This lesson covers installing Newman, running a collection from the terminal, the flags you'll reach for daily, and how its exit codes plug into any CI system. The masterclass API Testing in CI/CD lesson covered the why of CI testing; this lesson is the Postman-flavoured how.

Why a CLI runner exists

The GUI Runner is interactive — perfect for local exploration, useless for a pipeline. CI runs need:

  • Headless execution — no GUI to render.
  • Machine-readable output — JUnit XML, JSON, exit codes that fail builds.
  • Reproducibility — the same JSON in Git produces the same run on every machine.
  • No login required — no Postman account needed on the CI worker.

Newman gives you all four. Same collection, same tests, same assertions; the only thing that changes is where it runs.

Postman GUI Runner vs Newman CLI

Postman GUI Runner

  • Interactive

    Click through results, drill into failed requests, replay individual iterations. Built for human use.

  • Visual

    Live progress bar, colour-coded status, request/response inspectors. Great for development.

  • Manual trigger

    Run when you click Run. Not suited to scheduled or automated execution.

  • Local only

    Tied to your Postman desktop install. Doesn't run in CI workers, containers, or servers.

Newman CLI

  • Headless

    No GUI. Pure terminal output (or HTML/XML files). Runs anywhere Node.js runs.

  • Machine-readable

    JUnit XML, JSON, htmlextra reports for CI dashboards. Standard exit codes (0 pass, 1 fail) drive build gates.

  • Automatable

    Trigger from cron, GitHub Actions, Jenkins, GitLab, ArgoCD, schedulers, npm scripts.

  • Same engine as the GUI

    The collection JSON, environment JSON, and test scripts behave identically between GUI and CLI. Develop in Postman, run in Newman.

The two are complementary, not alternatives. Develop a suite in Postman, ship it via Newman.

Installing Newman

Newman is an npm package. You need Node.js 18+ on the machine. To install globally:

npm install -g newman
newman --version

You should see something like 6.0.0. If newman isn't found, the npm global bin directory probably isn't on your PATH — fix with export PATH="$(npm bin -g):$PATH" or follow your shell's npm setup.

For a project-scoped install (recommended in real repos):

cd path/to/your/repo
npm install --save-dev newman
npx newman --version

That keeps the Newman version pinned in package.json so every contributor and the CI runner use the same one.

Running a collection

Export your collection from Postman first (right-click → Export → Collection v2.1). Then in your terminal:

newman run JSONPlaceholder-API-Tests.postman_collection.json

Newman parses the JSON, executes every request in order, runs every test, and prints a summary at the end:

→ GET All Users
  GET https://jsonplaceholder.typicode.com/users [200 OK, 5.6kB, 215ms]
  ✓  Status is 200
  ✓  Response time is under 500ms
  ✓  Body is a non-empty array

→ GET User by ID
  GET https://jsonplaceholder.typicode.com/users/1 [200 OK, 510B, 180ms]
  ✓  Status is 200
  ✓  Email field present

┌─────────────────────────┬────────────┬────────────┐
│                         │   executed │     failed │
├─────────────────────────┼────────────┼────────────┤
│              iterations │          1 │          0 │
├─────────────────────────┼────────────┼────────────┤
│                requests │          2 │          0 │
├─────────────────────────┼────────────┼────────────┤
│            test-scripts │          2 │          0 │
├─────────────────────────┼────────────┼────────────┤
│      prerequest-scripts │          0 │          0 │
├─────────────────────────┼────────────┼────────────┤
│              assertions │          5 │          0 │
└─────────────────────────┴────────────┴────────────┘

Five assertions, zero failed. Exit code: 0 (success).

With an environment

Export your environment too (Environments tab → ⋯ → Export). Then point Newman at it:

newman run collection.json -e staging-env.json

Variables resolve exactly as they did in the GUI — {{baseUrl}}, {{authToken}}, all of it. Switching from staging to production is one CLI flag away.

For sensitive environments where the JSON has placeholder values and the real values come from elsewhere, use --env-var:

newman run collection.json -e env.json \
  --env-var "baseUrl=https://staging.api.com" \
  --env-var "apiKey=$STAGING_API_KEY"

Each --env-var overrides (or adds) one variable. Pull from shell environment variables and the secret never lives in a file.

Data-driven runs from the CLI

Same data file you used in the GUI Runner (Chapter 4 Lesson 2):

newman run collection.json -e env.json -d test-data.csv

Newman runs once per row, substituting the row's values into {{vars}}. The summary table now shows multiple iterations and a per-iteration breakdown of any failures.

Running directly from the Postman cloud

If you don't want to manually export the JSON, Newman can fetch a collection from the Postman API:

newman run "https://api.getpostman.com/collections/<COLLECTION_ID>?apikey=<YOUR_POSTMAN_API_KEY>"

Convenient — but means CI has live internet access to Postman, and the API key needs careful storage. Most teams settle on the export-and-commit-to-Git approach: the JSON is auditable, version-controlled, and CI runs are reproducible even when Postman's services are down.

The flags you'll reach for daily

A short list that covers most real cases:

  • -e <env-file> — pick an environment.
  • -d <data-file> — pick a data file (CSV/JSON).
  • -n <count> — run the collection N times. Without -d this is just looping.
  • --folder <name> — run only one folder of the collection. Saves time when smoke-testing.
  • --delay-request <ms> — pause between requests. --delay-request 200 is friendly for rate-limited APIs.
  • --timeout-request <ms> — kill any single request that takes longer than this. --timeout-request 10000 (10 seconds) is a sensible default.
  • --bail — stop on the first failure. Default is to keep running and report the aggregate. Use --bail when an early failure makes later assertions meaningless.
  • --reporters cli,htmlextra — output formats. CLI is default; combine with htmlextra for HTML reports (next lesson) or junit for JUnit XML.
  • --env-var "key=value" — inline variable overrides (one flag per variable).
  • --insecure — skip TLS verification. Useful against test environments with self-signed certs; never use against production.
  • --suppress-exit-code — exit 0 even when assertions fail. Niche use: report-only runs where you don't want CI to fail the build.

A real-world invocation will combine several:

newman run postman/JSONPlaceholder.postman_collection.json \
  -e postman/staging.postman_environment.json \
  --env-var "apiKey=$STAGING_API_KEY" \
  --delay-request 100 \
  --timeout-request 10000 \
  --reporters cli,htmlextra \
  --reporter-htmlextra-export reports/api-report.html

Exit codes — the CI integration in one number

Newman exits with:

  • 0 — every assertion passed.
  • 1 — one or more assertions failed, or Newman itself errored.

Every CI system in existence treats a non-zero exit code as a failed step. Wiring Newman into GitHub Actions, Jenkins, GitLab, CircleCI, or any other pipeline is just "add a step that runs newman run ..." — the system fails the build automatically if anything fails.

To verify locally:

newman run collection.json
echo $?    # 0 if all passed

Adding to package.json scripts

In a real repo, the Newman invocation usually lives in package.json so contributors run it the same way:

{
  "scripts": {
    "test:api": "newman run postman/collection.json -e postman/staging.json -r cli,htmlextra --reporter-htmlextra-export reports/report.html",
    "test:api:smoke": "newman run postman/collection.json --folder Smoke -e postman/staging.json --bail",
    "test:api:prod": "newman run postman/collection.json -e postman/prod.json --folder 'Read-only smoke'"
  }
}

Then anybody on the team runs npm run test:api and gets the same invocation. CI does the same.

⚠️ Common mistakes

  • Hardcoding secrets in committed environment files. Newman reads them happily; Git remembers them forever. Use --env-var "key=$VAR" so secrets come from CI environment variables, never the file.
  • Forgetting --insecure is for tests only. --insecure disables TLS verification. Useful when staging has a self-signed cert; catastrophic if used against production where MITM is now undetectable.
  • Skipping --timeout-request. Without a per-request timeout, a single hung endpoint can stall a CI step indefinitely. Set 10000ms (or whatever your slowest legitimate request is) and let Newman fail fast on stuck requests.

🎯 Practice task

Run your suite from the terminal. 25-30 minutes.

  1. Install Newman: npm install -g newman (you need Node.js 18+). Verify with newman --version.
  2. Export your JSONPlaceholder API Tests collection from Postman to disk. Right-click → Export → Collection v2.1 → save to a folder e.g. ~/postman-course/.
  3. Export the JSONPlaceholder environment too (Environments tab → ⋯ → Export).
  4. In a terminal in that folder:
    newman run "JSONPlaceholder API Tests.postman_collection.json" \
      -e JSONPlaceholder.postman_environment.json
    Watch every request fire and the summary table at the end. Confirm echo $? prints 0.
  5. Force a failure. Edit one of the test scripts in Postman to assert pm.response.to.have.status(999). Re-export the collection. Re-run Newman. The summary should show a failed assertion; echo $? should print 1. Revert.
  6. Run only one folder:
    newman run "JSONPlaceholder API Tests.postman_collection.json" \
      --folder "CRUD Chain" \
      -e JSONPlaceholder.postman_environment.json
    Notice only the chain's five requests run.
  7. Override an env var:
    newman run "JSONPlaceholder API Tests.postman_collection.json" \
      --env-var "baseUrl=https://my-json-server.typicode.com/typicode/demo"
    The collection now hits the alternative host without a separate environment file.
  8. Add to package.json. Initialise an npm project (npm init -y), install Newman locally (npm install --save-dev newman), and add a script:
    "scripts": { "test:api": "newman run \"JSONPlaceholder API Tests.postman_collection.json\" -e JSONPlaceholder.postman_environment.json" }
    Run npm run test:api. Same output, but now versioned with the project.
  9. Stretch: add --delay-request 100 and --timeout-request 5000. Run again. Notice the visible pause between requests in the CLI output.

You can now run any Postman collection from a terminal — and so can any CI system. The next lesson layers HTML and JUnit reports on top of the CLI output, so you have something to share with stakeholders and parse in dashboards.

// tip to track lessons you complete and pick up where you left off across devices.