Advanced Scripting
One request that checks itself is a test; several requests that cooperate are a workflow. This chapter adds the scripting techniques that turn a pile of requests into realistic end-to-end scenarios: pre-request scripts, passing data between requests, dynamic test data, schema validation, and shared logic at folder and collection level.
Pre-request Scripts
Everything in Scripts → Pre-request runs before the request is sent — the natural home for setup: computing a timestamp, generating a signature, fetching a fresh token, or logging state for debugging.
// Give every run a unique correlation id
pm.environment.set("runId", pm.variables.replaceIn("{{$guid}}"));
// Log what we're about to do (appears in the Postman Console)
console.log("Creating user with runId", pm.environment.get("runId"));
The Postman Console (footer, or View → Show Postman Console) is your debugger: it shows every request as actually sent — resolved variables, final headers — plus everything you console.log. When a variable "mysteriously" doesn't resolve, the Console ends the mystery in seconds.
Chaining Requests: the Create-then-Verify Pattern
Real scenarios span requests: create a resource, capture its ID, then read, update, and delete it. The bridge is a variable set in one request's post-response script and used in the next request's URL.
In the POST /users post-response script:
pm.test("User created", () => pm.response.to.have.status(201));
const created = pm.response.json();
pm.collectionVariables.set("newUserId", created.id);
The next request's URL becomes {{baseUrl}}/users/{{newUserId}}, with its own tests:
pm.test("Created user is retrievable", () => {
pm.response.to.have.status(200);
pm.expect(pm.response.json().id)
.to.eql(pm.collectionVariables.get("newUserId"));
});
Run the collection (Chapter 10) and the whole life cycle executes in order — a genuine integration test.
Controlling the flow: by default the runner executes requests top to bottom. Scripts can redirect it:
// Jump to a named request
pm.execution.setNextRequest("Delete user");
// Or stop the run entirely
pm.execution.setNextRequest(null);
(The older postman.setNextRequest(...) still works; pm.execution.setNextRequest is the current API.) Use flow control sparingly — a suite that jumps around is hard to read — but it is invaluable for skip-on-failure logic and polling loops.
Dynamic Test Data
Postman bundles the Faker library as dynamic variables, resolvable anywhere with {{$...}}:
{{$guid}}— a unique identifier{{$timestamp}}— current Unix time{{$randomEmail}},{{$randomFullName}},{{$randomInt}}— realistic random data
A POST body like {"email": "{{$randomEmail}}"} gives every run fresh, collision-free data — which is what lets the same suite run repeatedly against a persistent staging database without tripping over its own leftovers.
Best practice: tests that create data should delete it. A teardown request at the end of a workflow folder keeps staging clean and keeps your suite re-runnable — the cardinal virtue of automation.
Schema Validation: Contract Testing in Ten Lines
Field-by-field assertions catch value bugs; schema validation catches structural drift — a renamed field, a number that became a string, a missing property — which is exactly what breaks API consumers. Postman ships the ajv JSON-schema validator via Chai's jsonSchema matcher:
const userSchema = {
type: "object",
required: ["id", "name", "email"],
properties: {
id: { type: "integer" },
name: { type: "string" },
email: { type: "string", pattern: "@" }
}
};
pm.test("Response matches the user schema", () => {
pm.expect(pm.response.json()[0]).to.be.jsonSchema(userSchema);
});
Store shared schemas in a collection variable (as a JSON string) and JSON.parse them in tests, and every endpoint returning a user validates against the same contract.
Sharing Logic: Collection and Folder Scripts
Scripts don't only belong to requests. A collection-level post-response script runs after every request in the collection — the perfect home for universal assertions:
pm.test("No server errors", () => {
pm.expect(pm.response.code).to.be.below(500);
});
Folder-level scripts do the same for a folder's requests. Execution order is collection → folder → request for pre-request scripts, and the same order again for post-response scripts. Shared assertions written once at the top level are the single cheapest coverage upgrade available in Postman.
Your toolbox is now complete. The remaining question — the most important one — is what to point it at.