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 --versionBasic 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 120000Exporting 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.jsonBetter 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.jsonGitHub 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-resultsMulti-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.jsonNewman Reporter Configuration
Install reporters:
npm install -g newman-reporter-htmlextra newman-reporter-junithtmlextra 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 trueJUnit output for CI integration (most CI tools parse JUnit XML):
newman run collection.json \
--reporters junit \
--reporter-junit-export results/junit.xmlRunning 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 →