The pm Object: Your Script's Entry Point
pm is the single global object exposed inside Postman's sandbox in both the Pre-request Script and Tests tabs. It's the one namespace that bundles everything a script needs: the outgoing request (pm.request), the received response in test scripts (pm.response), every variable scope, and the assertion helpers behind pm.test() and pm.expect().
Cricket analogy: Like the match referee's rulebook that's the single reference point covering pitch conditions, player conduct, and the scorecard — everything a match official needs is under one authority.
pm.request — Reading and Modifying the Outgoing Request
pm.request exposes the request that's about to be (or was just) sent: pm.request.url, pm.request.method, pm.request.headers (readable and writable via methods like .upsert() and .add()), and pm.request.body. In a pre-request script you can still mutate these values before the request leaves Postman; in a test script, pm.request reflects exactly what was actually sent.
Cricket analogy: Like a captain still being able to adjust the batting order right up until the toss result is confirmed, after which it's locked in for that innings.
pm.response — Inspecting What Came Back
pm.response only exists in the Tests tab, since there's nothing to inspect during a pre-request script — no response has arrived yet. Once it does, pm.response.code, .status, .responseTime, .headers, and the parsing helpers .json() and .text() give you everything needed to assert on what the API actually returned.
Cricket analogy: Like reviewing the ball-by-ball outcome, the exact speed gun reading, and the umpire's signal only after the delivery has actually been bowled and the outcome is known.
// Pre-request Script
const token = pm.collectionVariables.get('authToken');
pm.request.headers.upsert({ key: 'Authorization', value: `Bearer ${token}` });
// Tests tab
pm.test('Status is 200', () => {
pm.response.to.have.status(200);
});
pm.test('Response time under 800ms', () => {
pm.expect(pm.response.responseTime).to.be.below(800);
});
const body = pm.response.json();
pm.test('Body contains expected user id', () => {
pm.expect(body).to.have.property('id');
});pm.environment, pm.collectionVariables, pm.globals, and pm.variables (local) are four separate variable scopes. When the same variable name exists in more than one, Postman resolves {{name}} using this precedence: local > data > environment > collection > global.
Variable Scopes: environment, collectionVariables, globals, variables
Because the same variable name can exist in several scopes at once, Postman needs a deterministic rule for which value wins when resolving {{name}}: local script variables take priority, then Runner iteration data, then the active environment, then collection variables, then globals. Understanding this precedence matters most when debugging why a request resolved to an unexpected value despite the variable looking correct in one particular scope.
Cricket analogy: Like a team selection hierarchy where a player's form in the current match overrides their season average, which itself overrides their career average when picking today's XI.
pm.environment.set() only writes into whichever environment is currently active in the top-right environment selector. If no environment is selected, the set call won't make the value resolve as expected anywhere. pm.collectionVariables.set() is a safer default since it doesn't depend on an environment being selected.
- pm is the single global object exposed in both the Pre-request Script and Tests tabs inside Postman's sandbox.
- pm.request exposes the outgoing request's url, method, headers, and body, and is available (and mutable) in pre-request scripts.
- pm.response exposes code, status, responseTime, headers, and body via .json()/.text() — but only exists in the Tests tab, since there's no response yet during pre-request.
- pm.environment, pm.collectionVariables, pm.globals, and pm.variables are four distinct variable scopes with different lifetimes.
- When the same variable name exists in multiple scopes, Postman resolves it using precedence: local > data > environment > collection > global.
- pm.environment.set only writes to the currently active environment — if none is selected, values won't resolve as expected, so pm.collectionVariables is a safer default scope.
Practice what you learned
1. In which script tabs is the pm object available?
2. Why is pm.response not usable inside a Pre-request Script?
3. Which method on pm.request.headers would you use to add or overwrite a header before sending?
4. What is the correct variable scope precedence Postman uses when resolving {{name}} if it exists in multiple scopes?
5. What happens if you call pm.environment.set('token', 'abc123') but no environment is currently selected in Postman?
Was this page helpful?
You May Also Like
Pre-request Scripts
How to run JavaScript before a Postman request is sent, to set variables, compute signatures, and build dynamic request data.
Test Scripts Basics with pm.test()
How to write assertions in Postman's Tests tab using pm.test() and pm.expect() to automatically validate API responses.
Chaining Requests with Extracted Data
How to pass data from one Postman request's response into the next request by extracting values in a test script and storing them as variables.
Dynamic Variables and Faker Data
How to use Postman's built-in dynamic variables like {{$guid}} and {{$randomEmail}} to generate realistic fake data on every request.