Skip to main content

Postman โ€” The Complete Guide

A single-read, end-to-end reference for Postman: enough to organize a new API workspace, script request chaining and assertions, run a collection headlessly in CI, or walk into an SDET interview. Organized as a lookup you can also read top-to-bottom.

๐Ÿ“‹ Quick reference: Postman โ†’ Beginner
Learn this in 10 minutes10 min
  1. Create a collection and send your first request
  2. Add a test script using the pm.* API and an environment variable
  3. Chain two requests by passing a value between them
  4. Run the collection in CI with Newman
After this guide you can
  • Organise requests into collections and environments
  • Write test scripts and chain requests
  • Run collections in CI with Newman
  • Choose between Postman and Rest Assured

๐Ÿงญ Mental modelHow a Postman request becomes a CI-checked resultA request is organized into a collection, which can be run manually through the Collection Runner or headlessly through Newman in CI, with both paths producing the same pass or fail test report.Requestmethod, url, headersCollectionordered requestsCollection RunnerGUI, sequential runNewman (CLI)CI pipelineTest reportpass/fail

A single request only proves itself once; putting it in a collection makes it repeatable โ€” run it manually through the Collection Runner while you're building it, or headlessly through Newman in a CI pipeline once it's stable, with both paths producing the same pass/fail test report.

1. What Postman Is, in Practical Termsโ€‹

Postman is a GUI-first API client and testing platform โ€” the tool most engineers reach for first to manually explore a new endpoint, and (via scripting + Newman) a viable lightweight automation tool too. It sits at the "exploratory and collaborative" end of API testing, complementary to code-first frameworks like Rest Assured (see section 10).

Core building blocks:

ConceptWhat it is
RequestA single HTTP call (method, URL, headers, body, auth)
CollectionAn ordered folder of requests โ€” the unit of organization and CI execution
EnvironmentA named set of key-value variables (dev/staging/prod) swappable without editing requests
WorkspaceWhere collections/environments live, shared with a team
Collection RunnerGUI tool to execute a whole collection sequentially with data-driven iterations
NewmanCLI runner that executes a collection outside the GUI โ€” the CI integration point

2. Collections, Requests, and Environmentsโ€‹

A collection is a folder tree of requests, exportable/importable as JSON, and typically version-controlled alongside the API repo or synced via a team workspace.

Orders API (collection)
โ”œโ”€โ”€ Auth
โ”‚ โ””โ”€โ”€ POST /oauth/token
โ”œโ”€โ”€ Orders
โ”‚ โ”œโ”€โ”€ GET /orders/{{orderId}}
โ”‚ โ”œโ”€โ”€ POST /orders
โ”‚ โ””โ”€โ”€ DELETE /orders/{{orderId}}
โ””โ”€โ”€ Negative Cases
โ”œโ”€โ”€ GET /orders/invalid-id โ†’ expect 404
โ””โ”€โ”€ POST /orders (missing field) โ†’ expect 400

Requests reference variables with {{doubleCurlyBrace}} syntax instead of hardcoded values:

GET {{baseUrl}}/orders/{{orderId}}
Authorization: Bearer {{accessToken}}

Variable scopes (resolution order, narrowest wins)โ€‹

ScopeLifetimeTypical use
LocalSingle request script onlyOne-off computed value
DataOne Collection Runner iteration (from a CSV/JSON file)Data-driven test rows
EnvironmentActive environment (dev/staging/prod)baseUrl, apiKey โ€” swap per environment
CollectionEntire collection, any environmentValues shared across all environments
GlobalEntire Postman app, all workspacesRarely used โ€” avoid, causes cross-collection leakage

Postman resolves the narrowest matching scope first โ€” a local variable shadows a collection variable of the same name, which shadows a global one. This is a common source of "why is it using the wrong value" bugs โ€” check scopes top-down when debugging.

// Setting variables from scripts
pm.environment.set("accessToken", token);
pm.collectionVariables.set("lastOrderId", orderId);
pm.globals.set("runId", Date.now());

// Reading
pm.environment.get("baseUrl");

Mark secrets (API keys, tokens) as type "secret" in environment variables โ€” Postman masks them in the UI and excludes them from exported JSON by default, reducing accidental leakage in shared workspaces.


3. Pre-request Scripts and Tests (pm.* API)โ€‹

Postman requests run JavaScript at two hook points, both exposing the pm (Postman) API:

HookRunsTypical use
Pre-request ScriptBefore the request is sentCompute a timestamp/signature, refresh an auth token, set dynamic headers
Tests (post-response)After the response arrivesAssertions, extracting values into variables for the next request

Pre-request script exampleโ€‹

// Generate an HMAC signature header before sending
const timestamp = Date.now().toString();
const signature = CryptoJS.HmacSHA256(timestamp + pm.request.url, pm.environment.get("apiSecret"))
.toString(CryptoJS.enc.Hex);

pm.request.headers.add({ key: "X-Timestamp", value: timestamp });
pm.request.headers.add({ key: "X-Signature", value: signature });

Test script exampleโ€‹

pm.test("Status code is 200", () => {
pm.response.to.have.status(200);
});

pm.test("Response has expected schema", () => {
const body = pm.response.json();
pm.expect(body).to.have.property("id");
pm.expect(body.email).to.match(/@/);
});

pm.test("Response time is under 500ms", () => {
pm.expect(pm.response.responseTime).to.be.below(500);
});

// Extract a value and store it for the next request in the collection
const order = pm.response.json();
pm.collectionVariables.set("orderId", order.id);

Assertions use Chai's expect/should BDD syntax (pm.expect(...)), plus Postman-specific sugar like pm.response.to.have.status(200) and pm.response.to.be.json.

Collection-level and folder-level scriptsโ€‹

Pre-request/test scripts can also be attached to a folder or the whole collection, running before/after every request inside it โ€” the standard place to put shared auth-token refresh logic instead of pasting it into every request.


4. Chaining Requestsโ€‹

Because scripts can read/write variables, requests naturally chain: authenticate once, extract the token, use it downstream; create a resource, capture its ID, use it in the next request; and so on.

// In "POST /oauth/token" โ†’ Tests tab
const res = pm.response.json();
pm.environment.set("accessToken", res.access_token);
// In "GET /orders" โ†’ uses {{accessToken}} in the Authorization header automatically
Authorization: Bearer {{accessToken}}
// In "POST /orders" โ†’ Tests tab, feeding the next request
const created = pm.response.json();
pm.collectionVariables.set("orderId", created.id);

// In "GET /orders/{{orderId}}" โ†’ picks it up automatically

For more complex control flow (conditional branching, looping over a list returned by one request to call another N times), use postman.setNextRequest("Request Name") in a test script to control execution order explicitly within the Collection Runner, or postman.setNextRequest(null) to stop the run early on a failed precondition.


5. Collection Runner (Data-Driven Runs)โ€‹

The Collection Runner executes every request in a collection in order, optionally iterating once per row of a CSV or JSON data file โ€” Postman's equivalent of parametrized tests.

username,password,expectedStatus
validuser,correctpass,200
validuser,wrongpass,401
,correctpass,400
pm.test("Status matches expected", () => {
pm.response.to.have.status(Number(pm.iterationData.get("expectedStatus")));
});

Configure iteration count, delay between requests, and data file in the Runner UI; results show pass/fail per request per iteration, exportable as a report.


6. Newman โ€” Running Collections in CIโ€‹

Newman is Postman's official CLI collection runner โ€” it executes an exported collection JSON (and environment JSON) exactly as the app would, without the GUI, making it the CI integration point.

npm install -g newman

newman run OrdersAPI.postman_collection.json \
-e Staging.postman_environment.json \
-d test-data.csv \
--reporters cli,junit \
--reporter-junit-export results/newman-report.xml \
--bail
FlagPurpose
-eEnvironment file
-dData file for iterations
-nNumber of iterations
--reportersOutput formats (cli, json, junit, html via newman-reporter-htmlextra)
--bailStop on first failure
--folderRun only a specific folder/subset
--insecureSkip TLS verification (test envs)

GitHub Actions exampleโ€‹

- name: Run Postman collection via Newman
run: |
npm install -g newman newman-reporter-htmlextra
newman run collections/orders-api.json \
-e environments/staging.json \
--reporters cli,htmlextra \
--reporter-htmlextra-export reports/newman-report.html

Newman's JUnit reporter output plugs directly into most CI dashboards (Jenkins, GitHub Actions, GitLab) the same way a JUnit/TestNG XML report would from a code-first framework โ€” this is what makes Postman collections viable as an actual CI gate, not just a manual tool.


7. Mock Serversโ€‹

Postman can spin up a mock server from a collection โ€” a hosted endpoint that returns example responses saved on each request, without a real backend existing yet.

POST /orders  โ†’  saved example response: 201 { "id": 1, "status": "created" }

Use cases:

  • Frontend/consumer teams build and test against the mock while the real backend is still in development (contract-first workflow).
  • SDETs validate that a client integration handles specific response shapes/error codes without needing to force those states from a real backend (e.g., simulate a 503 or a malformed payload).

Each saved example on a request becomes a possible mock response; Postman matches incoming mock requests to the closest example by method + path (+ optional headers/query for more specific matching).


8. Postman Monitors & Scheduled Runsโ€‹

Beyond CI-triggered runs, Postman Monitors run a collection on a schedule (e.g., every 15 minutes) from Postman's cloud infrastructure or select regions โ€” used for synthetic uptime/health checks and lightweight production API monitoring, alerting on failures via email/Slack/webhook. This overlaps with, but is distinct from, CI-triggered Newman runs โ€” Monitors watch production continuously; CI runs gate deploys.


9. Organizing Larger Workspacesโ€‹

  • Folders group related requests (by resource, by user flow) and can carry their own pre-request/test scripts inherited by everything inside.
  • Variables should default to environment-scoped, promoted to collection-scoped only when truly environment-independent โ€” avoids drift where dev/staging/prod behave subtly differently because a value was hardcoded at the wrong scope.
  • Version control: export collections/environments as JSON and commit them, or use Postman's native Git integration (workspaces backed by a Git repo) so history and PR review work the same as for code.
  • Fork & merge workflow: in team workspaces, fork a collection, make changes, and open a pull request back to the source collection โ€” mirrors a git branching workflow inside the Postman UI itself.

10. Postman vs Rest Assuredโ€‹

PostmanRest Assured
NatureGUI tool + JS scriptingCode-first Java library
Best forExploratory testing, manual API poking, cross-functional collaboration (PMs, manual QA), API documentationCI-integrated regression/contract suites versioned with app code
Scripting languageJavaScript (pm.* / Chai assertions)Java (Hamcrest matchers)
CI executionRequires Newman (separate CLI step)Native โ€” it is a JUnit/TestNG test
Diffing in gitJSON collection exports โ€” noisy diffs, merge conflicts commonPlain Java source โ€” diffs cleanly
OnboardingLow barrier โ€” no coding required to write a testRequires Java/build-tool familiarity
Mock serversBuilt-inNot built-in (would use WireMock or similar)

Practical rule of thumb: reach for Postman first when exploring a new or changing API, documenting behavior for other teams, or when non-engineers need to run/inspect requests themselves. Reach for Rest Assured when the tests need to be a durable, code-reviewed, CI-gated part of the regression suite. Many teams run both side by side rather than picking one exclusively.


11. Interview-Ready Q&Aโ€‹

Q: What's the difference between a pre-request script and a test script in Postman? A: A pre-request script runs before the request is sent โ€” used to compute dynamic values like timestamps, signatures, or to refresh an auth token so it's fresh for the call about to happen. A test script (the "Tests" tab) runs after the response arrives โ€” used for assertions via pm.test() and pm.expect(), and to extract values from the response into variables that downstream requests in the same collection can use.

Q: How do you chain requests in Postman โ€” for example, using a token from a login call in every subsequent request? A: In the login request's test script, extract the token from the response JSON and store it with pm.environment.set("accessToken", token). Subsequent requests reference {{accessToken}} in their Authorization header, and Postman resolves the variable at send time. The same pattern extracts any ID or value a later request in the chain needs.

Q: What's the difference between environment variables, collection variables, and global variables, and how does Postman resolve a naming collision? A: Environment variables are scoped to whichever environment (dev/staging/ prod) is active and are the main way to swap config without touching requests. Collection variables apply across all environments for that collection โ€” for values that don't change per environment. Global variables apply across the entire Postman app and should be used sparingly since they can leak across unrelated collections. When names collide, Postman resolves the narrowest scope first โ€” local, then data, then environment, then collection, then global.

Q: How do you run a Postman collection in a CI pipeline, since Postman itself is a GUI app? A: Export the collection and environment as JSON, then run them with Newman, Postman's official CLI runner โ€” newman run collection.json -e env.json --reporters cli,junit. Newman executes requests and test scripts identically to the GUI, and its JUnit reporter output plugs into standard CI dashboards the same way a JUnit XML report from a code-first framework would.

Q: What are Postman mock servers useful for, and how do they work? A: A mock server is generated from a collection and returns saved example responses for matching requests, without needing a real backend running. It's useful for frontend/consumer teams to build against an API contract before the backend exists, and for testers to force specific response scenarios (error codes, edge-case payloads) that would be hard to trigger from a real backend on demand. Postman matches incoming requests to the closest saved example by method, path, and optionally headers/query.

Q: When would you use Postman instead of a code-first tool like Rest Assured, and when would you avoid it? A: Postman is the right tool for exploratory testing of a new or evolving API, quick manual verification, and collaborating with non-engineers who want a UI rather than code โ€” it has a much lower barrier to entry. Avoid it as the primary CI regression suite when you want tests reviewed as first-class code with clean git diffs, strong typing, and no extra Newman step โ€” that's where a library like Rest Assured fits better. In practice many teams use Postman for exploration/documentation and Rest Assured (or similar) for the durable automated suite.

Q: A test that reads a variable set in an earlier request is getting an undefined/stale value. What's your debugging approach? A: First check variable scope โ€” confirm the earlier request actually set it at the scope you expect (pm.environment.set vs pm.collectionVariables.set vs a pm.globals.set from an old leftover script) and that the reading request is checking the same scope, since Postman resolves narrowest-scope- first and a stale global or collection variable can silently shadow the one you expect. Second, confirm execution order โ€” in the Collection Runner, requests run top-to-bottom by default unless postman.setNextRequest() reordered them, so the "earlier" request may not have actually run yet.

Q: How would you data-drive a Postman test โ€” for example, running the same request with 20 different input payloads? A: Use the Collection Runner (or Newman with -d) with a CSV or JSON data file โ€” one row per iteration. Each column becomes a variable accessible via pm.iterationData.get("columnName") in scripts, and the runner executes the collection once per row, so assertions can reference expected values per row (e.g., expected status code) directly from the data file instead of hardcoding them in the script.


Practical exercises
  1. Save this as server.js and run node server.js. It listens on port 4010; if that port is busy, choose another and change it everywhere. (If a request unexpectedly returns 404 with an HTML body, some other program is answering on your port.)

    const http = require('http');

    const orders = {};
    let next = 1;

    http.createServer((req, res) => {
    let body = '';
    req.on('data', chunk => (body += chunk));
    req.on('end', () => {
    res.setHeader('Content-Type', 'application/json');
    const json = body ? JSON.parse(body) : {};

    if (req.method === 'POST' && req.url === '/orders') {
    const id = next++;
    orders[id] = json;
    res.statusCode = 201;
    return res.end(JSON.stringify({ id, ...json }));
    }

    const m = req.url.match(/^\/orders\/(\d+)$/);
    if (req.method === 'GET' && m && orders[m[1]]) {
    return res.end(JSON.stringify({ id: Number(m[1]), ...orders[m[1]] }));
    }

    if (req.method === 'POST' && req.url === '/login') {
    if (!json.username) { res.statusCode = 400; return res.end('{}'); }
    if (json.password !== 'correctpass') { res.statusCode = 401; return res.end('{}'); }
    return res.end(JSON.stringify({ token: 'abc' }));
    }

    res.statusCode = 404;
    res.end('{}');
    });
    }).listen(4010, () => console.log('listening on 4010'));

    In Postman, create a collection with two requests. First POST http://localhost:4010/orders with the body {"item":"Widget"}, whose Tests tab checks for status 201 and stores the returned id in a collection variable called orderId. Second GET http://localhost:4010/orders/{{orderId}}, whose test checks for status 200 and that the returned id equals the stored one. Export the collection and run it:

    npx newman run Orders.postman_collection.json

    Done when: Newman reports 2 requests and 2 assertions with 0 failed, and the second request URL was filled in as /orders/1 by the value your first request stored.

    Stretch: Move the JSON content-type header into a collection-level setting instead of repeating it on each request.

  2. Use the same server. Create a collection with one request, POST http://localhost:4010/login, with the body {"username":"{{username}}","password":"{{password}}"} and one test: the status must equal the expected status from the current data row, read with pm.iterationData.get("expectedStatus") and converted with Number(...). Save this as data.csv:

    username,password,expectedStatus
    validuser,correctpass,200
    validuser,wrongpass,401
    ,correctpass,400
    npx newman run Login.postman_collection.json -d data.csv

    Done when: Newman reports 3 iterations and 3 assertions with 0 failed. Then change one expectedStatus to a wrong value and confirm the run reports exactly 1 failed assertion.

The token refresh pasted into forty requests
Context

Illustrative scenario. A collection grows to about forty requests, and each one carries its own copy of the code that refreshes the auth token before sending.

What happened

When the token endpoint changed, someone updated most of the copies but missed a few. The stale ones failed with confusing 401 errors that depended on which requests happened to run first, and the team lost time working out which copy was out of date.

Lesson

Put shared logic such as token refresh in a collection-level or folder-level pre-request script so it runs before every request from one place. Keep credentials as secret-type variables so they are masked and left out of exports.

Use this with AI
  • Ask an assistant to write pm.test assertions for a sample JSON response, then run them against the real response and delete any assertion that only passes because it is too loose.
  • Have it turn a list of edge cases into a CSV for the Collection Runner, and check that each row's expected status matches how the API really behaves, not how the assistant assumed it would.
  • Ask it to review a collection for secrets committed in plain variables or scripts, and confirm each finding before moving anything.

12. One-Line Summaryโ€‹

Postman turns API exploration into a shareable, scriptable workflow โ€” collections plus pm.* pre-request/test scripts for chaining and assertions โ€” and becomes CI-capable the moment you hand that same collection to Newman.