Postman Newman CI/CD Integration: Running API Tests in GitHub Actions and Jenkins

Postman Newman CI/CD Integration: Running API Tests in GitHub Actions and Jenkins

Postman collections are useful for manual API testing. Newman — Postman's command-line runner — makes those same collections run in CI/CD. Every push triggers the full API test suite, reports go into your build artifacts, and failures block merges.

This guide covers setting up Newman in CI/CD: GitHub Actions configuration, Jenkins pipeline integration, handling environments securely, and generating reports that give you actionable failure information.

Installing Newman

# Install globally
npm install -g newman

# Or as a project dependency (recommended for reproducibility)
npm install --save-dev newman
npx newman run --version

Basic Newman Usage

# Run a collection with an environment file
newman run collection.json --environment staging.json

# Run with a specific data file (data-driven)
newman run collection.json \
  --environment staging.json \
  --data test-data.csv

# Run and exit with non-zero status on failure
newman run collection.json \
  --environment staging.json \
  --bail  # Stop on first failure

# Specify timeout (milliseconds)
newman run collection.json \
  --timeout-request 5000 \
  --timeout 120000

Exporting Collections and Environments From Postman

Before CI can run your tests, you need to export:

# Export via Postman CLI (newer approach)
postman login --with-api-key $POSTMAN_API_KEY

# Export collection
postman collection export <collection-id> > collection.json

# Or use the Postman API directly
curl -H "X-Api-Key: $POSTMAN_API_KEY" \
  "https://api.getpostman.com/collections/<collection-id>" \
  | jq '.collection' > collection.json

Better approach for teams: commit the exported JSON files to your repository. This gives you version control over your test suite.

tests/
├── api/
│   ├── user-management.collection.json
│   ├── auth.collection.json
│   └── environments/
│       ├── staging.json
│       └── production.json
├── data/
│   └── test-users.csv
└── package.json

GitHub Actions Integration

Basic workflow:

# .github/workflows/api-tests.yml
name: API Tests

on:
  push:
    branches: [main, develop]
  pull_request:

jobs:
  api-test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install Newman
        run: npm install -g newman newman-reporter-htmlextra

      - name: Wait for API to be available
        run: |
          /usr/local/bin/await "curl -sf ${{ vars.STAGING_URL }}/health"

      - name: Run API tests
        env:
          BASE_URL: ${{ vars.STAGING_URL }}
          API_KEY: ${{ secrets.TEST_API_KEY }}
        run: |
          # Inject secrets into environment file
          jq ".values[] |= if .key == \"apiKey\" then .value = \"$API_KEY\" else . end" \
            tests/api/environments/staging.json > /tmp/staging-env.json

          newman run tests/api/user-management.collection.json \
            --environment /tmp/staging-env.json \
            --reporters cli,json,htmlextra \
            --reporter-json-export results/report.json \
            --reporter-htmlextra-export results/report.html \
            --reporter-htmlextra-title "API Test Results - ${{ github.sha }}"

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: api-test-results
          path: results/

      - name: Publish test summary
        if: always()
        uses: dorny/test-reporter@v1
        with:
          name: API Tests
          path: results/report.json
          reporter: newman-results

Multi-environment workflow (parallel):

# .github/workflows/api-tests-matrix.yml
name: API Tests Matrix

on:
  schedule:
    - cron: '0 */4 * * *'  # Every 4 hours

jobs:
  api-test:
    strategy:
      matrix:
        environment: [staging, production]
      fail-fast: false  # Continue other matrix jobs if one fails

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - run: npm install -g newman newman-reporter-htmlextra

      - name: Run ${{ matrix.environment }} tests
        env:
          API_KEY: ${{ secrets[format('{0}_API_KEY', upper(matrix.environment))] }}
          BASE_URL: ${{ vars[format('{0}_URL', upper(matrix.environment))] }}
        run: |
          newman run tests/api/smoke-tests.collection.json \
            --environment tests/api/environments/${{ matrix.environment }}.json \
            --env-var "apiKey=$API_KEY" \
            --env-var "baseUrl=$BASE_URL" \
            --reporters cli,json \
            --reporter-json-export results/${{ matrix.environment }}-report.json

      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: ${{ matrix.environment }}-results
          path: results/

Jenkins Pipeline Integration

// Jenkinsfile
pipeline {
    agent any

    environment {
        STAGING_URL = 'https://api.staging.example.com'
        TEST_API_KEY = credentials('api-test-key')
    }

    stages {
        stage('Install') {
            steps {
                sh 'npm install -g newman newman-reporter-htmlextra'
            }
        }

        stage('Wait for API') {
            steps {
                sh '''
                    until curl -sf $STAGING_URL/health; do
                        echo "Waiting for API..."
                        sleep 5
                    done
                '''
            }
        }

        stage('API Tests') {
            parallel {
                stage('Auth Tests') {
                    steps {
                        sh '''
                            newman run tests/api/auth.collection.json \
                                --env-var "baseUrl=$STAGING_URL" \
                                --env-var "apiKey=$TEST_API_KEY" \
                                --reporters cli,junit \
                                --reporter-junit-export results/auth-junit.xml
                        '''
                    }
                    post {
                        always {
                            junit 'results/auth-junit.xml'
                        }
                    }
                }

                stage('User API Tests') {
                    steps {
                        sh '''
                            newman run tests/api/user-management.collection.json \
                                --env-var "baseUrl=$STAGING_URL" \
                                --env-var "apiKey=$TEST_API_KEY" \
                                --reporters cli,junit,htmlextra \
                                --reporter-junit-export results/users-junit.xml \
                                --reporter-htmlextra-export results/users-report.html
                        '''
                    }
                    post {
                        always {
                            junit 'results/users-junit.xml'
                            publishHTML([
                                allowMissing: false,
                                alwaysLinkToLastBuild: true,
                                keepAll: true,
                                reportDir: 'results',
                                reportFiles: 'users-report.html',
                                reportName: 'API Test Report'
                            ])
                        }
                    }
                }
            }
        }
    }

    post {
        failure {
            slackSend(
                channel: '#engineering',
                color: 'danger',
                message: "API Tests Failed: ${env.BUILD_URL}"
            )
        }
    }
}

Handling Secrets Securely

Never commit API keys or passwords to your repository — even for test accounts. Use environment variable injection:

GitHub Actions approach:

# In your workflow: inject secrets as Newman env vars
newman run collection.json \
  --environment base-env.json \
  --env-var "apiKey=${{ secrets.API_KEY }}" \
  --env-var "dbPassword=${{ secrets.DB_PASSWORD }}"

For environment files with multiple secrets:

# Create a modified environment file at runtime
python3 << 'EOF'
import json, os, sys

with open('tests/api/environments/staging.json') as f:
    env = json.load(f)

secrets = {
    'apiKey': os.environ['API_KEY'],
    'adminPassword': os.environ['ADMIN_PASSWORD'],
    'webhookSecret': os.environ['WEBHOOK_SECRET'],
}

for var in env['values']:
    if var['key'] in secrets:
        var['value'] = secrets[var['key']]

with open('/tmp/runtime-env.json', 'w') as f:
    json.dump(env, f)
EOF

newman run collection.json --environment /tmp/runtime-env.json

Newman Reporter Configuration

Install reporters:

npm install -g newman-reporter-htmlextra newman-reporter-junit

htmlextra generates rich HTML reports:

newman run collection.json \
  --reporters htmlextra \
  --reporter-htmlextra-export results/report.html \
  --reporter-htmlextra-title "My API Tests" \
  --reporter-htmlextra-logs true \
  --reporter-htmlextra-showEnvironmentData true \
  --reporter-htmlextra-skipSensitiveData true

JUnit output for CI integration (most CI tools parse JUnit XML):

newman run collection.json \
  --reporters junit \
  --reporter-junit-export results/junit.xml

Running Collections in Parallel

For large test suites, split into multiple collections and run in parallel:

# run-parallel.sh
#!/bin/bash

BASE_URL=$1
API_KEY=$2

run_collection() {
    local collection=$1
    newman run "$collection" \
        --env-var "baseUrl=$BASE_URL" \
        --env-var "apiKey=$API_KEY" \
        --reporters cli,json \
        --reporter-json-export "results/${collection%.collection.json}-results.json" \
        > "logs/${collection%.collection.json}.log" 2>&1
    echo "$collection: exit $?"
}

mkdir -p results logs

# Run all collections in parallel
for collection in tests/api/*.collection.json; do
    run_collection "$collection" &
done

# Wait for all and check results
FAILED=0
for job in $(jobs -p); do
    wait "$job" || FAILED=$((FAILED + 1))
done

if [ "$FAILED" -gt 0 ]; then
    echo "FAIL: $FAILED collection(s) failed"
    cat logs/*.log
    exit 1
fi

echo "All collections passed"

Monitoring With Scheduled Newman Runs

For production API monitoring, run Newman on a schedule:

# .github/workflows/api-monitor.yml
name: API Health Monitor

on:
  schedule:
    - cron: '*/15 * * * *'  # Every 15 minutes

jobs:
  monitor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm install -g newman

      - name: Run smoke tests
        id: smoke
        run: |
          newman run tests/api/smoke-tests.collection.json \
            --env-var "baseUrl=${{ vars.PRODUCTION_URL }}" \
            --env-var "apiKey=${{ secrets.PROD_MONITOR_KEY }}" \
            --timeout-request 10000 \
            --bail

      - name: Alert on failure
        if: failure()
        uses: slackapi/slack-github-action@v1
        with:
          channel-id: 'on-call'
          slack-message: "Production API smoke tests failed! Check ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

Newman transforms Postman collections from developer tools into production monitoring assets. The same tests you write in Postman run in CI, in production monitoring, and in pre-deploy validation — one collection, multiple contexts.


HelpMeTest complements API tests with end-to-end behavioral testing that validates user workflows, not just API endpoints. Start free →

Read more

Start now free